SpringBoot技術(shù)實(shí)踐-隨機(jī)端口啟動(dòng)
一、SpringBoot隨機(jī)端口
1.1 基礎(chǔ)介紹
隨機(jī)端口可以自動(dòng)找指定范圍內(nèi)可使用的端口,不需要在配置文件中指定固定的啟動(dòng)端口
例如在SpringBoot中假如需要運(yùn)行多個(gè)實(shí)例,則需要單獨(dú)修改配置文件比較麻煩
隨機(jī)端口的原理就是與對(duì)應(yīng)
socket端口建立連接,能連接則已被使用,反之未被使用隨機(jī)獲取的端口校驗(yàn)可使用之后通過
System.setProperty("屬性名稱", port);寫入內(nèi)存,然后就可以在配置文件中獲取到如果寫入的名稱為
server.port則不用在配置文件中指定端口,否則需要配置server.port=${屬性名稱}本實(shí)踐基于SpringBoot普通工程,直接創(chuàng)建項(xiàng)目腳手架即可
【tip】例如在SpringCloud項(xiàng)目中服務(wù)提供者,可以使用隨機(jī)端口快速啟動(dòng)多個(gè)服務(wù),而不需要單獨(dú)修改配置文件再啟動(dòng)
1.2 實(shí)現(xiàn)步驟
創(chuàng)建
ServerPortUtil .java端口工具類,使用socket連接指定端口,例如有以下條件 a. 指定端口范圍為8000-65535 b. 識(shí)別端口是否使用,已被使用則繼續(xù)隨機(jī)產(chǎn)生 c. 如果全部端口不可使用則直接拋出錯(cuò)誤,中斷運(yùn)行
import java.net.InetAddress;
import java.net.Socket;
import java.util.Random;
public class ServerPortUtil {
private static final int MAX_PORT = 65535;
private static final int MIN_PORT = 8000;
public static String getAvailablePort() {
Random random = new Random();
// 最大嘗試次數(shù)為端口范圍
int maxRetryCount = MAX_PORT - MIN_PORT;
while (maxRetryCount > 0) {
// 指定范圍內(nèi)隨機(jī)端口,隨便寫的算法,根據(jù)自己需要調(diào)整
int port = random.nextInt(MAX_PORT - MIN_PORT) + MIN_PORT;
boolean isUsed = isLocalePortUsing(port);
if (!isUsed) {
return String.valueOf(port);
}
--maxRetryCount;
}
System.out.println("系統(tǒng)暫無端口可用,運(yùn)行結(jié)束");
System.exit(1);
return null;
}
/**
* 檢查給定端口是否可用
*
* @author [email protected]
* @since 2020/10/14
*/
public static boolean isLocalePortUsing(int port) {
try {
// 建立一個(gè)Socket連接, 如果該端口還在使用則返回true, 否則返回false, 127.0.0.1代表本機(jī)
new Socket(InetAddress.getByName("127.0.0.1"), port);
return true;
} catch (Exception e) {
// 異常說明端口連接不上,端口能使用
}
return false;
}
}
復(fù)制代碼創(chuàng)建
StartCommand.java命令類,調(diào)用隨機(jī)端口功能獲取端口信息,然后將端口信息寫入運(yùn)行環(huán)境中 a. 如果傳入的參數(shù)包含了端口則使用指定的,否則使用自動(dòng)生成
import com.codecoord.randomport.util.ServerPortUtil;
import org.springframework.util.StringUtils;
public class StartCommand {
/**
* 端口屬性名稱,如果名稱為server.port則在配置文件中不用指定,否則需要指定為此處配置的名稱,如${auto.port}
*/
private static final String SERVER_PORT = "auto.port";
public StartCommand(String[] args) {
boolean isServerPort = false;
String serverPort = "";
if (args != null) {
for (String arg : args) {
if (StringUtils.hasText(arg) && arg.startsWith("--server.port" )) {
isServerPort = true;
serverPort = arg;
break;
}
}
}
String port;
if (isServerPort) {
port = serverPort.split("=")[1];
} else {
port = ServerPortUtil.getAvailablePort();
}
System.out.println("Current project port is " + port);
System.setProperty(SERVER_PORT, port);
}
}
復(fù)制代碼在啟動(dòng)類啟動(dòng)前向環(huán)境寫入端口信息
import com.codecoord.randomport.config.StartCommand;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplicatio
public class SpringbootRandomPortApplication {
public static void main(String[] args) {
// 寫入端口信息
new StartCommand(args);
SpringApplication.run(SpringbootRandomPortApplication.class, args);
}
}
復(fù)制代碼在配置文件中指定端口為隨機(jī)生成的端口信息
server:
# 隨機(jī)端口配置
port: ${auto.port}
復(fù)制代碼1.3 項(xiàng)目測(cè)試
正常啟動(dòng)項(xiàng)目,可以在控制臺(tái)看到啟動(dòng)的端口信息


二、SpringBoot多實(shí)例運(yùn)行
SpringBoot的多實(shí)例運(yùn)行在IDEA中配置如下

3. 然后在啟動(dòng)上run/debug啟動(dòng)即可
作者:TianXinCoord
鏈接:https://juejin.cn/post/6986451492924293133
來源:掘金
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請(qǐng)注明出處。
