Ich habe eine Spring-Boot-Anwendung (mit Embedded Tomcat 7) und habe server.port = 0
meine application.properties
so eingestellt, dass ich einen zufälligen Port haben kann. Nachdem der Server gestartet wurde und auf einem Port ausgeführt wird, muss ich in der Lage sein, den ausgewählten Port abzurufen.
Ich kann nicht verwenden, @Value("$server.port")
weil es Null ist. Dies ist eine scheinbar einfache Information. Warum kann ich nicht über meinen Java-Code darauf zugreifen? Wie kann ich darauf zugreifen?
spring
spring-boot
port
embedded-tomcat-7
Tucker
quelle
quelle
Antworten:
Ist es auch möglich, auf ähnliche Weise auf den Verwaltungsport zuzugreifen, z.
@SpringBootTest(classes = {Application.class}, webEnvironment = WebEnvironment.RANDOM_PORT) public class MyTest { @LocalServerPort int randomServerPort; @LocalManagementPort int randomManagementPort;
quelle
@LocalServerPort
ist nur eine Abkürzung für@Value("${local.server.port}")
.Spring's Environment hält diese Informationen für Sie bereit.
@Autowired Environment environment; String port = environment.getProperty("local.server.port");
Auf den ersten Blick sieht dies identisch aus mit dem Einfügen eines mit Anmerkungen versehenen
@Value("${local.server.port}")
(oder@LocalServerPort
identischen) Felds, bei dem beim Start ein Autowire-Fehler ausgelöst wird, da der Wert erst verfügbar ist, wenn der Kontext vollständig initialisiert ist. Der Unterschied besteht darin, dass dieser Aufruf implizit in der Laufzeit-Geschäftslogik erfolgt und nicht beim Start der Anwendung aufgerufen wird. Daher wird das "Lazy-Fetch" des Ports in Ordnung aufgelöst.quelle
environment.getProperty("server.port")
funktioniert.Vielen Dank an @Dirk Lachowski, der mich in die richtige Richtung gelenkt hat. Die Lösung ist nicht so elegant, wie ich es mir gewünscht hätte, aber ich habe sie zum Laufen gebracht. Wenn ich die Frühlingsdokumente lese, kann ich das EmbeddedServletContainerInitializedEvent abhören und den Port abrufen, sobald der Server betriebsbereit ist. So sieht es aus -
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(); } }
quelle
PortProvider
und stellte einegetPort()
Methode bereit. Ich habe mich automatischPortProvider
mit dem Controller verbunden, der den Port benötigt, und als meine Geschäftslogik aufgerufen wurdeportProvider.getPort()
, wurde der Laufzeitport zurückgegeben.EmbeddedServletContainerInitializedEvent
, aber es gibt eine ähnliche KlasseServletWebServerInitializedEvent
mit einer.getWebServer()
Methode. Dadurch erhalten Sie zumindest den Port, den Tomcat abhört.Nur damit andere, die ihre Apps wie meine konfiguriert haben, von dem profitieren, was ich durchgemacht habe ...
Keine der oben genannten Lösungen hat für mich funktioniert, da ich ein
./config
Verzeichnis direkt unter meiner Projektbasis mit 2 Dateien habe:application.properties
application-dev.properties
In
application.properties
Ich habe:spring.profiles.active = dev # set my default profile to 'dev'
In habe
application-dev.properties
ich:server_host = localhost server_port = 8080
Dies ist so, wenn ich mein Fat Jar über die CLI starte, werden die
*.properties
Dateien aus dem./config
Verzeichnis gelesen und alles ist gut.Nun, es stellt sich heraus, dass diese Eigenschaftendateien die
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT
Einstellung@SpringBootTest
in meinen Spock-Spezifikationen vollständig überschreiben . Egal, was ich versucht habe, selbst wenn SpringwebEnvironment
eingestellt ist, wirdRANDOM_PORT
der eingebettete Tomcat-Container auf Port 8080 immer gestartet (oder welcher Wert auch immer ich in meinen./config/*.properties
Dateien festgelegt habe).Die einzige Möglichkeit, dies zu überwinden, bestand darin
properties = "server_port=0"
, der@SpringBootTest
Anmerkung in meinen Spock-Integrationsspezifikationen eine explizite Anmerkung hinzuzufügen :@SpringBootTest (webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, properties = "server_port=0")
Dann und erst dann fing Spring endlich an, Tomcat an einem zufälligen Port hochzufahren. IMHO ist dies ein Spring Testing Framework Bug, aber ich bin sicher, dass sie ihre eigene Meinung dazu haben werden.
Hoffe das hat jemandem geholfen.
quelle
Sie können den Port, der von einer eingebetteten Tomcat-Instanz während der Tests verwendet wird, abrufen, indem Sie den Wert local.server.port als solchen einfügen:
// Inject which port we were assigned @Value("${local.server.port}") int port;
quelle
local.server.port
wird nur eingestellt, wenn mit@WebIntegrationTests
Ab Spring Boot 1.4.0 können Sie dies in Ihrem Test verwenden:
import org.springframework.boot.context.embedded.LocalServerPort; @SpringBootTest(classes = {Application.class}, webEnvironment = WebEnvironment.RANDOM_PORT) public class MyTest { @LocalServerPort int randomPort; // ... }
quelle
Keine dieser Lösungen hat bei mir funktioniert. Ich musste den Server-Port kennen, während ich eine Swagger-Konfigurations-Bean erstellte. Die Verwendung von ServerProperties hat bei mir funktioniert:
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 } }
In diesem Beispiel werden die automatische Konfiguration von Spring Boot und JAX-RS (nicht Spring MVC) verwendet.
quelle
Nach Spring Boot 2 hat sich viel geändert. Die oben angegebenen Antworten funktionieren vor Spring Boot 2. Wenn Sie Ihre Anwendung nun mit Laufzeitargumenten für den Server-Port ausführen, erhalten Sie nur den statischen Wert mit
@Value("${server.port}")
, der in der Datei application.properties angegeben ist. Verwenden Sie nun die folgende Methode, um den tatsächlichen Port abzurufen, auf dem der Server ausgeführt wird:@Autowired private ServletWebServerApplicationContext server; @GetMapping("/server-port") public String serverPort() { return "" + server.getWebServer().getPort(); }
Wenn Sie Ihre Anwendungen als Eureka / Discovery-Clients mit Lastenausgleich
RestTemplate
oder verwendenWebClient
, gibt die oben beschriebene Methode die genaue Portnummer zurück.quelle
Sie können den Server-Port von der erhalten
@Autowired private HttpServletRequest request; @GetMapping(value = "/port") public Object getServerPort() { System.out.println("I am from " + request.getServerPort()); return "I am from " + request.getServerPort(); }
quelle
Bitte stellen Sie sicher, dass Sie das richtige Paket importiert haben
import org.springframework.core.env.Environment;
und verwenden Sie dann das Umgebungsobjekt
@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")); }
quelle
Ich habe es mit einer Art Proxy-Bean gelöst. Der Client wird bei Bedarf initialisiert. Bis dahin sollte der Port verfügbar sein:
@Component public class GraphQLClient { private ApolloClient apolloClient; private final Environment environment; public GraphQLClient(Environment environment) { this.environment = environment; } public ApolloClient getApolloClient() { if (apolloClient == null) { String port = environment.getProperty("local.server.port"); initApolloClient(port); } return apolloClient; } public synchronized void initApolloClient(String port) { this.apolloClient = ApolloClient.builder() .serverUrl("http://localhost:" + port + "/graphql") .build(); } public <D extends Operation.Data, T, V extends Operation.Variables> GraphQLCallback<T> graphql(Operation<D, T, V> operation) { GraphQLCallback<T> graphQLCallback = new GraphQLCallback<>(); if (operation instanceof Query) { Query<D, T, V> query = (Query<D, T, V>) operation; getApolloClient() .query(query) .enqueue(graphQLCallback); } else { Mutation<D, T, V> mutation = (Mutation<D, T, V>) operation; getApolloClient() .mutate(mutation) .enqueue(graphQLCallback); } return graphQLCallback; } }
quelle