Spring MVC - ContextLoaderListener加载了两次

时间:2017-01-27 01:27:59

标签: spring spring-mvc tomcat web-applications web.xml

所以我的头真的很痛 - 我在Spring看过ContextLoaderListener的角色/目的,我不能再往前走了。

我有一个非常古老的项目,我正在升级它。到目前为止,我已经设法将它从spring 2.x带到spring 4.x以及从Java 7到Java 8,但是我坚持在tomcat 8上运行应用程序。它两次使用ContextLoaderListener!在tomcat 7上启动没有问题。

Tomcat 7:apache-tomcat-7.0.29

Tomcat 8:apache-tomcat-8.5.11

web.xml

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE web-app PUBLIC 
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"     
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
               http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

    <display-name>VERSION-1.7.1</display-name>

    <context-param>
        <param-name>listenPort_http</param-name>
        <param-value>80</param-value>
    </context-param>
    <context-param>
        <param-name>listenPort_https</param-name>
        <param-value>8443</param-value>
    </context-param>

    <context-param>
        <param-name>daoType</param-name>
        <param-value>ibatis</param-value>
    </context-param>

    <context-param>
        <param-name>javax.servlet.jsp.jstl.fmt.localizationContext</param-name>
        <param-value>ApplicationResources</param-value>
    </context-param>

    <context-param>
        <param-name>javax.servlet.jsp.jstl.fmt.fallbackLocale</param-name>
        <param-value>en</param-value>
    </context-param>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            classpath*:META-INF/applicationContext-*.xml
            /WEB-INF/applicationContext-*.xml
        </param-value>
    </context-param>
    <context-param>
        <param-name>org.apache.myfaces.ERROR_HANDLING</param-name>
        <param-value>false</param-value>
    </context-param>

    <context-param>
        <param-name>javax.faces.CONFIG_FILES</param-name>
        <param-value>
            /WEB-INF/faces-specification-config.xml,
            /WEB-INF/faces-operating-config.xml,
            /WEB-INF/faces-popup-config.xml,
            /WEB-INF/faces-mabr-config.xml
        </param-value>
        <description></description>
    </context-param>

    <filter>
        <filter-name>clickstreamFilter</filter-name>
        <filter-class>com.opensymphony.clickstream.ClickstreamFilter</filter-class>
    </filter>
    <filter>
        <filter-name>encodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter>
        <filter-name>rewriteFilter</filter-name>
        <filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>
    </filter>
    <filter>
        <filter-name>sitemesh</filter-name>
        <filter-class>com.opensymphony.module.sitemesh.filter.PageFilter</filter-class>
    </filter>
    <filter>
        <filter-name>exportFilter</filter-name>
        <filter-class>org.displaytag.filter.ResponseOverrideFilter</filter-class>
    </filter>
    <filter>
        <filter-name>uploadExtensionsFilter</filter-name>
        <filter-class>
            org.apache.myfaces.webapp.filter.ExtensionsFilter
        </filter-class>
        <init-param>
            <param-name>uploadMaxFileSize</param-name>
            <param-value>10m</param-value>
        </init-param>
        <init-param>
            <param-name>uploadThresholdSize</param-name>
            <param-value>100k</param-value>
        </init-param>
    </filter>

    <filter>
        <filter-name>compressionFilter</filter-name>
        <display-name>Compression Filter</display-name>
        <filter-class>org.opendls.webapp.filter.GZIPFilter</filter-class>
    </filter>
    <filter>
        <filter-name>mySecurityFilter</filter-name>
        <display-name>Security Filter</display-name>
        <filter-class>org.opendls.webapp.filter.MySecurityFilter</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>mySecurityFilter</filter-name>
        <url-pattern>*.html</url-pattern>
    </filter-mapping>
    <filter-mapping>
        <filter-name>mySecurityFilter</filter-name>
        <url-pattern>*.jsp</url-pattern>
    </filter-mapping>
    <filter-mapping>
        <filter-name>clickstreamFilter</filter-name>
        <url-pattern>*.html</url-pattern>
    </filter-mapping>
    <filter-mapping>
        <filter-name>encodingFilter</filter-name>
        <url-pattern>*.html</url-pattern>
    </filter-mapping>
    <filter-mapping>
        <filter-name>encodingFilter</filter-name>
        <url-pattern>*.jsp</url-pattern>
    </filter-mapping>
    <filter-mapping>
        <filter-name>exportFilter</filter-name>
        <url-pattern>*.html</url-pattern>
    </filter-mapping>
    <filter-mapping>
        <filter-name>compressionFilter</filter-name>
        <url-pattern>*.html</url-pattern>
    </filter-mapping>
    <filter-mapping>
        <filter-name>sitemesh</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <filter-mapping>
        <filter-name>uploadExtensionsFilter</filter-name>
        <url-pattern>*.html</url-pattern>
    </filter-mapping>

    <listener>
        <listener-class>com.opensymphony.clickstream.ClickstreamListener</listener-class>
    </listener>
    <listener>
        <listener-class>org.apache.myfaces.webapp.StartupServletContextListener</listener-class>
    </listener>
    <listener>
        <listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>
    </listener>
    <listener>
        <listener-class>com.sun.xml.ws.transport.http.servlet.WSServletContextListener</listener-class>
    </listener>

    <listener>
        <listener-class>org.opendls.webapp.listener.StartupListener</listener-class>
    </listener>
    <listener>
        <listener-class>org.opendls.webapp.listener.SessionListener</listener-class>
    </listener>
    <listener>
        <listener-class>org.opendls.webapp.listener.ShutdownListener</listener-class>
    </listener>
    <listener>
        <listener-class>org.opendls.webapp.listener.UserCounterListener</listener-class>
    </listener>

    <servlet>
        <servlet-name>faces</servlet-name>
        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
        <load-on-startup>2</load-on-startup>
    </servlet>
    <servlet>
        <servlet-name>wsit-jaxws-fromjava</servlet-name>
        <display-name>wsit-jaxws-fromjava</display-name>
        <description>JAX-WS endpoint - fromjava</description>
        <servlet-class>com.sun.xml.ws.transport.http.servlet.WSServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>


    <servlet-mapping>
        <servlet-name>faces</servlet-name>
        <url-pattern>*.html</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>wsit-jaxws-fromjava</servlet-name>
        <url-pattern>/webservices/*</url-pattern>
    </servlet-mapping>

    <session-config>
        <session-timeout>1440</session-timeout>
    </session-config>

    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>

    <error-page>
        <error-code>500</error-code>
        <location>/error.jsp</location>
    </error-page>
    <error-page>
        <error-code>400</error-code>
        <location>/index.jsp</location>
    </error-page>
    <error-page>
        <error-code>403</error-code>
        <location>/403.jsp</location>
    </error-page>
    <error-page>
        <error-code>404</error-code>
        <location>/404.jsp</location>
    </error-page>
    <error-page>
        <exception-type>javax.faces.application.ViewExpiredException</exception-type>
        <location>/viewExpired.jsp</location>
    </error-page>

    <resource-ref>
        <description>DB Connection</description>
        <res-ref-name>jdbc/primary</res-ref-name>
        <res-type>javax.sql.DataSource</res-type>
        <res-auth>Container</res-auth>
    </resource-ref>
    <resource-ref>
        <description>DB Connection</description>
        <res-ref-name>jdbc/secondary</res-ref-name>
        <res-type>javax.sql.DataSource</res-type>
        <res-auth>Container</res-auth>
    </resource-ref>


</web-app>

StartupListener.java

public class StartupListener extends ContextLoaderListener
implements ServletContextListener {

    private static final Log log = LogFactory.getLog(StartupListener.class);

    public void contextInitialized(ServletContextEvent event) {
        if (log.isDebugEnabled()) {
            log.debug("initializing context...");
        }

        super.contextInitialized(event);

        ServletContext context = event.getServletContext();
        String daoType = context.getInitParameter(Constants.DAO_TYPE);

        // if daoType is not specified, use DAO as default
        if (daoType == null) {
            log.warn("No 'daoType' context carameter, using hibernate");
            daoType = Constants.DAO_TYPE_HIBERNATE;
        }

        // Orion starts Servlets before Listeners, so check if the config
        // object already exists
        Map config = (HashMap) context.getAttribute(Constants.CONFIG);

        if (config == null) {
            config = new HashMap();
        }

        // Create a config object to hold all the app config values
        config.put(Constants.DAO_TYPE, daoType);
        context.setAttribute(Constants.CONFIG, config);

        // output the retrieved values for the Init and Context Parameters
        if (log.isDebugEnabled()) {
            log.debug("daoType: " + daoType);
            log.debug("populating ...");
        }
        setupContext(context);        
    }    

    public static void setupContext(ServletContext context) {
        ApplicationContext appContext = WebApplicationContextUtils.getRequiredWebApplicationContext(context);

        RightsManager rightsManager = (RightsManager) appContext.getBean("rightsManager");

        context.setAttribute(Constants.AVAILABLE_ROLES, rightsManager.getAllRights());

        if (log.isDebugEnabled()) {
            log.debug("initialization complete [OK]");
        }        
    }      
}

我在web.xml和StartupListener.java上尝试过很多东西,但是我无法只管理一次ContextLoaderListener。我一遍又一遍地得到同样的错误:

错误:

27-Jan-2017 02:25:29.217 INFO [localhost-startStop-1] org.apache.catalina.core.ApplicationContext.log No Spring WebApplicationInitializer types detected on classpath
27-Jan-2017 02:25:30.071 INFO [localhost-startStop-1] org.apache.catalina.core.ApplicationContext.log Initializing Spring root WebApplicationContext
27-Jan-2017 02:25:33.060 SEVERE [localhost-startStop-1] org.apache.catalina.core.StandardContext.listenerStart Exception sending context initialized event to listener instance of class org.opendls.webapp.listener.StartupListener
 java.lang.IllegalStateException: Cannot initialize context because there is already a root application context present - check whether you have multiple ContextLoader* definitions in your web.xml!
    at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:297)
    at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:107)
    at org.opendls.webapp.listener.StartupListener.contextInitialized(StartupListener.java:48)
    at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4725)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5189)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:752)
    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:728)
    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:734)
    at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:952)
    at org.apache.catalina.startup.HostConfig$DeployWar.run(HostConfig.java:1823)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)

27-Jan-2017 02:25:33.071 INFO [localhost-startStop-1] org.apache.catalina.core.ApplicationContext.log Closing Spring root WebApplicationContext
27-Jan-2017 02:25:33.075 INFO [localhost-startStop-1] org.apache.catalina.core.ApplicationContext.log Closing Spring root WebApplicationContext
27-Jan-2017 02:25:33.405 INFO [localhost-startStop-1] org.apache.catalina.core.ApplicationContext.log ContextListener: contextInitialized()
27-Jan-2017 02:25:33.407 INFO [localhost-startStop-1] org.apache.catalina.core.ApplicationContext.log SessionListener: contextInitialized()
问题在哪里?

1 个答案:

答案 0 :(得分:0)

好的 - 问题已解决

M.Denim提到有一些重复的侦听器触发了相同的ApplicationContext来加载。

WEB-INF中有.tld文件,其中包含web.xml中的相同侦听器,该文件由ant task创建。 Tomcat 8.x的新实现将它们读作noPluggabilityListeners并且第二次触发了load。