Java 为什么要加载两次Spring上下文?
我有一个带有Spring和Spring安全性的web项目。 My web.xml: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/
<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由于您有springdelegatingFilterProxy
,如果您删除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无论如何都会继承它。