J'ai une application de démarrage printanière (avec Tomcat 7 intégré) et j'ai défini server.port = 0
Dans mon application.properties
Pour pouvoir utiliser un port aléatoire. Une fois le serveur démarré et fonctionnant sur un port, je dois pouvoir obtenir le port qui a été choisi.
Je ne peux pas utiliser @Value("$server.port")
parce que c'est zéro. C'est une information apparemment simple, alors pourquoi ne puis-je pas y accéder à partir de mon code Java? Comment puis-je y accéder?)
Merci à @Dirk Lachowski de m'avoir orienté dans la bonne direction. La solution n'est pas aussi élégante que je l'aurais souhaité, mais je la fais fonctionner. En lisant la documentation print, je peux écouter sur EmbeddedServletContainerInitializedEvent et obtenir le port une fois le serveur opérationnel. Voici à quoi ça ressemble -
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();
}
}
Est-il également possible d’accéder au port de gestion de la même manière, par exemple:
@SpringBootTest(classes = {Application.class}, webEnvironment = WebEnvironment.RANDOM_PORT)
public class MyTest {
@LocalServerPort
int randomServerPort;
@LocalManagementPort
int randomManagementPort;
Spring's Environment détient ces informations pour vous.
@Autowired
Environment environment;
String port = environment.getProperty("local.server.port");
En surface, cela semble identique à l’injection d’un champ annoté @Value("${local.server.port}")
(ou @LocalServerPort
, Identique), un échec de l'auto-câblage étant renvoyé au démarrage, la valeur n'étant disponible que lorsque le contexte est complètement initialisé. La différence réside dans le fait que cet appel est implicitement passé dans la logique métier d'exécution plutôt que d'être appelé au démarrage de l'application, d'où la résolution correcte du port.
Vous pouvez obtenir le port utilisé par une instance intégrée de Tomcat lors des tests en injectant la valeur local.server.port en tant que telle:
// Inject which port we were assigned
@Value("${local.server.port}")
int port;
À partir de Spring Boot 1.4.0, vous pouvez l’utiliser dans votre test:
import org.springframework.boot.context.embedded.LocalServerPort;
@SpringBootTest(classes = {Application.class}, webEnvironment = WebEnvironment.RANDOM_PORT)
public class MyTest {
@LocalServerPort
int randomPort;
// ...
}
Juste pour que ceux qui ont configuré leurs applications comme la mienne profitent de ce que j'ai vécu ...
Aucune des solutions ci-dessus n'a fonctionné pour moi car j'ai un répertoire ./config
Juste sous ma base de projet avec 2 fichiers:application.properties
application-dev.properties
Dans application.properties
, J'ai:
spring.profiles.active = dev # set my default profile to 'dev'
Dans application-dev.properties
J'ai:
server_Host = localhost
server_port = 8080
C’est le cas lorsque je lance mon gros fichier jar à partir de la CLI. Les fichiers *.properties
Sont lus à partir du répertoire ./config
Et c’est bon.
Eh bien, il se trouve que ces fichiers de propriétés remplacent complètement le paramètre webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT
Dans @SpringBootTest
Dans mes spécifications Spock. Quoi que j'aie essayé, même avec webEnvironment
défini sur RANDOM_PORT
, Spring démarrera toujours le conteneur Tomcat intégré sur le port 8080 (ou la valeur que j'aurais définie dans mes fichiers ./config/*.properties
).
La manière SEULEMENT que j'ai pu surmonter cela était en ajoutant un properties = "server_port=0"
Explicite à l'annotation @SpringBootTest
Dans mon intégration Spock Spécifications:
@SpringBootTest (webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, properties = "server_port=0")
Alors, et seulement alors, Spring a finalement commencé à faire tourner Tomcat sur un port aléatoire. IMHO c'est un bogue du framework de test de Spring, mais je suis sûr qu'ils auront leur propre opinion à ce sujet.
J'espère que cela a aidé quelqu'un.
Aucune de ces solutions n'a fonctionné pour moi. J'avais besoin de connaître le port du serveur lors de la construction d'un bean de configuration Swagger. Utiliser ServerProperties a fonctionné pour moi:
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
}
}
Cet exemple utilise la configuration automatique Spring Boot et JAX-RS (pas Spring MVC).