Java 为什么要加载两次Spring上下文?

Java 为什么要加载两次Spring上下文?,java,spring,Java,Spring,我有一个带有Spring和Spring安全性的web项目。 My web.xml: <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/

我有一个带有Spring和Spring安全性的web项目。 My web.xml:

    <web-app xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
         version="3.0" >
        <display-name>BillBoard
        </display-name>
        <session-config>
            <session-timeout>
                30
            </session-timeout>
        </session-config>
        <listener>
            <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
        </listener>
        <listener>
            <listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
        </listener>
        <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:security-config.xml classpath:billboard-servlet.xml</param-value>
        </context-param>
        <servlet>
            <servlet-name>billboard</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <init-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>classpath:security-config.xml classpath:billboard-servlet.xml</param-value>
            </init-param>
            <load-on-startup>1</load-on-startup>

        </servlet>
        <servlet-mapping>
            <servlet-name>billboard</servlet-name>
            <url-pattern>*.html</url-pattern>
        </servlet-mapping>
        <filter>
            <filter-name>springSecurityFilterChain</filter-name>
            <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
        </filter>

        <filter-mapping>
            <filter-name>springSecurityFilterChain</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>
    </web-app>

广告牌
30
org.springframework.web.context.ContextLoaderListener
org.springframework.security.web.session.HttpSessionEventPublisher
上下文配置位置
类路径:security-config.xml类路径:billboard-servlet.xml
广告牌
org.springframework.web.servlet.DispatcherServlet
上下文配置位置
类路径:security-config.xml类路径:billboard-servlet.xml
1.
广告牌
*.html
springSecurityFilterChain
org.springframework.web.filter.DelegatingFilterProxy
springSecurityFilterChain
/*
在服务器日志中,我看到Spring上下文被加载了两次(Springbean初始化、数据库创建…)。DispatcherServlet第一次执行此操作,第二次执行ContextLoaderListener。我怎样才能修好它


在本教程中,我看到如果显示contextParam,则不需要servlet init参数。但如果删除init参数,则会出现错误:“org.apache.catalina.LifecycleException:org.apache.catalina.LifecycleException:java.io.FileNotFoundException:无法打开ServletContext资源[/WEB-INF/billboard servlet.xml]”。Dispather servlet在默认位置查找上下文配置。

这是两个独立的方法来完成相同的任务。例如,删除
ContextLoaderListener

您仍然需要servlet的上下文:

初始化DispatcherServlet后,Spring MVC在WEB应用程序的WEB-INF目录中查找名为[servlet name]-servlet.xml的文件,并在其中创建定义的bean,覆盖全局范围内使用相同名称定义的任何bean的定义

不过,您不需要在
ContextLoaderListener
中将其作为
context参数加载


只需将
security config.xml
保留为
context参数(它必须放在那里,因为每个应用程序的安全性都是全局的),将
billboard servlet.xml
保留为servlet的
contextConfigLocation
,它应该可以工作。

我也有同样的问题,原因是:


1由于您有spring
delegatingFilterProxy
,如果您删除
contextLoaderLister
,您将得到以下异常

java.lang.IllegalStateException: No WebApplicationContext found: 
no   ContextLoaderListener registered?

因此,通过contextLoaderLister加载security-config.xml,通过dispatcher servlet加载billboard-servlet.xml。

在xml中配置spring MVC框架配置时,您可以将其配置为以下内容:

<!-- for Spring context loader -->
<servlet>
    <servlet-name>billboard</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:security-config.xml classpath:billboard-servlet.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>

</servlet>

广告牌
org.springframework.web.servlet.DispatcherServlet
上下文配置位置
类路径:security-config.xml类路径:billboard-servlet.xml
1.
此配置将导致IoC容器初始化两次

您应该将默认servlet名称[billboard]更改为其他名称以解决此问题

因为您的DispatcherServlet正在使用默认的上下文命名空间[name of servlet]-servlet.xml (在billboard servlet.xml的情况下)然后Spring MVC将自动加载它


有关更多详细信息,请参见:

如果我删除contextLoaderListener,则会出现异常“java.lang.IllegalStateException:未找到WebApplicationContext:未注册contextLoaderListener?”如果您删除
contextConfigLocation
,则我尝试从DispatcherServlet中删除上下文参数或init参数,但这两个选项都会抛出错误。然后您需要发布关于这些错误的完整详细信息。Stacktraces,作为开始。我修改了问题,请再次查看。对于身份验证,我使用了用户数据库,所以我在billboard-servlet.xml中定义了数据源,并在我的AuthenticationProvider中像属性一样引用它。如果您的数据源在servlet之外使用,它不应该在
billboard servlet.xml
中。把它放在根上下文中——servlet无论如何都会继承它。