java 为什么 Spring Context 被加载两次?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11409237/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 04:58:34  来源:igfitidea点击:

Why Spring Context is loaded twice?

javaspring

提问by Balconsky

I have web project with Spring and Spring security. My web.xml:

我有带有 Spring 和 Spring 安全性的 Web 项目。我的 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>

In server logs I see Spring context is loaded twice (spring bean initialization, database createtion...). At first time DispatcherServlet does it, and at the secont time ContextLoaderListener. How can I fix it?

在服务器日志中,我看到 Spring 上下文被加载了两次(spring bean 初始化、数据库创建...)。第一次 DispatcherServlet 执行它,第二次执行 ContextLoaderListener。我该如何解决?

In thistutorial I see that if contextParam is presented then servlet init-params are not required. But if I remove init params I have error: "org.apache.catalina.LifecycleException: org.apache.catalina.LifecycleException: java.io.FileNotFoundException: Could not open ServletContext resource [/WEB-INF/billboard-servlet.xml]". Dispather servlet finds context-configuration in default location.

教程中,我看到如果提供了 contextParam,则不需要 servlet init-params。但是如果我删除初始化参数我有错误:“org.apache.catalina.LifecycleException: org.apache.catalina.LifecycleException: java.io.FileNotFoundException: 无法打开 ServletContext 资源 [/WEB-INF/billboard-servlet.xml] ”。Dispather servlet 在默认位置找到上下文配置。

回答by soulcheck

You still need a context for your servlet:

您仍然需要一个 servlet 的上下文:

Upon initialization of a DispatcherServlet, Spring MVC looks for a file named [servlet-name]-servlet.xml in the WEB-INF directory of your web application and creates the beans defined there, overriding the definitions of any beans defined with the same name in the global scope.

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

You don't need to load it as context-paramin the ContextLoaderListenerthough.

你不需要像context-param在那样加载它ContextLoaderListener

Just leave the security-config.xmlas context-param(it has to go there, as security is global per application), and billboard-servlet.xmlas contextConfigLocationof your servlet and it should work.

刚刚离开security-config.xmlcontext-param(它有去那里,因为安全是每个应用程序的全球性),并billboard-servlet.xmlcontextConfigLocation你的servlet的,它应该工作。

回答by Stefan

I had the same issue and the reason was:

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

<load-on-startup>1</load-on-startup

<load-on-startup>1</load-on-startup

回答by Marko Topolnik

These are two independent methods to do the same thing. Drop the ContextLoaderListener, for example.

这是两种独立的方法来做同样的事情。ContextLoaderListener例如,删除。

回答by Bharath

Since you have spring delegatingFilterProxy, if you drop contextLoaderListeryou will get the below exception.

由于您有 spring delegatingFilterProxy,如果您放弃,contextLoaderLister您将获得以下异常。

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

So load security-config.xml via contextLoaderLister and billboard-servlet.xml via dispatcher servlet.

因此,通过 contextLoaderLister 加载 security-config.xml,通过调度程序 servlet 加载 billboard-servlet.xml。

回答by aamir

When you configure the spring MVC framework configuration in the XML, you may configure it as bellow:

在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>

this configuration will cause the IoC container initialize twice.

此配置将导致 IoC 容器初始化两次。

You should change the default servlet name[billboard] to others to solve this problem.

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

Because your dispatcher servlet is using the default context namespace [name of servlet]-servlet.xml (in the case billboard-servlet.xml) then Spring MVC will automatically load it.

因为您的调度程序 servlet 使用默认上下文命名空间 [servlet 的名称]-servlet.xml(在 billboard-servlet.xml 的情况下),那么 Spring MVC 将自动加载它。

For more details see: https://www.conqtech.com/blog/?p=85

更多详情请见:https: //www.conqtech.com/blog/?p=85