Как мне установить свойство в bean-компоненте ServletWebServerFactory - PullRequest
0 голосов
/ 21 апреля 2020

Я создал класс в модуле библиотеки, у которого есть bean-компонент ServletWebServerFactory, чтобы при запуске моего приложения весенней загрузки вызывался этот метод bean-компонента, чтобы я мог программно установить порт для tomcat на основе некоторых свойств среды. В основном, если server.port не установлен, он использует SocketUtils для получения случайного доступного порта в пределах диапазона, определенного свойствами server.port.min и server.port.max (или их значениями по умолчанию)

public class TomcatServlet {

    final Logger logger = LoggerFactory.getLogger(TomcatServlet.class);

    @Autowired
    private Environment environment;

    @Bean
    public ServletWebServerFactory servletWebServerFactory() {

        String serverPort = environment.getProperty("server.port");

        // Note: min port number should be greater or equal to 49152 as lower values are either registered or semi-reserved
        int minPort = Integer.parseInt(environment.getProperty("server.port.min", "49152"));
        int maxPort = Integer.parseInt(environment.getProperty("server.port.max", "65535"));

        logger.info("server.port: {}, server.port.min: {}, server.port.max: {}", serverPort, minPort, maxPort);

        // if serverPort is defined then use that value
        int port;

        // if serverPort is not defined then get a random available port in the defined or default range
        if (serverPort == null) {
            // get an available port in the range
            port = getRandomPort(minPort, maxPort);
        } else {
            port = Integer.parseInt(serverPort);
        }
        logger.info("port to set tomcat on: {}", port);

        Long unloadDelay = Long.valueOf(environment.getProperty("tomcat.unload.timeout", "30000"));
        logger.info("Tomcat unloadDelay = {}", unloadDelay);

        TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();
        Long finalUnloadDelay = unloadDelay;
        tomcat.addContextCustomizers(context -> {
            if(context instanceof StandardContext) {
                ((StandardContext) context).setUnloadDelay(finalUnloadDelay);
            }
        });
        tomcat.setPort(port);

        return tomcat;
    }

    private int getRandomPort(int minPort, int maxPort) {

        int returnPort = 0;
        try {
            returnPort = SocketUtils.findAvailableTcpPort(minPort, maxPort);
            logger.info("Random Server Port is {}.", returnPort);
        } catch( IllegalStateException e) {
            // no available port found so it will use the configured server.port value
            logger.warn("No port available in range {$minPort}-{$maxPort}. Default configuration {$returnPort} will be used.");
        }
        return returnPort;

    }
}

Это все работает нормально, tomcat запускается на ожидаемом порту, и я могу включить эту библиотеку во все наши службы, и все они будут запускаться на ожидаемых портах.

Однако , каждая служба определяется как служба клиента Eureka и как таковая регистрируется на сервере Eureka. Когда он делает это, он отправляет информацию об имени сервера и номере порта на сервер Eureka.

Номер порта берется из свойства server.port, которое не обязательно является портом, на котором был запущен tomcat. Поэтому я хотел бы сохранить рассчитанный порт в свойстве server.port в том месте, где он рассчитан. Есть ли способ получить доступ к свойствам приложений таким образом, чтобы их можно было изменить в моем классе TomcatServlet?

Я провел тестовую реализацию аналогичных функций в основном классе одного из сервисов, чтобы я мог получить доступ к SpringApplication и используйте метод setDefaultProperties для установки server.port, и в этом случае мне не пришлось бы делать это в классе библиотеки.

public static void main(String[] args) {

        SpringApplication application = new SpringApplication(AddressBSMain.class);
        Properties properties = new Properties();
        int port = HttpUtils.getRandomPort(50000, 50100);
        properties.put("server.port", port);
        application.setDefaultProperties(properties);

        application.run(args);

    }

Опять же, это работает нормально. Единственная проблема с этим состоит в том, что мы должны были бы внедрить это изменение в каждую из наших 60 с лишним услуг. В идеале мы хотели бы сохранить код в нашей общей библиотеке, чтобы все, что нам нужно было сделать, - это изменить каждый файл maven pom служб, чтобы изменить версию зависимости

Есть предложения?

...