SpringBoot动态获取项目部署的端口号
参考:通过Spring boot编码获取当前程序运行的host和端口号_不当初-CSDN博客
这里总共涉及,两种不同启动方式下的获取方法,
分别是Springboot以内置的tomcat启动和以外部tomcat方式启动
第一种,当Springboot以内置的tomcat启动的时候,直接采用Spring提供的ApplicationListener接口来监听项目的启动,在启动的时候获取到项目的端口号即可。
1)代码如下:
import lombok.Getter;
import org.springframework.boot.web.context.WebServerInitializedEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
/**
* @className: ServerConfig
* @author: wang
* @date: 2021/12/7
**/
@Getter
@Component
public class ServerConfig implements ApplicationListener<WebServerInitializedEvent> {
private Integer port;
@Override
public void onApplicationEvent(WebServerInitializedEvent webServerInitializedEvent) {
this.port = webServerInitializedEvent.getWebServer().getPort();
}
}
这个代码记得加上@Component或者@Configuration等注解。
使用的时候,需要用注解的方式装配对象,new实例出来的会报错
这种方式获取到的端口号,其实就是写在application配置文件中的端口号。与其这样获取,不如直接使用@Value注解去配置文件中获取。
如果要想拿到tomcat的端口号
可以采用下面这种方式,但这种方式拿到的都是内置tomcat的端口号,默认都是8080,意义不大
package com.piesat.config;
import lombok.Data;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
/**
* @className: WebServerConfig
* @author: wang
* @date: 2021/12/7
**/
@Component
@Data
public class TomcatServerConfig {
private static final Logger logger = LoggerFactory.getLogger(TomcatServerConfig.class);
private Integer serverPort;
@Bean
public WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> webServerFactoryCustomizer() {
return factory -> {
int serverPort = factory.getWebServer().getPort();
TomcatServerConfigHolder.webServerConfig.setServerPort(serverPort);
logger.error(">>>>>>>>>>>>>>>>>>port:[{}]<<<<<<<<<<<<<<<<<<", serverPort);
};
}
private TomcatServerConfig() {
}
private static class TomcatServerConfigHolder {
private static final TomcatServerConfig webServerConfig = new TomcatServerConfig();
}
public static TomcatServerConfig getInstance() {
return TomcatServerConfigHolder.webServerConfig;
}
}
2)如果不想使用注解的方式,可以采用静态内部类的方式(对应图一)。
import lombok.Data;
import org.springframework.boot.web.context.WebServerInitializedEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
/**
* @className: ServerConfig
* @author: wang
* @date: 2021/12/7
**/
@Component
@Data
public class ServerConfig implements ApplicationListener<WebServerInitializedEvent> {
private Integer serverPort;
@Override
public void onApplicationEvent(WebServerInitializedEvent webServerInitializedEvent) {
int port = webServerInitializedEvent.getWebServer().getPort();
ServerConfigHolder.serverConfig.setServerPort(port);
}
private ServerConfig() {
}
private static class ServerConfigHolder {
private static final ServerConfig serverConfig = new ServerConfig();
}
public static ServerConfig getInstance() {
return ServerConfigHolder.serverConfig;
}
}
使用的方法如下,效果一样
上面这种写法,只适合springboot2.0之后,1.+没有WebServerInitializedEvent类,需要换成EmbeddedServletContainerInitializedEvent类
因为2.0之后,Springboot就将EmbeddedServletContainerInitializedEvent 给修改成WebServerInitializedEvent了
简单的示例如下,也可以修改成上面静态内部类的方式
import org.springframework.boot.context.embedded.EmbeddedServletContainerInitializedEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
/**
* @className: ServerConfig
* @date: 2021/12/7
* spring boot 1.5.X
**/
@Component
public class ServerConfig implements ApplicationListener<EmbeddedServletContainerInitializedEvent> {
private Integer port;
@Override
public void onApplicationEvent(EmbeddedServletContainerInitializedEvent event) {
this.port = event.getEmbeddedServletContainer().getPort();
}
public Integer getPort(){
return port;
}
}
第二种、当Springboot,打成War包,放到外部tomcat中部署的时候,就需要剔除内置的tomcat容器,此时Springboot的启动流程就和上面不一样,好像就不再有初始化WebServer的步骤了,详细步骤需要看下源码。
这个时候,项目的端口就取决于外部的tomcat配置文件是如何配置的了。
代码如下:
import javax.management.*;
import java.lang.management.ManagementFactory;
import java.util.Set;
/**
* @className: TomcatPortConfig
* @author: wang
* @date: 2021/12/7
**/
public class TomcatPortConfig {
public static String getPort() {
MBeanServer beanServer = ManagementFactory.getPlatformMBeanServer();
try {
QueryExp protocol = Query.match(Query.attr("protocol"), Query.value("HTTP/1.1"));
ObjectName name = new ObjectName("*:type=Connector,*");
Set<ObjectName> objectNames = beanServer.queryNames(name, protocol);
for (ObjectName objectName : objectNames) {
String catalina = objectName.getDomain();
if ("Catalina".equals(catalina)) {
return objectName.getKeyProperty("port");
}
}
} catch (MalformedObjectNameException e) {
e.printStackTrace();
}
return null;
}
}
这两种方式,第一个适用于采用java -jar ***.jar的方式部署的,第二种适合,采用打成War包,部署到tomcat中进行启动的。方法不能搞反,否则都报空指针异常