配置Spring Boot使用两个端口

30
我正在尝试在Spring Boot中配置一个应用程序,使用两个不同的端口,但我还没有成功。 我的第一次尝试是使用两个控制器,并在两个控制器中定义了一个@Bean,其中包含container.setPort(8080); 我的第二次尝试是添加了actuator依赖,并更改了管理端口,但我的应用程序无法运行。它显示:
Address already in use: bind 

如何配置一个具有两个端口的应用程序?我想要一个端口用于管理员,另一个端口用于访问我的API。

2
你考虑过以下哪个回答是“答案”?有机会的话,能标记一下吗?请点击此评论旁边的旗帜并将其标记为删除。谢谢。 - PatS
5个回答

35
正如之前提到的,可以设置server.portmanagement.port以及management.context-path属性来使嵌入式容器监听不同的端口(管理相关属性用于访问Actuator端点)。
要监听除server.portmanagement.port之外的其他端口:
@Configuration
public class EmbeddedTomcatConfiguration {

    @Value("${server.additionalPorts}")
    private String additionalPorts;

    @Bean
    public EmbeddedServletContainerFactory servletContainer() {
        TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory();
        Connector[] additionalConnectors = this.additionalConnector();
        if (additionalConnectors != null && additionalConnectors.length > 0) {
            tomcat.addAdditionalTomcatConnectors(additionalConnectors);
        }
        return tomcat;
    }

    private Connector[] additionalConnector() {
        if (StringUtils.isBlank(this.additionalPorts)) {
            return null;
        }
        String[] ports = this.additionalPorts.split(",");
        List<Connector> result = new ArrayList<>();
        for (String port : ports) {
            Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
            connector.setScheme("http");
            connector.setPort(Integer.valueOf(port));
            result.add(connector);
        }
        return result.toArray(new Connector[] {});
    }
}

application.yml

server:
  port: ${appPort:8800}
  additionalPorts: 8881,8882

Application.java

@SpringBootApplication
@ComponentScan(...)
@Import(EmbeddedTomcatConfiguration.class)
public Application {

    public static void main(String[] args) {
        SpringApplication.run(Application .class, args);
    }
}

我最近在博客中讨论了这个话题:


4
作为补充,有Spring Boot 2.0的修改 - https://dev59.com/DFYN5IYBdhLWcg3wXnJa?rq=1 - Betlista
3
你现在如何区分: localhost:port1 -> 为管理员提供主页服务 localhost:port2 -> 为其他人提供主页服务 - obey

8

从Springboot 2开始,ootero解决方案中提到的EmbeddedServletContainerFactory已不再可用,因此您应根据您的上下文使用TomcatServletWebServerFactoryTomcatReactiveWebServerFactory

除了工厂注入之外,解决方案保持不变:

@Bean
public TomcatServletWebServerFactory servletContainer() {
    TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();
    Connector[] additionalConnectors = this.additionalConnector();
    if (additionalConnectors != null && additionalConnectors.length > 0) {
        tomcat.addAdditionalTomcatConnectors(additionalConnectors);
    }
    return tomcat;
}

4

要更改Actuator管理端口,您可以使用属性

management.port=8081

完整的属性列表请在此处查看。

更新: 在这种情况下,Actuator会创建一个额外的嵌入式Tomcat(servlet容器)实例。 详见此处此处


是的,我知道,但是能否这样做:management.port = 8081和server.port = 8080?并在同一应用程序中使用两个不同的端口? - nole
服务器端口默认为8080。2个不同的端口意味着2个不同的套接字监听不同的端口。 - Dennis R
谢谢,我知道这是可能的,但我们不希望将我们的管理应用程序放在执行器端口上,我们需要一个不同的端口。 - nole

1
要在一个项目内运行2个或更多应用程序或更改默认端口,您可以执行以下操作。
@SpringBootApplication
public class NewApplication {
     public static void main(String[] args) {
         SpringApplication app = new SpringApplication(NewApplication .class);
         app.setDefaultProperties(Collections.singletonMap("server.port", "8083"));
         app.run(args);
     }
}

0
如果只需要打开一个额外的端口,以下代码就足够了(Kotlin):
@Configuration
class AdditionalEndpointConfig {

    @Bean
    @ConditionalOnProperty(PORT_PROPERTY)
    fun tomcatServletWebServerFactory(@Value("\${$PORT_PROPERTY}") additionalPort: Int) =
        TomcatServletWebServerFactory().apply {
            addAdditionalTomcatConnectors(
                Connector("org.apache.coyote.http11.Http11NioProtocol").apply {
                    scheme = "http"
                    port = additionalPort
                })
        }

    companion object {
        const val PORT_PROPERTY = "server.additional.port"
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接