ContextLoaderListener 与否?

标准的弹簧 Web 应用程序(由 Roo 或“Spring MVC 项目”模板创建)使用 和 创建一个 web.xml。为什么他们不仅使用 DispatcherServlet 并让它加载完整的配置?ContextLoaderListenerDispatcherServlet

我理解 ContextLoaderListener 应该用于加载与 Web 无关的内容,而 DispatcherServlet 用于加载与 Web 相关的内容(控制器,...)。这导致两个上下文:父上下文和子上下文。

背景:

几年来,我一直以这种标准方式做到这一点。

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

这通常会导致两个上下文以及它们之间的依赖关系出现问题。在过去,我总是能够找到解决方案,我有强烈的感觉,这使得软件结构/架构总是更好。但现在我面临着两种情况的事件的问题

- 然而,这让我重新思考这两种上下文模式,我问自己:为什么我应该让自己陷入这种麻烦,为什么不用一个加载所有spring配置文件并完全删除。(我仍然会有不同的配置文件,但只有一个上下文。DispatcherServletContextLoaderListener

有什么理由不删除 ?ContextLoaderListener


答案 1

在你的情况下,不,没有理由保留 和 .如果你的应用程序只与servlet的上下文一起工作,那就坚持这一点,那就更简单了。ContextLoaderListenerapplicationContext.xml

是的,通常鼓励的模式是将非Web内容保留在webapp级别的上下文中,但它只不过是一个弱约定。

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

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

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

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


答案 2

您也可以反过来配置应用程序上下文。例如,为了使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>

只需确保上下文ConfigLocation参数值为空。


推荐