web-dev-qa-db-ja.com

Spring Boot-実行中のポートを取得する方法

埋め込みのTomcat 7を使用したスプリングブートアプリケーションがあり、server.port = 0application.propertiesを設定したため、ランダムなポートを使用できます。サーバーを起動してポートで実行した後、選択したポートを取得できるようにする必要があります。

@Value("$server.port")はゼロなので使用できません。これは一見シンプルな情報ですが、Javaコードからアクセスできないのはなぜですか?どうすればアクセスできますか?

57
Tucker

私を正しい方向に向けてくれた@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();
      }
    }
19
Tucker

同様の方法で管理ポートにアクセスすることも可能ですか、例えば:

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

    @LocalServerPort
    int randomServerPort;

    @LocalManagementPort
    int randomManagementPort;
68
LaughingLemon

Spring's Environmentはこの情報を保持します。

@Autowired
Environment environment;

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

表面的には、これは@Value("${local.server.port}")(または@LocalServerPort、同じ)アノテーションが付けられたフィールドの注入と同じに見えます。これにより、コンテキストが完全に初期化されるまで値が利用できないため、起動時に自動配線の失敗がスローされます。ここでの違いは、この呼び出しはアプリケーションの起動時に呼び出されるのではなく、実行時のビジネスロジックで暗黙的に行われるため、ポートの「遅延フェッチ」は問題なく解決することです。

53
hennr

Local.server.port値を次のように注入することにより、テスト中に埋め込みTomcatインスタンスによって使用されているポートを取得できます。

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

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;

  // ...
}
11
jabal

私のようにアプリを設定した他の人が私が経験したことの恩恵を受けるだけです...

上記の解決策はどれもうまくいきませんでした。なぜなら、プロジェクトベースのすぐ下に2つのファイルがある./configディレクトリがあるからです。

application.properties
application-dev.properties

_application.propertiesにあるもの:

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

application-dev.propertiesにあるもの:

server_Host = localhost
server_port = 8080

これは、CLIからfat jarを実行すると、*.propertiesファイルが./config dirから読み取られ、すべてが正常に実行されるためです。

さて、これらのプロパティファイルは、Spock仕様のwebEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT@SpringBootTest設定を完全にオーバーライドすることがわかりました。 webEnvironmentRANDOM_PORTに設定されていても、Springはポート8080(または./config/*.propertiesファイルに設定した値)で常に埋め込みTomcatコンテナを起動します。

ONLY私がこれを克服できたのは、Spock統合仕様のproperties = "server_port=0"アノテーションに明示的な@SpringBootTestを追加することでした。

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

その後、SpringはついにランダムポートでTomcatを起動し始めました。私見これはSpringテストフレームワークのバグですが、彼らはこれについて自分の意見を持っていると確信しています。

これが誰かを助けることを願っています。

11
Jacomoman

これらのソリューションはどれも私にとってはうまくいきませんでした。 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         
    }
}

この例では、Spring Bootの自動構成とJAX-RS(Spring MVCではありません)を使用します。

6
mre