spring boot 可以打包成可执行jar运行(内置Tomcat),也可以打包成war包,放到tomcat的webapp文件夹下进行运行发布(外置Tomcat);根据运行的方式的不同,获取端口的方式也有差别(不是获取配置文件中配置的端口,而且Tomcat也不是根据 spring boot 的配置文件设置端口发布项目)
内置Tomcat获取端口方式:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext;
import org.springframework.context.annotation.Configuration;
/**
* @author
* @date 2024/1/26 17:56
*/
@Configuration
public class TTConfig {
@Autowired
private ServletWebServerApplicationContext appContext;
public int getPort(){
return appContext.getWebServer().getPort();
}
}
外置Tomcat获取端口方式:
import javax.management.*;
import java.lang.management.ManagementFactory;
import java.util.Set;
/**
* @author
* @date 2024/1/26 17:55
*/
public class TTUtil {
/**
* 获取外置 tomcat 启动的 http 开放端口
* 参考:https://blog.csdn.net/oNew_Lifeo/article/details/127276152
* @return
*/
private int getTomcatPort() {
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 Integer.parseInt(objectName.getKeyProperty("port"));
}
}
} catch (MalformedObjectNameException e) {
e.printStackTrace();
}
return 0;
}
}
出现这种情况的原因:
这里涉及 spring boot 启动加载Tomcat容器的机制,tomcat外置启动项目时,容器中的 webServer
为空,内置tomcat启动webServer
这个有值;
具体可以用IDEA
对下方方法加断点,debug启动可以观察到 内置tomcat启动时 servletContext
为空,外置tomcat启动时servletContext
不为空;
关键代码:org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext#createWebServer
@Override
protected void onRefresh() {
super.onRefresh();
try {
createWebServer();
}
catch (Throwable ex) {
throw new ApplicationContextException("Unable to start web server", ex);
}
}
private void createWebServer() {
WebServer webServer = this.webServer;
ServletContext servletContext = getServletContext();
if (webServer == null && servletContext == null) {
StartupStep createWebServer = this.getApplicationStartup().start("spring.boot.webserver.create");
ServletWebServerFactory factory = getWebServerFactory();
createWebServer.tag("factory", factory.getClass().toString());
this.webServer = factory.getWebServer(getSelfInitializer());
createWebServer.end();
getBeanFactory().registerSingleton("webServerGracefulShutdown",
new WebServerGracefulShutdownLifecycle(this.webServer));
getBeanFactory().registerSingleton("webServerStartStop",
new WebServerStartStopLifecycle(this, this.webServer));
}
else if (servletContext != null) {
try {
getSelfInitializer().onStartup(servletContext);
}
catch (ServletException ex) {
throw new ApplicationContextException("Cannot initialize servlet context", ex);
}
}
initPropertySources();
}
参考
1.SpringBoot获取项目ip和端口号【内置和外置获取的两种方式】
2.spring boot启动加载tomcat原理深度剖析