Перейти к основному содержимому

Получить работающий порт в Spring Boot

· 4 мин. чтения

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 с Spring TestContext.
  • @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 .