2015-05-18 15 views
23

Ho un'applicazione di avvio a molla (utilizzando tomcat incorporato 7) e ho impostato server.port = 0 nel mio application.properties in modo che possa avere una porta casuale. Dopo che il server è stato avviato e in esecuzione su una porta, ho bisogno di essere in grado di ottenere la porta che è stata scelta.Spring Boot - Come ottenere la porta in esecuzione

Non riesco a utilizzare @Value("$server.port") perché è zero. Questa è un'informazione apparentemente semplice, quindi perché non posso accedervi dal mio codice java? Come posso accedervi?

+0

Correlato: http://stackoverflow.com/a/24643484/1686330 –

+0

Un'altra possibilità può essere trovata nei documenti: http://docs.spring.io/spring-boot/docs/current/reference/html/ howto-embedded-servlet-containers.html (vedi 64.5 Scopri la porta HTTP in fase di esecuzione) –

+0

Grazie, ma ho letto quei siti ma non mi danno la risposta - o non funzionano, sembrano troppo complicata per essere la migliore risposta o non è applicabile. Non sto facendo test unitari. Voglio semplicemente ottenere la porta che il server è stato avviato in modo programmatico. questo dovrebbe essere facile, ma non riesco a trovare la risposta :( – Tucker

risposta

14

Grazie a @Dirk Lachowski per avermi indicato nella giusta direzione. La soluzione non è elegante come avrei voluto, ma l'ho fatta funzionare. Leggendo i documenti di primavera, posso ascoltare EmbeddedServletContainerInitializedEvent e ottenere la porta una volta che il server è attivo e funzionante. Ecco come si presenta -

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(); 
     } 
    } 
+0

AFAIK questo non funzionerà se stai cercando di configurare un bean con la porta del server. Questo evento non è sparato fino a dopo che tutti i fagioli sono stati caricati e le servlet sono state registrate. – mre

+0

ha funzionato per me al momento questo è il motivo per cui l'ho accettato.non ho ancora provato la risposta di hennr. – Tucker

+0

Anche questo non funziona. – mre

5

È possibile ottenere la porta che viene utilizzata da un'istanza di Tomcat incorporato durante i test iniettando il valore local.server.port in quanto tale:

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

'local.server.port' viene impostato solo quando è in esecuzione con' @ WebIntegrationTests' – ejain

21

Ambiente di primavera detiene queste informazioni per te.

@Autowired 
Environment environment; 

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

Sulla superficie questo sembra identico ad iniettare un campo annotato @Value("${local.server.port}") (o @LocalServerPort, che è identico), per cui un guasto autowiring viene lanciata all'avvio come il valore non è disponibile fino a quando il contesto è completamente inizializzato. La differenza qui è che questa chiamata viene implicitamente eseguita nella logica di business runtime piuttosto che invocata all'avvio dell'applicazione, e quindi il 'lazy-fetch' della porta si risolve ok.

4

Nessuna di queste soluzioni ha funzionato per me. Avevo bisogno di conoscere la porta del server durante la costruzione di un bean di configurazione Swagger. Utilizzando ServerProperties ha lavorato per me:

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   
    } 
} 

questo esempio viene utilizzata la configurazione automatica della molla di avvio e JAX-RS (non Spring MVC).

4

partire con la Primavera di avvio 1.4.0 è possibile utilizzare questo nel tuo test:

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

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

    @LocalServerPort 
    int randomPort; 

    // ... 
} 
30

E 'anche possibile accedere alla porta di gestione in modo simile, ad esempio:

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

    @LocalServerPort 
    int randomServerPort; 

    @LocalManagementPort 
    int randomManagementPort; 
2

Proprio così altri che hanno configurato le loro app come la mia traggono beneficio da quello che ho passato ...

Nessuna delle soluzioni di cui sopra ha funzionato per me perché ho una directory ./config appena sotto la mia base di progetto con 2 file:

application.properties
application-dev.properties

In application.properties ho:

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

In application-dev.properties Ho:

server_host = localhost 
server_port = 8080 

Questo è così quando eseguo il mio contenitore di grassi dalla CLI i file *.properties verranno letti dalla directory ./config e tutto va bene.

Bene, si scopre che questi file di proprietà sovrascrivono completamente l'impostazione webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT in @SpringBootTest nelle specifiche di Spock. Indipendentemente da ciò che ho provato, anche con webEnvironment impostato su RANDOM_PORT Spring avviava sempre il contenitore Tomcat incorporato sulla porta 8080 (o qualunque valore avessi impostato nei miei file ./config/*.properties).

Il SOLO modo in cui mi è stato in grado di superare questo è stato con l'aggiunta di un esplicito properties = "server_port=0" alla @SpringBootTest annotazioni nei miei Spock specifiche di integrazione:

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

Allora, e solo allora primavera finalmente iniziare a girare in su Tomcat su una porta casuale. IMHO questo è un bug del framework Spring testing, ma sono sicuro che avranno la loro opinione su questo.

Spero che questo abbia aiutato qualcuno.

Problemi correlati