端口冲突的解决方案以及SpringBoot自动检测可用端口demo

时间:2024-10-07 07:27:28
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"); } }