1. Обзор
Приложение Spring Boot включает в себя веб-сервер, и иногда нам может понадобиться обнаружить порт HTTP во время выполнения.
В этом руководстве мы рассмотрим, как программно получить порт HTTP в приложении Spring Boot.
2. Введение
2.1. Наше приложение Spring Boot
Мы создадим простой пример приложения Spring Boot, чтобы быстро показать методы обнаружения порта HTTP во время выполнения:
@SpringBootApplication
public class GetServerPortApplication {
public static void main(String[] args) {
SpringApplication.run(GetServerPortApplication.class, args);
}
}
2.2. Два сценария установки порта
Обычно самый простой способ настроить HTTP-порт приложения Spring Boot — определить порт в файле конфигурации application.properties
или application.yml
.
Например, в файле application.properties
мы можем установить 7777
в качестве порта, на котором работает наше приложение:
server.port=7777
В качестве альтернативы, вместо определения фиксированного порта, мы можем позволить приложению Spring Boot работать на произвольном порту, установив « 0
» в качестве значения свойства « server.port
» :
server.port=0
Далее давайте рассмотрим два сценария и обсудим различные способы программного получения порта во время выполнения.
В этом руководстве мы обнаружим порт сервера в модульных тестах.
3. Получение фиксированного порта во время выполнения
Создадим файл свойств application-fixedport.properties
и определим в нем фиксированный порт 7777
:
server.port=7777
Далее попробуем получить порт в классе юнит-тестов:
@RunWith(SpringRunner.class)
@SpringBootTest(classes = GetServerPortApplication.class,
webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
@ActiveProfiles("fixedport")
public class GetServerFixedPortUnitTest {
private final static int EXPECTED_PORT = 7777;
....
}
Прежде чем мы увидим методы тестирования, давайте быстро взглянем на аннотации тестового класса:
@RunWith(SpringRunner.class)
— это объединит тест JUnit с SpringTestContext.
@SpringBootTest(… SpringBootTest.WebEnvironment.DEFINED_PORT)
— вSpringBootTest
мы будем использоватьDEFINED_PORT
для встроенного веб-сервера.@ActiveProfiles («fixedport»)
— с помощью этой аннотации мы включили профиль Spring «fixedport
», чтобы загружалось нашеприложение -fixedport.properties.
3.1. Использование аннотации @Value("${ server.port }")
Поскольку файл application-fixedport.properties
будет загружен, мы можем получить свойство « server.port
» с помощью аннотации @Value
:
@Value("${server.port}")
private int serverPort;
@Test
public void givenFixedPortAsServerPort_whenReadServerPort_thenGetThePort() {
assertEquals(EXPECTED_PORT, serverPort);
}
3.2. Использование класса ServerProperties
ServerProperties
содержит свойства встроенного веб-сервера, такие как порт, адрес и заголовок сервера.
Мы можем внедрить компонент ServerProperties
и получить от него порт:
@Autowired
private ServerProperties serverProperties;
@Test
public void givenFixedPortAsServerPort_whenReadServerProps_thenGetThePort() {
int port = serverProperties.getPort();
assertEquals(EXPECTED_PORT, port);
}
До сих пор мы узнали два способа получить фиксированный порт во время выполнения. Далее давайте посмотрим, как обнаружить порт в сценарии со случайным портом.
4. Получение случайного порта во время выполнения
На этот раз давайте создадим еще один файл свойств application-randomport.properties
:
server.port=0
Как видно из приведенного выше кода, мы позволяем Spring Boot выбирать свободный порт случайным образом при запуске веб-сервера.
В том же духе давайте создадим еще один класс модульного теста:
....
@ActiveProfiles("randomport")
public class GetServerRandomPortUnitTest {
...
}
Здесь нам нужно активировать профиль Spring « randomport
», чтобы загрузить соответствующий файл свойств.
Мы узнали два способа обнаружения фиксированного порта во время выполнения. Однако они не могут помочь нам получить случайный порт:
@Value("${server.port}")
private int randomServerPort;
@Test
public void given0AsServerPort_whenReadServerPort_thenGet0() {
assertEquals(0, randomServerPort);
}
@Autowired
private ServerProperties serverProperties;
@Test
public void given0AsServerPort_whenReadServerProps_thenGet0() {
int port = serverProperties.getPort();
assertEquals(0, port);
}
Как показывают два тестовых метода, и @Value("${server.port}")
, и serverProperties.getPort()
сообщают "0" в качестве порта. Очевидно, это не тот порт, который мы ожидаем.
4.1. Использование ServletWebServerApplicationContext
Spring Boot запускает ServletWebServerApplicationContext
, если запускается встроенный веб-сервер.
Следовательно, мы можем получить WebServer
из объекта контекста, чтобы получить информацию о сервере или манипулировать сервером:
@Autowired
private ServletWebServerApplicationContext webServerAppCtxt;
@Test
public void given0AsServerPort_whenReadWebAppCtxt_thenGetThePort() {
int port = webServerAppCtxt.getWebServer().getPort();
assertTrue(port > 1023);
}
В приведенном выше тесте мы проверяем, больше ли порт 1023. Это потому, что 0-1023 являются системными портами.
4.2. Обработка ServletWebServerInitializedEvent
Приложение Spring может публиковать различные события, а EventListeners
обрабатывают эти события.
При запуске встроенного веб-сервера будет опубликовано событие ServletWebServerInitializedEvent .
Это событие содержит информацию о веб-сервере.
Поэтому мы можем создать EventListener
для получения порта от этого события:
@Service
public class ServerPortService {
private int port;
public int getPort() {
return port;
}
@EventListener
public void onApplicationEvent(final ServletWebServerInitializedEvent event) {
port = event.getWebServer().getPort();
}
}
Мы можем внедрить сервисный компонент в наш тестовый класс, чтобы быстро получить случайный порт:
@Autowired
private ServerPortService serverPortService;
@Test
public void given0AsServerPort_whenReadFromListener_thenGetThePort() {
int port = serverPortService.getPort();
assertTrue(port > 1023);
}
5. Вывод
Обычно мы настраиваем порт сервера приложения Spring Boot в файле свойств или файле YAML, где мы можем установить либо фиксированный, либо случайный порт.
В этой статье мы обсудили различные подходы к получению фиксированного и случайного порта во время выполнения.
Как всегда, полный исходный код статьи доступен на GitHub .