端口冲突的解决方案以及SpringBoot自动检测可用端口demo
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.embedded.tomcat.TomcatConnectorCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.io.IOException;
import java.net.ServerSocket;
import java.util.Random;
/**
* @ Author:Yang
* @ Description:自动加载可用端口配置
* @ create:2024-10-06-13:54
*/
@Slf4j
@Configuration
public class PortAutoConfiguration {
@Value("${server.port:8080}")
private int defaultPort;
@Value("${sdk.port.retry-count:10}")
private int retryCount;
@Value("${sdk.port.max-port:100000}")
private int maxPort;
@Value("${sdk.port.min-port:1000}")
private int minPort;
@Bean
public TomcatConnectorCustomizer customServerPortTomcatConnectorCustomizer() {
// 尝试次数为0,则设置为0
if (retryCount < 0) retryCount = 0;
// 确保最大端口不小于最小端口
if (maxPort < minPort) maxPort = minPort;
// 从默认端口开始寻找可用端口
int port = findAvailablePort(defaultPort);
log.info("设置端口为 port : {}", port);
// 返回可用端口
return connector -> connector.setPort(port);
}
private int findAvailablePort(int port) {
Random random = new Random();
//已经尝试次数
int count = 0;
// 这样可以保证最小为 1 ,random的最小为0
int bound = maxPort - minPort + 1;
while (count < retryCount) {
try (ServerSocket serverSocket = new ServerSocket(port)) {
return port;
} catch (IOException e) {
// 端口被占用,尝试下一个端口
int oldPort = port;
count++;
port = minPort + random.nextInt(bound);
log.warn("{}端口冲突,更换端口为{},已尝试{}次",oldPort,port,count);
}
}
// 如果循环结束后仍未找到可用端口,抛出异常或返回特定值
throw new RuntimeException("Unable to find an available port after " + retryCount + " retries");
}
}