ContextLoaderListener or not?

A standard spring web application (created by Roo or "Spring MVC Project" Template) create a web.xml with ContextLoaderListener and DispatcherServlet. Why do they not only use the DispatcherServlet and make it to load the complete configuration?

I understand that the ContextLoaderListener should be used to load the stuff that is not web relevant and the DispatcherServlet is used to load the web relevant stuff (Controllers,...). And this result in two contexts: a parent and a child context.

Background:

I was doing it this standard way for several years.

<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:META-INF/spring/applicationContext*.xml</param-value>
</context-param>


<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>


<!-- Handles Spring requests -->
<servlet>
<servlet-name>roo</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>WEB-INF/spring/webmvc-config.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>

This often caused problems with the two contexts and the dependencies between them. In the past I was always able to find a solution, and I have the strong feeling that this makes the software structure/architecture always better. But now I am facing a problem with the events of the both contexts.

-- However this makes my rethink this two context pattern, and I am asking myself: why should I bring myself into this trouble, why not loading all spring configuration files with one DispatcherServlet and removing the ContextLoaderListener completely. (I still will to have different configuration files, but only one context.)

Is there any reason not to remove the ContextLoaderListener?

53577 次浏览

在你的情况下,不,没有理由保留 ContextLoaderListenerapplicationContext.xml。如果您的应用程序只需要 servlet 的上下文就可以正常工作,那么它就更简单了。

是的,普遍鼓励的模式是将非 web 内容保留在 webapp 级别的上下文中,但这只不过是一种薄弱的约定。

使用 webapp 级别上下文的唯一令人信服的理由是:

  • 如果您有多个需要共享服务的 DispatcherServlet
  • 如果您有需要访问 Spring 有线服务的遗留/非 Spring servlet
  • 如果你的 servlet 过滤器可以连接到 webapp 级别的上下文(例如 Spring Security 的 DelegatingFilterProxyOpenEntityManagerInViewFilter等)

这些都不适用于您,因此额外的复杂性是没有根据的。

只是在向 servlet 上下文添加后台任务时要小心,比如计划任务、 JMS 连接等等。如果您忘记将 <load-on-startup>添加到 web.xml中,那么直到第一次访问 servlet 时才会启动这些任务。

我想分享我在 Spring-MVC 应用程序中所做的工作:

  1. we-mvc-config.xml上,我只添加了带有@Controller 注释的类:

    <context:component-scan base-package="com.shunra.vcat">
    <context:include-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
    </context:component-scan>
    
  2. On the applicationContext.xml files I added all the rest:

    <context:component-scan base-package="com.shunra.vcat">
    <context:exclude-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
    </context:component-scan>
    

您也可以反过来配置应用程序上下文。例如,为了使 OpenEntityManagerInViewFilter工作。设置 ContextLoaderListener,然后用以下方式配置 DispatcherServlet:

<servlet>
<servlet-name>spring-mvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value></param-value>
</init-param>
</servlet>

只要确保 ContextConfigLocation参数值为空即可。