首页 文章

Spring启动服务器端口范围设置

提问于
浏览
2

是否可以在application.yml文件中为spring启动应用程序设置server.port的可接受范围 .

我已经设置server.port = 0来获得自动分配的端口而不是硬编码的端口 .

我们的网络运营人员希望限制此端口分配的可用范围 .

任何的想法?

5 回答

  • 3

    只需实施 EmbeddedServletContainerCustomizer http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-developing-web-applications.html#boot-features-programmatic-embedded-container-customization

    当然你可以对下面的 public static boolean available(int port) 进行改进,检查端口的可用性,因为有些端口虽然可用,但有时会被拒绝,如端口1024,依赖于操作系统,也可以从某些属性文件读取范围但不能使用Spring读取,因为范围是在上下文之前设置的加载,但这不应该是一个问题,我把所有东西放在一个文件中,以显示方法,使其看起来不漂亮

    @Configuration
    @ComponentScan
    @EnableAutoConfiguration
    
    
    public class DemoApplication {
    
        private static final int MIN_PORT = 1100; // to by set according to your
        private static final int MAX_PORT = 9000; // needs or uploaded from
        public static int myPort; // properties whatever suits you
    
        public static void main(String[] args) {
    
        int availablePort = MIN_PORT;
        for (availablePort=MIN_PORT; availablePort < MAX_PORT; availablePort++) {
            if (available(availablePort)) {
    
                break;
            }
        }
        if (availablePort == MIN_PORT && !available(availablePort)) {
            throw new IllegalArgumentException("Cant start container for port: " + myPort);
    
        }
        DemoApplication.myPort = availablePort;
    
        SpringApplication.run(DemoApplication.class, args);
    }
    
        public static boolean available(int port) {
            System.out.println("TRY PORT " + port);
            // if you have some range for denied ports you can also check it
            // here just add proper checking and return 
            // false if port checked within that range
            ServerSocket ss = null;
            DatagramSocket ds = null;
            try {
                ss = new ServerSocket(port);
                ss.setReuseAddress(true);
                ds = new DatagramSocket(port);
                ds.setReuseAddress(true);
                return true;
            } catch (IOException e) {
            } finally {
                if (ds != null) {
                    ds.close();
                }
    
                if (ss != null) {
                    try {
                        ss.close();
                    } catch (IOException e) {
                        /* should not be thrown */
                    }
                }
            }
    
            return false;
        }
    
    }
    

    这是最重要的部分:

    @Component
    class CustomizationBean implements EmbeddedServletContainerCustomizer {
    
        @Override
        public void customize(ConfigurableEmbeddedServletContainer container) {
    
            container.setPort(DemoApplication.myPort);
    
        }
    
    }
    
  • 2

    在user1289300和Dave Syer之后,我使用答案来制定一个解决方案 . 它作为配置提供,从服务器部分的application.yml文件中读取 . 我提供了一个最小和最大的端口范围可供选择 . 再次感谢

    @Configuration
    @ConfigurationProperties("server")
    public class EmbeddedServletConfiguration{
    
    /*
        Added EmbeddedServletContainer as Tomcat currently. Need to change in future if  EmbeddedServletContainer get changed
     */
    private final int MIN_PORT = 1100;
    private final int MAX_PORT = 65535;
    /**
     * this is the read port from the applcation.yml file
     */
    private int port;
    /**
     * this is the min port number that can be selected and is filled in from the application yml fil if it exists
     */
    private int maxPort = MIN_PORT;
    
    /**
     * this is the max port number that can be selected and is filled
     */
    private int minPort = MAX_PORT;
    
    /**
     * Added EmbeddedServletContainer as Tomcat currently. Need to change in future if  EmbeddedServletContainer get changed
     *
     * @return the container factory
     */
    @Bean
    public EmbeddedServletContainerFactory servletContainer() {
        return new TomcatEmbeddedServletContainerFactory();
    }
    
    @Bean
    public EmbeddedServletContainerCustomizer containerCustomizer() {
            return new EmbeddedServletContainerCustomizer() {
            @Override
            public void customize(ConfigurableEmbeddedServletContainer container) {
                // this only applies if someone has requested automatic port assignment
                if (port == 0) {
                    // make sure the ports are correct and min > max
                    validatePorts();
                    int port = SocketUtils.findAvailableTcpPort(minPort, maxPort);
                    container.setPort(port);
                }
               container.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/404"));
               container.addErrorPages(new ErrorPage(HttpStatus.FORBIDDEN, "/403"));
    
            }
        };
    }
    
    /**
     * validate the port choices
     * - the ports must be sensible numbers and within the alowable range and we fix them if not
     * - the max port must be greater than the min port and we set it if not
     */
     private void validatePorts() {
         if (minPort < MIN_PORT || minPort > MAX_PORT - 1) {
             minPort = MIN_PORT;
         }
    
         if (maxPort < MIN_PORT + 1 || maxPort > MAX_PORT) {
             maxPort = MAX_PORT;
         }
    
         if (minPort > maxPort) {
             maxPort = minPort + 1;
         }
     }
    
    }
    
  • 0

    Spring 季启动项目存在挑战,我们目前无法将此功能添加到 spring 启动,如果您有任何解决方案请提供帮助 .

    Spring boot server port range support Pull Request

  • 0

    我们使用EmbeddedServletContainerCustomizer在Spring Boot 1.5.9中完成了这个操作,如下所示:

    @Bean
    public EmbeddedServletContainerCustomizer containerCustomizer() {
        return (container -> {
            try {
    
                // use defaults if we can't talk to config server
                Integer minPort = env.getProperty("minPort")!=null ? Integer.parseInt(env.getProperty("minPort")) : 7500;
                Integer maxPort = env.getProperty("maxPort")!=null ? Integer.parseInt(env.getProperty("maxPort")) : 9500;
                int port = SocketUtils.findAvailableTcpPort(minPort,maxPort);
                System.getProperties().put("server.port", port);
                container.setPort(port);
            } catch (Exception e) {
                log.error("Error occured while reading the min & max port form properties : " + e);
                throw new ProductServiceException(e);
            }
    
        });
    }
    

    但是在Spring Boot 2.0.0.M7中似乎不可能这样,我们正在寻找另一种方法 .

  • -1

    使用此解决方案,应用程序选择自己的端口 . 我不明白为什么它会变成“-1”,因为它运行得很完美 .

    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer;
    import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.util.SocketUtils;    
    
    @Configuration
    
       class PortRangeCustomizerBean implements EmbeddedServletContainerCustomizer 
    {
    
    private final Logger logger = LoggerFactory.getLogger(this.getClass());
    
    @Value("${spring.port.range.min}")
    private int MIN_PORT;
    
    @Value("${spring.port.range.max}")
    private int MAX_PORT;
    
    @Override
    public void customize(ConfigurableEmbeddedServletContainer container) {
        int port = SocketUtils.findAvailableTcpPort(MIN_PORT, MAX_PORT);
        logger.info("Started with PORT:\t " + port);
        container.setPort(port);
    }
    

    }

相关问题