为项目启动生成一个随机端口

2022-07-01 08:08:17

        在实际开发中,项目的端口都是定好的,通过server.port可以指定端口。当一个服务想要启动多个实例时,就需要改变端口,特别是在微服务中,服务都会注册到注册中心去,为了能够让服务随时都可以扩容,在服务启动的时候能随机生成一个可以使用的端口是最好不过的。

        第一种:在配置文件中通过server.port指定。指定的值通过${random}来随机生成

server:
  port: ${random.int[2000,8000]}

        这种通过配置文件的方式是最简单的,但是如果启动中随机生成的端口已经被占用,那么启动就会报错。

        第二种:编写一个启动参数设置类,通过启动参数设置类指定。

1、编写启动参数设置类等相关代码

import com.smile.server.utils.ServerPortUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

/**
 * 启动参数设置类
 */
public class StartCommand {

    private Logger logger = LoggerFactory.getLogger(StartCommand.class);

    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;
                }
            }
        }
        //没有指定端口,则随机生成一个可用的端口
        if (!isServerPort){
            int port = ServerPortUtils.getAvailablePort();
            logger.info("current server.port=" + String.valueOf(port));
            System.setProperty("server.port",String.valueOf(port));
        }else {
            logger.info("current server.port="+ serverPort.split("=")[1]);
            System.setProperty("server.port",serverPort.split("=")[1]);
        }
    }

}
import java.util.Random;

/**
 * 随机端口生成类
 */
public class ServerPortUtils {

    public static int getAvailablePort(){
        int max = 65535;
        int min = 2000;
        Random random = new Random();
        int port = random.nextInt(max)%(max-min+1) + min;
        boolean using = NetUtils.isLoclePortUsing(port);
        if (using){
            return getAvailablePort();
        }else {
            return port;
        }
    }

}
import java.net.InetAddress;
import java.net.Socket;

public class NetUtils {

    public static boolean isLoclePortUsing(int port){
        boolean flag = true;
        try {
            flag = isPortUsing("127.0.0.1", port);
        } catch (Exception e) {
        }
        return flag;
    }

    public static boolean isPortUsing(String host,int port) {
        boolean flag = false;
        try {
            InetAddress theAddress = InetAddress.getByName(host);
            Socket socket = new Socket(theAddress,port);
            flag = true;
        } catch (Exception e) {

        }
        return flag;
    }

}

2、在启动类中调用,进行启动参数设置

import com.smile.server.config.StartCommand;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;


@SpringBootApplication
public class ServerApplication {

    public static void main(String[] args) {
        //启动参数设置,比如自动生成端口
        new StartCommand(args);
        SpringApplication.run(ServerApplication.class, args);
        System.out.println("项目启动成功!");
    }

}

通过启动参数设置类,主要通过对启动参数进行遍历判断,如果有指定端口,后续就不指定了,如果没有指定端口,就通过ServerPortUtils获取一个可以使用的端口,然后设置到环境变量中。注意在存在启动参数设置类的时候,即使在配置文件中指定了项目的端口,配置文件中的端口也不会生效,因此,在存在启动参数设置类的时候,配置文件中server.port的值应当写为下面格式

server:
  port: ${server.port}
  • 作者:one_smail
  • 原文链接:https://blog.csdn.net/qq_40386113/article/details/120274735
    更新时间:2022-07-01 08:08:17