«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» для загрузки соответствующего файла свойств.

Мы узнали два способа обнаружения фиксированного порта во время выполнения. Однако они не могут помочь нам получить случайный порт. «0» в качестве порта. Очевидно, это не тот порт, который мы ожидаем.

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

4.1. Использование ServletWebServerApplicationContext

Spring Boot запускает ServletWebServerApplicationContext, если запускается встроенный веб-сервер.

Следовательно, мы можем получить WebServer из объекта контекста, чтобы получить информацию о сервере или манипулировать сервером:

В приведенном выше тесте мы проверяем, больше ли порт 1023. Это потому, что 0- 1023 — это системные порты.

@Autowired
private ServletWebServerApplicationContext webServerAppCtxt;

@Test
public void given0AsServerPort_whenReadWebAppCtxt_thenGetThePort() {
    int port = webServerAppCtxt.getWebServer().getPort();
 
    assertTrue(port > 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.