• 分析解决 spring quartz 中出现的执行两次问题


    1. 问题描述

    在开发询盘功能时,遇到一个需求,就是后台定时任务执行用电施工业务的工单下发。

    使用的技术是 spring quartz,因为其他应用有先例,配置quartz 完成后,先写了一个 helloworld 测试下。

    然而却发现,每次到定时时间后,程序都会执行两次。

    2. 分析过程

    先使用 bing 搜索了下看别人是否也遇到过类似问题,果然有。

    http://blog.csdn.net/jiang117/article/details/43077275

    上面文档的作者,查找的原因是 ContextLoaderListener 和 DispatcherServlet 对应用上下文重复加载,导致问题出现。

    给出的解决方法如下:

    带着这个疑惑,我检查一下自己项目的 web.xml 文件,发现果然有问题。

    下面是 ContextLoaderListener 中加载的上下文。

      <!-- 加载Spring和Mybatis的配置信息 -->
        <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/classes/spring/spring-all.xml</param-value>
        </context-param>
        <!-- Spring监听器 -->
        <listener>
            <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
        </listener>

    这是 DispatcherServlet 加载的上下文

            <!-- Spring MVC servlet -->
        <servlet>
            <servlet-name>SpringMVC</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <init-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>/WEB-INF/classes/spring/spring-all.xml</param-value>
            </init-param>
            <load-on-startup>1</load-on-startup>
            <async-supported>true</async-supported>
        </servlet>
        <servlet-mapping>
            <servlet-name>SpringMVC</servlet-name>
            <url-pattern>/</url-pattern>
        </servlet-mapping>

    经过对比发现,两个上下文都会加载 /WEB-INF/classes/spring/spring-all.xml, spring-all.xml 文件则包含了所有的 spring 配置文件,也就是所有的上下文配置。

    这样就会产生一个问题,就是  spring-all .xml 上下文中所有的配置都会被实例化两次,因此也就会导致该问题出现。

    3. 解决过程

    找到了问题原因,下一步就要修改 web.xml 中的配置,解决 spring-all xml 上下文被实例化两次的问题。

    解决问题之前,先要弄清楚 DispatcherServlet 和 ContextLoaderListener 这两个应用上下文之间的关系。

    下面的内容选自 《spring 实战 第4版》 p139

    两个应用上下文之间的故事
    
    当 DispatcherServlet 启动的时候,它会创建 Spring 上下文,并加载配置文件或者配置类中所声明的 bean。
    
    同时在 Spring Web 应用中,通常还有一个另外的应用上下文,它由 ContextLoaderListener 创建。
    
    两者的分工有所不同, DispatcherServlet 中加载 Web 组件的 bean,如 Controller,viewResolver 以及处理器映射。
    而ContextLoaderListener 要加载应用中其他的 bean,这些 bean 通常是驱动应用后端的中间层和数据层组件。

    同时在如下博客链接 http://www.cnblogs.com/weknow619/p/6341395.html 得到说明:

     因此决定使用 ContextLoaderListener 加载所有配置,而将 DispatchServlet 上下文去除。

        <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/classes/spring/spring-all.xml</param-value>
        </context-param>
    
        <listener>
            <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
        </listener>
            <!-- Spring MVC servlet -->
        <servlet>
            <servlet-name>SpringMVC</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <init-param>
                <param-name>contextConfigLocation</param-name>
                <param-value></param-value>
            </init-param>
            <load-on-startup>1</load-on-startup>
            <async-supported>true</async-supported>
        </servlet>
        <servlet-mapping>
            <servlet-name>SpringMVC</servlet-name>
            <url-pattern>/</url-pattern>
        </servlet-mapping>

    再次启动工程,问题解决。

  • 相关阅读:
    JStorm开发经验+运维经验总结
    Storm-166:Nimbus HA solution based on Zookeeper
    Storm实战集锦
    JStorm之Nimbus简介
    BF算法 + KMP算法
    分布式消息系统:Kafka
    分布式服务框架:Zookeeper简介
    修改JSONArray里所有key的值
    JQuery中$.ajax()方法参数详解
    java利用16进制来辨别png格式的图片
  • 原文地址:https://www.cnblogs.com/reycg-blog/p/7857301.html
Copyright © 2020-2023  润新知