Spring Boot - 如何获取正在运行的端口

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/30312058/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 00:34:49  来源:igfitidea点击:

Spring Boot - How to get the running port

springspring-bootportembedded-tomcat-7

提问by Tucker

I have a spring boot application (using embedded tomcat 7), and I've set server.port = 0in my application.propertiesso I can have a random port. After the server is booted up and running on a port, I need to be able to get the port that that was chosen.

我有一个 spring 启动应用程序(使用嵌入式 tomcat 7),并且我已经server.port = 0在我的中设置了application.properties一个随机端口。服务器启动并在某个端口上运行后,我需要能够获取所选的端口。

I cannot use @Value("$server.port")because it's zero. This is a seemingly simple piece of information, so why can't I access it from my java code? How can I access it?

我不能使用,@Value("$server.port")因为它是零。这是一条看似简单的信息,为什么我不能从我的java代码中访问它呢?我怎样才能访问它?

采纳答案by Tucker

Thanks to @Dirk Lachowski for pointing me in the right direction. The solution isn't as elegant as I would have liked, but I got it working. Reading the spring docs, I can listen on the EmbeddedServletContainerInitializedEvent and get the port once the server is up and running. Here's what it looks like -

感谢@Dirk Lachowski 为我指明了正确的方向。该解决方案并不像我希望的那样优雅,但我让它起作用了。阅读 spring 文档,我可以监听 EmbeddedServletContainerInitializedEvent 并在服务器启动并运行后获取端口。这是它的样子 -

import org.springframework.boot.context.embedded.EmbeddedServletContainerInitializedEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;




    @Component
    public class MyListener implements ApplicationListener<EmbeddedServletContainerInitializedEvent> {

      @Override
      public void onApplicationEvent(final EmbeddedServletContainerInitializedEvent event) {
          int thePort = event.getEmbeddedServletContainer().getPort();
      }
    }

回答by LaughingLemon

Is it also possible to access the management port in a similar way, e.g.:

是否也可以以类似的方式访问管理端口,例如:

  @SpringBootTest(classes = {Application.class}, webEnvironment = WebEnvironment.RANDOM_PORT)
  public class MyTest {

    @LocalServerPort
    int randomServerPort;

    @LocalManagementPort
    int randomManagementPort;

回答by hennr

Spring's Environment holds this information for you.

Spring 的 Environment 为您保存了这些信息。

@Autowired
Environment environment;

String port = environment.getProperty("local.server.port");

On the surface this looks identical to injecting a field annotated @Value("${local.server.port}")(or @LocalServerPort, which is identical), whereby an autowiring failure is thrown at startup as the value isn't available until the context is fully initialised. The difference here is that this call is implicitly being made in runtime business logic rather than invoked at application startup, and hence the 'lazy-fetch' of the port resolves ok.

从表面上看,这看起来与注入带注释的字段@Value("${local.server.port}")(或@LocalServerPort,相同)相同,即在启动时抛出自动装配失败,因为该值在上下文完全初始化之前不可用。这里的区别在于这个调用是在运行时业务逻辑中隐式进行的,而不是在应用程序启动时调用,因此端口的“延迟获取”解析正常。

回答by Jacomoman

Just so others who have configured their apps like mine benefit from what I went through...

只是让其他像我这样配置了他们的应用程序的人从我的经历中受益......

None of the above solutions worked for me because I have a ./configdirectory just under my project base with 2 files:

application.properties
application-dev.properties

In application.propertiesI have:

上述解决方案都不适合我,因为./config我的项目库下有一个目录,其中包含 2 个文件:

application.properties
application-dev.properties

application.properties我有:

spring.profiles.active = dev  # set my default profile to 'dev'

In application-dev.propertiesI have:

application-dev.properties我有:

server_host = localhost
server_port = 8080

This is so when I run my fat jar from the CLI the *.propertiesfiles will be read from the ./configdir and all is good.

因此,当我从 CLI 运行我的胖 jar 时,*.properties将从./config目录中读取文件并且一切正常。

Well, it turns out that these properties files completely override the webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORTsetting in @SpringBootTestin my Spock specs. No matter what I tried, even with webEnvironmentset to RANDOM_PORTSpring would always startup the embedded Tomcat container on port 8080 (or whatever value I'd set in my ./config/*.propertiesfiles).

好吧,事实证明这些属性文件完全覆盖了我的 Spock 规范中的webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT设置 @SpringBootTest。无论我尝试什么,即使webEnvironment设置为RANDOM_PORTSpring 也会始终在端口 8080(或我在./config/*.properties文件中设置的任何值)上启动嵌入式 Tomcat 容器。

The ONLYway I was able to overcome this was by adding an explicit properties = "server_port=0"to the @SpringBootTestannotation in my Spock integration specs:

我能够克服这个问题的唯一方法是在我的 Spock 集成规范中添加一个显式properties = "server_port=0"@SpringBootTest注释:

@SpringBootTest (webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, properties = "server_port=0")

Then, and only then did Spring finally start to spin up Tomcat on a random port. IMHO this is a Spring testing framework bug, but I'm sure they'll have their own opinion on this.

然后,直到那时,Spring 才终于开始在一个随机端口上启动 Tomcat。恕我直言,这是一个 Spring 测试框架错误,但我相信他们对此会有自己的看法。

Hope this helped someone.

希望这对某人有所帮助。

回答by bsyk

You can get the port that is being used by an embedded Tomcat instance during tests by injecting the local.server.port value as such:

您可以通过注入 local.server.port 值来获取测试期间嵌入式 Tomcat 实例正在使用的端口:

// Inject which port we were assigned
@Value("${local.server.port}")
int port;

回答by jabal

Starting with Spring Boot 1.4.0 you can use this in your test:

从 Spring Boot 1.4.0 开始,您可以在测试中使用它:

import org.springframework.boot.context.embedded.LocalServerPort;

@SpringBootTest(classes = {Application.class}, webEnvironment = WebEnvironment.RANDOM_PORT)
public class MyTest {

  @LocalServerPort
  int randomPort;

  // ...
}

回答by mre

None of these solutions worked for me. I needed to know the server port while constructing a Swagger configuration bean. Using ServerPropertiesworked for me:

这些解决方案都不适合我。在构建 Swagger 配置 bean 时,我需要知道服务器端口。使用ServerProperties对我有用

import javax.annotation.PostConstruct;
import javax.inject.Inject;
import javax.ws.rs.ApplicationPath;

import io.swagger.jaxrs.config.BeanConfig;
import io.swagger.jaxrs.listing.ApiListingResource;
import io.swagger.jaxrs.listing.SwaggerSerializers;

import org.glassfish.jersey.server.ResourceConfig;
import org.springframework.stereotype.Component;

@Component
@ApplicationPath("api")
public class JerseyConfig extends ResourceConfig 
{
    @Inject
    private org.springframework.boot.autoconfigure.web.ServerProperties serverProperties;

    public JerseyConfig() 
    {
        property(org.glassfish.jersey.server.ServerProperties.BV_SEND_ERROR_IN_RESPONSE, true);
    }

    @PostConstruct
    protected void postConstruct()
    {
        // register application endpoints
        registerAndConfigureSwaggerUi();
    }

    private void registerAndConfigureSwaggerUi()
    {
        register(ApiListingResource.class);
        register(SwaggerSerializers.class);

        final BeanConfig config = new BeanConfig();
        // set other properties
        config.setHost("localhost:" + serverProperties.getPort()); // gets server.port from application.properties file         
    }
}

This example uses Spring Boot auto configuration and JAX-RS (not Spring MVC).

此示例使用 Spring Boot 自动配置和 JAX-RS(不是 Spring MVC)。

回答by Ahmed

Please make sure you have imported the correct package

请确保您导入了正确的包

import org.springframework.core.env.Environment;

and then use the Environment object

然后使用 Environment 对象

@Autowired
private Environment env;    // Environment Object containts the port number

 @GetMapping("/status")
  public String status()
    {
   return "it is runing on"+(env.getProperty("local.server.port"));
    }