world tutorial starter run hello español spring spring-boot port embedded-tomcat-7

tutorial - spring boot web



Spring Boot: cómo obtener el puerto de ejecución (7)

¿También es posible acceder al puerto de administración de manera similar, por ejemplo:

@SpringBootTest(classes = {Application.class}, webEnvironment = WebEnvironment.RANDOM_PORT) public class MyTest { @LocalServerPort int randomServerPort; @LocalManagementPort int randomManagementPort;

Tengo una aplicación de inicio de Spring (usando Tomcat 7 integrado), y configuré server.port = 0 en mi application.properties para poder tener un puerto aleatorio. Después de que el servidor se inicia y se ejecuta en un puerto, necesito poder obtener el puerto que se eligió.

No puedo usar @Value("$server.port") porque es cero. Esta es una información aparentemente simple, entonces, ¿por qué no puedo acceder a ella desde mi código Java? ¿Cómo puedo acceder?


A partir de Spring Boot 1.4.0 puede usar esto en su prueba:

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


Así que otros que han configurado sus aplicaciones como la mía se benefician de lo que pasé ...

Ninguna de las soluciones anteriores funcionó para mí porque tengo un directorio ./config justo debajo de mi base de proyecto con 2 archivos:

application.properties
application-dev.properties

En application.properties tengo:

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

En application-dev.properties tengo:

import org.springframework.boot.context.embedded.LocalServerPort; @SpringBootTest(classes = {Application.class}, webEnvironment = WebEnvironment.RANDOM_PORT) public class MyTest { @LocalServerPort int randomPort; // ... }

Esto es así cuando ejecuto mi jarra desde la CLI, los archivos *.properties se leerán desde el directorio ./config y todo estará bien.

Bueno, resulta que estos archivos de propiedades anulan por completo la webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT en @SpringBootTest en mis especificaciones de Spock. No importa lo que intenté, incluso con webEnvironment configurado en RANDOM_PORT Spring siempre iniciaría el contenedor Tomcat incorporado en el puerto 8080 (o cualquier valor que haya configurado en mis archivos ./config/*.properties ).

La ÚNICA forma en que pude superar esto fue agregando unas properties = "server_port=0" explícitas properties = "server_port=0" a la anotación @SpringBootTest en mis especificaciones de integración de Spock:

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

Entonces, y solo entonces Spring finalmente comenzó a hacer girar a Tomcat en un puerto aleatorio. En mi humilde opinión, este es un error de marco de prueba de primavera, pero estoy seguro de que tendrán su propia opinión al respecto.

Espero que esto haya ayudado a alguien.


Gracias a @Dirk Lachowski por señalarme en la dirección correcta. La solución no es tan elegante como me hubiera gustado, pero la hice funcionar. Al leer los documentos de Spring, puedo escuchar en el EmbeddedServletContainerInitializedEvent y obtener el puerto una vez que el servidor está en funcionamiento. Así es como se ve:

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


Ninguna de estas soluciones funcionó para mí. Necesitaba conocer el puerto del servidor mientras construía un bean de configuración Swagger. Usar ServerProperties funcionó para mí:

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

Este ejemplo utiliza la configuración automática de Spring Boot y JAX-RS (no Spring MVC).


Puede obtener el puerto que está utilizando una instancia de Tomcat incrustada durante las pruebas inyectando el valor local.server.port como tal:

server_host = localhost server_port = 8080


Spring''s Environment contiene esta información para usted.

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

En la superficie, esto parece idéntico a inyectar un campo anotado @Value("${local.server.port}") (o @LocalServerPort , que es idéntico), por lo que se arroja una falla de cableado automático al inicio ya que el valor no está disponible hasta que el contexto esté completamente inicializado. La diferencia aquí es que esta llamada se realiza implícitamente en la lógica de negocios en tiempo de ejecución en lugar de invocarse al inicio de la aplicación, y por lo tanto, la ''recuperación lenta'' del puerto se resuelve bien.