У меня есть приложение весной загрузки (используя встроенные 7) кот, и я поставил server.port = 0
по моему , application.properties
так что я могу иметь случайный порт. После того, как сервер загружен и работает на порту, мне нужно получить тот порт, который был выбран.
Я не могу использовать, @Value("$server.port")
потому что это ноль. Это, казалось бы, простая информация, так почему я не могу получить к ней доступ из своего Java-кода? Как я могу получить к нему доступ?
Ответы:
Можно ли аналогичным образом получить доступ к порту управления, например:
@SpringBootTest(classes = {Application.class}, webEnvironment = WebEnvironment.RANDOM_PORT) public class MyTest { @LocalServerPort int randomServerPort; @LocalManagementPort int randomManagementPort;
источник
@LocalServerPort
это просто ярлык для@Value("${local.server.port}")
.Среда Spring содержит для вас эту информацию.
@Autowired Environment environment; String port = environment.getProperty("local.server.port");
На первый взгляд это выглядит идентично внедрению аннотированного
@Value("${local.server.port}")
(или@LocalServerPort
идентичного) поля , в результате чего при запуске возникает сбой автоподключения, поскольку значение недоступно, пока контекст не будет полностью инициализирован. Разница здесь в том, что этот вызов неявно выполняется в бизнес-логике времени выполнения, а не вызывается при запуске приложения, и, следовательно, «ленивая выборка» порта разрешается нормально.источник
environment.getProperty("server.port")
.Спасибо @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(); } }
источник
PortProvider
и предоставивgetPort()
метод. Автоматически подключил меняPortProvider
к контроллеру, которому нужен порт, и при вызове моей бизнес-логикиportProvider.getPort()
был возвращен порт времени выполнения.EmbeddedServletContainerInitializedEvent
, но есть похожий класс, уServletWebServerInitializedEvent
которого есть.getWebServer()
метод. Это даст вам хотя бы порт, который прослушивает Tomcat.Точно так же другие, которые настроили свои приложения, как мое, извлекли выгоду из того, через что я прошел ...
Ни одно из вышеперечисленных решений не помогло мне, потому что у меня есть
./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
Это так, когда я запускаю свою толстую банку из интерфейса командной строки,
*.properties
файлы будут прочитаны из./config
каталога, и все будет хорошо.Что ж, оказывается, что эти файлы свойств полностью отменяют
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT
настройку@SpringBootTest
в моих спецификациях Spock. Независимо от того, что я пробовал, даже приwebEnvironment
установкеRANDOM_PORT
Spring всегда запускал встроенный контейнер Tomcat на порт 8080 (или любое другое значение, которое я установил в своих./config/*.properties
файлах).Только так , как я был в состоянии преодолеть это путь добавления явного
properties = "server_port=0"
к@SpringBootTest
аннотации в моей интеграции спецификации Spock:@SpringBootTest (webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, properties = "server_port=0")
Тогда и только тогда Spring, наконец, начал запускать Tomcat на случайном порту. ИМХО, это ошибка фреймворка тестирования Spring, но я уверен, что у них будет собственное мнение по этому поводу.
Надеюсь, это кому-то помогло.
источник
Вы можете получить порт, который используется встроенным экземпляром Tomcat во время тестов, введя значение local.server.port как таковое:
// Inject which port we were assigned @Value("${local.server.port}") int port;
источник
local.server.port
устанавливается только при беге с@WebIntegrationTests
Начиная с 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; // ... }
источник
Ни одно из этих решений не помогло мне. Мне нужно было знать порт сервера при создании bean-компонента конфигурации Swagger. У меня сработало использование 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).
источник
После Spring Boot 2 многое изменилось. Приведенные выше ответы работают до Spring Boot 2. Теперь, если вы запускаете свое приложение с аргументами времени выполнения для порта сервера, вы получите только статическое значение с
@Value("${server.port}")
, которое упоминается в файле application.properties . Теперь, чтобы получить фактический порт, на котором работает сервер, используйте следующий метод:@Autowired private ServletWebServerApplicationContext server; @GetMapping("/server-port") public String serverPort() { return "" + server.getWebServer().getPort(); }
Кроме того, если вы используете свои приложения в качестве клиентов Eureka / Discovery с балансировкой нагрузки
RestTemplate
илиWebClient
, указанный выше метод вернет точный номер порта.источник
Вы можете получить порт сервера из
@Autowired private HttpServletRequest request; @GetMapping(value = "/port") public Object getServerPort() { System.out.println("I am from " + request.getServerPort()); return "I am from " + request.getServerPort(); }
источник
Убедитесь, что вы импортировали правильный пакет
import org.springframework.core.env.Environment;
а затем используйте объект Environment
@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")); }
источник
Я решил это с помощью своего рода прокси-бина. Клиент инициализируется, когда это необходимо, к тому времени порт должен быть доступен:
@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; } }
источник