在Spring Boot中獲取正在運行的端口

1.概述

Spring Boot應用程序嵌入了Web服務器,有時,我們可能希望在運行時發現HTTP端口。

在本教程中,我們將介紹如何在Spring Boot應用程序中以編程方式獲取HTTP端口。

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 設置端口的兩種方案

通常,配置Spring Boot應用程序的HTTP端口最直接的方法是在配置文件application.propertiesapplication.yml定義端口。

例如,在application.properties文件中,我們可以將7777設置為應用程序在其上運行的端口:

server.port=7777

另外,除了定義固定端口, 0 ”設置為“ server.port ”屬性的值來讓Spring Boot應用程序在隨機端口上運行

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) –這將通過Spring TestContext
  • @SpringBootTest( … SpringBootTest.WebEnvironment.DEFINED_PORT) –在SpringBootTest ,我們將DEFINED_PORT用於嵌入式Web服務器
  • @ActiveProfiles(“fixedport”) –使用此註釋,我們啟用了Spring概要文件“ fixedport ”,以便將我們的application-fixedport.properties加載

3.1 使用@Value(“${server.port}”)批註

由於application-fixedport.properties文件,因此我們可以@Value批註server.port ”屬性:

@Value("${server.port}")

 private int serverPort;



 @Test

 public void givenFixedPortAsServerPort_whenReadServerPort_thenGetThePort() {

 assertEquals(EXPECTED_PORT, serverPort);

 }

3.2 使用ServerProperties

ServerProperties保留嵌入式Web服務器的屬性,例如端口,地址和服務器標頭。

我們可以注入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

如上面的代碼所示,當Web服務器啟動時,我們允許Spring Boot隨機選擇一個空閒端口。

同樣,讓我們創建另一個單元測試類:

....

 @ActiveProfiles("randomport")

 public class GetServerRandomPortUnitTest {

 ...

 }

在這裡,我們需要激活“ randomport ” Spring配置文件以加載相應的屬性文件。

我們已經學習了兩種在運行時發現固定端口的方法。但是,它們不能幫助我們獲得隨機端口:

@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

如果嵌入式Web服務器啟動,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處理這些事件。

嵌入式Web服務器啟動後,將發布[ServletWebServerInitializedEvent](https://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/web/servlet/context/ServletWebServerInitializedEvent.html)此事件包含有關Web服務器的信息。

因此,我們可以創建一個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.結論

通常,我們在屬性文件或YAML文件中配置Spring Boot應用程序的服務器端口,我們可以在其中設置固定端口或隨機端口。

在本文中,我們討論了在運行時獲取固定端口和隨機端口的不同方法。