Как зарегистрировать DispatcherServlets и переопределить OnStartup при расширении SpringBootServletInitializer

#spring #spring-boot #servlets #jasypt #servlet-listeners

#spring #spring-boot #сервлеты #jasypt #сервлет-слушатели

Вопрос:

У меня есть приложение spring boot, которое развертывается во внешнем экземпляре Tomcat. Основной класс расширяет SpringBootServletInitializer и переопределяет методы configure и OnStartup . В методе configure инициализируется пользовательская среда для предоставления средства шифрования для расшифровки пользовательских паролей для activemq, поскольку jasypt не инициализируется до завершения activemq. Это я получил из документации jasypt-spring-boot.

 @Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
    try {
        StandardEncryptableServletEnvironment env = StandardEncryptableServletEnvironment.builder().encryptor(encryptor).build();
        return application.environment(env).sources(AxleServer.class);
    } catch (FileNotFoundException e) {
        logger.error("Could not load encryptable environment", e);
        return application.sources(AxleServer.class);
    }
}
  

В методе OnStartup я настраиваю DispatcherServlets:

 @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
        context.register(RemotingConfig.class);
        servletContext.addListener(new ContextLoaderListener(context));
        
        ServletRegistration.Dynamic restDispatcher = servletContext.addServlet("rest-dispatcher", new DispatcherServlet(context));
        restDispatcher.setLoadOnStartup(1);
        restDispatcher.addMapping("/rest/*");

        ServletRegistration.Dynamic remotingDispatcher = servletContext.addServlet("remoting-dispatcher", new DispatcherServlet(context));
        remotingDispatcher.setLoadOnStartup(2);
        remotingDispatcher.addMapping("/remoting/*");
    }
  

Проблема в том, что метод configure никогда не вызывается, потому что он вызывается из суперреализации OnStartup . Я попытался вызвать super.onStartup(servletContext); суперреализацию, но затем я получаю сообщение об ошибке, что корневой контекст уже существует при развертывании приложения.

Как правильно зарегистрировать DispatcherServlets и переопределить метод OnStartup? Требуется ли вызывать суперреализацию OnStartup?

Ответ №1:

Я смог решить эту проблему, сначала вызвав super.OnStartup, а затем получив корневой контекст из атрибутов ServletContext

 @Override
public void onStartup(ServletContext servletContext) throws ServletException {
    super.onStartup(servletContext);
    Object obj = servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
    if(obj instanceof AnnotationConfigServletWebServerApplicationContext) {
        AnnotationConfigServletWebServerApplicationContext context = (AnnotationConfigServletWebServerApplicationContext) obj;
        context.register(RemotingConfig.class);
            
        ServletRegistration.Dynamic restDispatcher = servletContext.addServlet("rest-dispatcher", new DispatcherServlet(context));
        restDispatcher.setLoadOnStartup(1);
        restDispatcher.addMapping("/rest/*");

        ServletRegistration.Dynamic remotingDispatcher = servletContext.addServlet("remoting-dispatcher", new DispatcherServlet(context));
        remotingDispatcher.setLoadOnStartup(2);
        remotingDispatcher.addMapping("/remoting/*");
    }
}