【问题标题】:WebApplicationInitializer being called repeatedlyWebApplicationInitializer 被重复调用
【发布时间】:2012-10-09 20:38:54
【问题描述】:

我有一个托管在 Tomcat 7.x(最新版本)下的基于 Spring 3.1 的应用程序。该应用程序仅使用 Java 配置(没有 web.xml,没有 Spring XML 配置)。所有单元测试都通过了,包括使用 Spring Java 配置的单元测试 (@ContextConfiguration)。

问题在于,在部署应用程序时,WebApplicationInitializer 实现被多次调用。过滤器和侦听器的重复注册会导致异常,并且应用程序永远不会启动。

我没想到WebApplicationInitializer.onStartup() 会被重复调用,我希望尽可能消除这种行为。如果有人对为什么会发生这种情况以及如何阻止它提出建议,我将不胜感激。

更新我认为问题是初始化类本身的外部问题,但如果我弄错了……

public class DeploymentDescriptor implements WebApplicationInitializer {

    private static final Logger LOGGER = LoggerFactory.getLogger("org.ghc.web-app-initializer");

    @Override
    public void onStartup (ServletContext servletContext) throws ServletException {
        // This is the programmatic way of declaring filters. This allows you to order
        // Filters. The order of these security filters DOES MATTER!
        FilterRegistration.Dynamic mockSecurityFilter       = servletContext.addFilter ("mockSecurityFilter", "org.ghc.security.MockSecurityFilter");
        mockSecurityFilter.addMappingForUrlPatterns         (EnumSet.of (REQUEST), true, "/*");

        FilterRegistration.Dynamic siteMinderSecurityFilter = servletContext.addFilter ("siteMinderSecurityFilter", "org.ghc.security.SiteMinderSecurityFilter");
        siteMinderSecurityFilter.addMappingForUrlPatterns   (EnumSet.of (REQUEST), true, "/*");

        FilterRegistration.Dynamic userDetailsStoreFilter   = servletContext.addFilter ("userDetailsStoreFilter", "org.ghc.security.UserDetailsStoreFilter");
        userDetailsStoreFilter.addMappingForUrlPatterns     (EnumSet.of (REQUEST), true, "/*");


        // Static resource handling using "default" servlet
        servletContext.getServletRegistration ("default").addMapping ("*.js", "*.css", "*.jpg", "*.gif", "*.png");
        // Map jspf files to jsp servlet
        servletContext.getServletRegistration ("jsp").addMapping ("*.jspf");


        // Spin up the Spring 3.1 class that can scan a package tree for classes
        // annotated with @Configuration. See org.ghc.spring3.ControllerConfiguration for
        // this example.
        final AnnotationConfigWebApplicationContext dispatcherContext = new AnnotationConfigWebApplicationContext ();
        dispatcherContext.setServletContext (servletContext);
        dispatcherContext.register(ScProviderDirectory.class);
        dispatcherContext.refresh ();

        // Spin up the Spring DispatcherServlet (just like before) passing the just built
        // application context. Load it like the regular Servlet that it is!
        final ServletRegistration.Dynamic servlet = servletContext.addServlet ("spring", new DispatcherServlet(dispatcherContext));
        servlet.setLoadOnStartup (1);
        servlet.addMapping ("/");  // Make sure this is NOT "/*"!
    }
}

更新 2 这很奇怪。 Tomcat 日志似乎标识了我的 DeploymentDescriptor 类的两个实例。我验证了我的 .war 文件中只有一个此类的实例。我不知道第二个(幻影)实例来自哪里,但至少这解释了为什么这个类被扫描了两次......

logs/localhost.2012-10-09.log:INFO: Spring WebApplicationInitializers detected on classpath: [org.ghc.configuration.DeploymentDescriptor@3b29642c]
logs/localhost.2012-10-09.log:INFO: Spring WebApplicationInitializers detected on classpath: [org.ghc.configuration.DeploymentDescriptor@432c4c7a]

【问题讨论】:

  • 很有趣,想知道你的初始化程序是否抛出了一些异常,你可以添加更多日志以确保
  • 我一直在用调试器观看(Java 配置的真正好处)。第一次通过一切顺利。第二个生成 NPE(servletContext.addFilter() 返回 null,然后对该过滤器的调用导致 NPE)。第一次之后对 ServletContext 的其他调用也会出现问题。
  • 我认为它更像是SpringServletContainerInitializer 的两个实例,它注册了被检测到的WebApplicationInitializers..可能是多个spring-web*.jar?
  • 很好地验证我的依赖关系。不幸的是,它们很干净,没有版本不匹配,没有冲突。如果您滚动到日志条目的右侧,它似乎实际上是在找到我的 DeploymentDescritor 类两次(DeploymentDescriptor@3b29642c 和 DeploymentDescriptor@432c4c7a),而不是不同的 WebApplicationInitializers 实现。我有几个这样的应用程序,我无法找出为什么这个应用程序的行为不同。再次感谢您的想法!

标签: spring tomcat spring-mvc


【解决方案1】:

这里的问题是 Maven Overlay 将 crap 一个 Spring xml 配置文件转储到我的应用程序中。无论出于何种原因,这都会导致 WebApplicationInitializer.onStartup() 被调用两次。可能是应用程序上下文和 servlet 上下文的初始化。关闭覆盖,应用程序正在按预期初始化。

【讨论】:

  • 我也有同样的问题,你到底是怎么“杀死 Maven Overlay”的?你能再解释一下吗?我正在查看maven.apache.org/plugins/maven-war-plugin/overlays.html,但我不知道该怎么做?
  • 已经有一段时间了,但我相信问题的核心是(有意)使用基于 Java 的 Spring 配置类,以及 XML Spring 配置文件的存在(无意)。我不记得 xml 是上下文还是 servlet 范围。删除意外包含的(在我的情况下覆盖)xml 配置文件为我清除了它。对不起,我不记得细节......
【解决方案2】:

我遇到了同样的问题。问题是我有多个 spring-web*.jar 像 Biju K. 建议的(一个作为战争的一部分,另一个在共享/tomcat 库中)。

【讨论】:

    【解决方案3】:

    我遇到了同样的问题。在 web 应用模块的目录中运行 mvn clean 然后启动 Tomcat 为我解决了这个问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-09-03
      • 1970-01-01
      • 2011-02-05
      • 1970-01-01
      • 1970-01-01
      • 2017-08-15
      • 2023-03-19
      相关资源
      最近更新 更多