WebApplicationContextUtils.getWebApplicationContext(ServletContext) 从 ServletContextListener 返回 NULL

Md *_*aza 6 spring-mvc spring-java-config

我无法在 ServletContextListener 中获取 WebApplicationContext。我寻找解决方案,但没有一个适合我。如果有人可以提供帮助,我将不胜感激。提前致谢。

以下是代码片段 - 我的 AppConfig 类:

package in.andonsystem.config;

import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ResourceBundleMessageSource;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = {"in.andonsystem"})
public class AppConfig extends WebMvcConfigurerAdapter{

   @Bean
   public ViewResolver viewResolver(){
      InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
      viewResolver.setViewClass(JstlView.class);
      viewResolver.setPrefix("WEB-INF/views/");
      viewResolver.setSuffix(".jsp");
      return viewResolver;
   }

   @Bean
   public MessageSource messageSource(){
      ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
      messageSource.setBasename("messages");     
      return messageSource;
   }

   @Override
   public void addResourceHandlers(ResourceHandlerRegistry registry) {
      registry.addResourceHandler("/static/**").addResourceLocations("/static/");
   }
}
Run Code Online (Sandbox Code Playgroud)

我的 AppInitializer 类。

package in.andonsystem.config;

import javax.servlet.ServletRegistration;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;

public class Appinitializer implements WebApplicationInitializer{

   @Override
   public void onStartup(ServletContext servletContext) throws ServletException {
      AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
      rootContext.register(AppConfig.class);
      rootContext.setServletContext(servletContext);

      // Manage the lifecycle of the root application context
      servletContext.addListener(new ContextLoaderListener(rootContext));
      rootContext.refresh();

      // Register and map the dispatcher servlet
      ServletRegistration.Dynamic dispatcher =
              servletContext.addServlet("dispatcher", new DispatcherServlet(rootContext));
      dispatcher.setLoadOnStartup(1);
      dispatcher.addMapping("/");

   }
}
Run Code Online (Sandbox Code Playgroud)

我的 ContextListener 类:

package in.andonsystem.config;

import com.mysql.jdbc.AbandonedConnectionCleanupThread;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Enumeration;
import java.util.logging.Logger;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

@WebListener
public class ContextListener implements ServletContextListener{

   private Logger logger = Logger.getLogger("ContextListener");


   @Override
   public void contextInitialized(ServletContextEvent sce) {
      logger.info("contextInitialized()");

      WebApplicationContext rootContext = WebApplicationContextUtils.getWebApplicationContext(sce.getServletContext());
      System.out.println("Is rootContext null:" + (rootContext == null));

   }

   @Override
   public void contextDestroyed(ServletContextEvent sce) {

   }

}
Run Code Online (Sandbox Code Playgroud)

标准输出输出总是成真。我缺少什么?

Md *_*aza 2

终于想出了解决办法。问题是 ServletContextListener 在 ContextLoaderListener 之前加载,因此返回的 WebApplicationContext 为 null,因为 ContextLoaderListener 必须在 ServletContextListener 之前加载才能获取 rootContext。

我从 ContextListener 中删除了 @WebListener 注释,并在添加 ContextLoaderListener 后以编程方式在 AppInitializer 的 onStartup 方法中添加了此侦听器。

现在我没有 @WebListener 注释的 ContextListener 是:

public class ContextListener implements ServletContextListener{

   private Logger logger = Logger.getLogger("ContextListener");


   @Override
   public void contextInitialized(ServletContextEvent sce) {
      logger.info("contextInitialized()");

      WebApplicationContext rootContext = 
              WebApplicationContextUtils.getWebApplicationContext(sce.getServletContext());
      System.out.println("Is rootContext null:" + (rootContext == null));

   }

   @Override
   public void contextDestroyed(ServletContextEvent sce) {
      logger.info("contextDestroyed()");
   }

}
Run Code Online (Sandbox Code Playgroud)

AppInitializer 是:

public class Appinitializer implements WebApplicationInitializer{

   @Override
   public void onStartup(ServletContext servletContext) throws ServletException {
      AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
      rootContext.register(AppConfig.class);
      rootContext.setServletContext(servletContext);

      // Manage the lifecycle of the root application context
      servletContext.addListener(new ContextLoaderListener(rootContext));
      //ContextListener must be added after ContextLoaderListener
      servletContext.addListener(ContextListener.class);


      // Register and map the dispatcher servlet
      ServletRegistration.Dynamic dispatcher =
              servletContext.addServlet("dispatcher", new DispatcherServlet(rootContext));
      dispatcher.setLoadOnStartup(1);
      dispatcher.addMapping("/");

   }
}
Run Code Online (Sandbox Code Playgroud)