转载

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中进行启动的。方法不能搞反,否则都报空指针异常

正文到此结束
该篇文章的评论功能已被站长关闭