[spring] Spring Boot-실행중인 포트를 얻는 방법

스프링 부트 애플리케이션 (임베디드 tomcat 7 사용) 이 있으며 임의의 포트를 가질 수 있도록 설정 server.port = 0했습니다 application.properties. 서버가 부팅되고 포트에서 실행 된 후 선택한 포트를 가져올 수 있어야합니다.

@Value("$server.port")제로라서 사용할 수 없습니다 . 이것은 겉보기에 간단한 정보이므로 Java 코드에서 액세스 할 수없는 이유는 무엇입니까? 어떻게 액세스 할 수 있습니까?



답변

다음과 같은 방법으로 관리 포트에 액세스 할 수도 있습니까?

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

    @LocalServerPort
    int randomServerPort;

    @LocalManagementPort
    int randomManagementPort;


답변

Spring의 환경은이 정보를 보유하고 있습니다.

@Autowired
Environment environment;

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

표면적으로 이것은 주석이 달린 @Value("${local.server.port}")(또는 @LocalServerPort동일한) 필드를 삽입하는 것과 동일 해 보이며 컨텍스트가 완전히 초기화 될 때까지 값을 사용할 수 없기 때문에 시작시 자동 연결 실패가 발생합니다. 여기서 차이점은이 호출이 응용 프로그램 시작시 호출되지 않고 런타임 비즈니스 논리에서 암시 적으로 수행되므로 포트의 ‘지연 가져 오기’가 정상적으로 해결된다는 것입니다.


답변

저를 올바른 방향으로 안내 해준 @Dirk Lachowski에게 감사드립니다. 솔루션은 내가 원했던 것만 큼 우아하지는 않지만 제대로 작동했습니다. 스프링 문서를 읽으면서 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();
      }
    }


답변

저와 같이 앱을 구성한 다른 사람들이 제가 겪은 일로부터 혜택을 얻도록 …

위의 솔루션 중 어느 것도 ./config내 프로젝트 기반 바로 아래에 2 개의 파일 이있는 디렉토리 가 있기 때문에 효과가 없었습니다 .

application.properties
application-dev.properties

In application.propertiesI have :

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

에서 application-dev.propertiesI 있습니다 :

server_host = localhost
server_port = 8080

이것은 CLI에서 내 fat jar를 실행할 때 *.properties파일이 ./configdir 에서 읽히고 모든 것이 좋습니다.

음, 이러한 속성 파일 은 내 Spock 사양 의 webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT설정을 완전히 무시하는 것으로 나타났습니다 @SpringBootTest. 내가 무엇을 시도 했든간에 Spring 으로 webEnvironment설정 하더라도 RANDOM_PORT항상 포트 8080 (또는 내 ./config/*.properties파일에 설정 한 값)에서 포함 된 Tomcat 컨테이너를 시작합니다 .

내가 이것을 극복 할 수 있는 유일한 방법 은 내 Spock 통합 사양 properties = "server_port=0"@SpringBootTest주석에 명시 적을 추가하는 것입니다 .

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

그런 다음 Spring은 마침내 임의의 포트에서 Tomcat을 스핀 업하기 시작했습니다. IMHO 이것은 Spring 테스트 프레임 워크 버그이지만 그들 자신의 의견을 가질 것이라고 확신합니다.

이것이 누군가를 도왔기를 바랍니다.


답변

다음과 같이 local.server.port 값을 삽입하여 테스트 중에 포함 된 Tomcat 인스턴스에서 사용중인 포트를 가져올 수 있습니다.

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


답변

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;

  // ...
}


답변

이 솔루션 중 어느 것도 나를 위해 일하지 않았습니다. Swagger 구성 빈을 구성하는 동안 서버 포트를 알아야했습니다. 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         
    }
}

이 예제는 Spring Boot 자동 구성 및 JAX-RS (Spring MVC 아님)를 사용합니다.