zoukankan      html  css  js  c++  java
  • 解决Spring定时计划任务重复执行两次(实例被构造两次)问题的方法

    http://blog.csdn.net/chaijunkun/article/details/6925889

    计划任务确实是差不多每隔3秒钟被调度的,但是每次调度执行了任务方法两次。设想一下,这仅仅是个开销很小的例子,但是如果这个方法执行的是一个非常耗时耗资源的任务,好不容易执行完一次后又要执行一次,这是对计算资源的极大浪费。于是查找了一天的原因,最后在国外的一个论坛上找到了解决的办法(http://forum.springsource.org/showthread.php?33311-IoC-Container-initializes-my-app-twice)。

     

    楼主roncox和我遇到了同样的问题,他和我的配置差不多,同样也贴出了配置文件。虽然其他人没有解决问题,但是他自己解决了,并提供了最后的解决方法:

     

    解决办法就是将web.xml配置文件中的如下节点删掉:

    [html]view plaincopy
     
    1. <listener>
    2. <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    3. </listener>
    4. <context-param>
    5. <param-name>contextConfigLocation</param-name>
    6. <param-value>/WEB-INF/classes/applicationContext*.xml</param-value>
    7. </context-param>


    修改之后程序运行一切正常。个人推测,由于org.springframework.web.context.ContextLoaderListener和org.springframework.web.servlet.DispatcherServlet都能够加载applicationContext*.xml(“*”是通配符,表示所有以“applicationContext”开头的xml文件)。而两个类殊途同归,最终都将这些配置文件交给了Spring框架的Ioc容器进行实例化。因此每个类都会被实例化两次。

     

    2012年1月10日补充:今天做项目自习研究了一下spring的配置文件,发现之前说的不完全正确,不应该删除web.xml中的如下节点

     

    [html]view plaincopy
     
    1. <listener>
    2. <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    3. </listener>
    4. <context-param>
    5. <param-name>contextConfigLocation</param-name>
    6. <param-value>/WEB-INF/classes/applicationContext*.xml</param-value>
    7. </context-param>


    因为该节点指派的applicationContext*.xml是用于实例化除servlet之外的所有对象的,可以说项目中绝大多数的service和dao层操作都由ContextLoaderListener传递给Spring来进行实例化。

     

    在web应用中,web.xml还经常出现如下的配置:

     

    [html]view plaincopy
     
    1. <!--全局Servlet调度配置-->
    2. <servlet>
    3. <!--若设置servlet-name为[name]-->
    4. <!--则DispatcherServlet在实例化后会自动加载[name]-servlet.xml-->
    5. <servlet-name>spring</servlet-name>
    6. <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    7. <init-param>
    8. <param-name>contextConfigLocation</param-name>
    9. <param-value>classpath:servletContext.xml</param-value>
    10. </init-param>
    11. <!--随服务器一同启动-->
    12. <load-on-startup>1</load-on-startup>
    13. </servlet>
    14. <servlet-mapping>
    15. <servlet-name>spring</servlet-name>
    16. <url-pattern>*.do</url-pattern>
    17. </servlet-mapping>

    这个是用来处理所有servlet的,没有它就无法通过请求地址来调用相应的Controller。
    这里我明确地指示了要加载类路径下的servletContext.xml,如果不指定,则会按照注释中所描述地那样自动加载spring-servlet.xml
    无论是servletContext.xml还是applicationContext*.xml都可以按照<beans>...<bean id="XXX" class="XXX" />...</beans>这样的形式来配置。
    问题来了,有时候不注重对象初始化的分类,尤其是使用<context:component-scan base-package="controller" />这样的包扫描形式统一初始化,
    很容易造成满足条件的对象被初始化两次,那么在计划任务的时候被执行两次也就不奇怪了。其实说来说去,还是要提醒大家,不同的配置文件其作用是不一样的,
    不要将所有的初始化操作都放到一个配置文件中,更不要重复配置。不仅浪费资源,还很容易导致莫名其妙的故障。

     

     

    另外,有相关文章还提到过是Tomcat服务器的问题,修改conf目录下的server.xml。修改节点Host,将appBase属性由默认的“webapps”设置为空("")即可,如下所示:

    [html]view plaincopy
     
    1. <Hostname="localhost"appBase=""unpackWARs="true"autoDeploy="true"
    2. xmlValidation="false"xmlNamespaceAware="false">
    3. <ContextdocBase="/usr/local/apache-tomcat-6.0.29/webapps/semwinner"
    4. path=""reloadable="true"></Context>
    5. <ContextdocBase="/usr/local/apache-tomcat-6.0.29/webapps/emarboxmanager"
    6. path="/admin"reloadable="true"></Context>
    7. </Host>

    但是本人尝试之后并没有起作用。可能不适用于我遇到的这个问题。写出上面解决方法的作者认为web应用程序默认都是放在webapps这个目录下的,如果不把“webapps“去掉,这里会调用一次quartz的任务调度,在接下来的“<Context path”中又会调用一次quartz的任务调度,所以就重复了2次。两个方法都写出来,供朋友们参考。

    第二种解决方法来自http://nkliuliu.iteye.com/blog/816335

  • 相关阅读:
    课程评价
    6.1-6.7 第十六周总结
    5.31 软件开发日志
    5.25-5.31 第十五周总结
    5.30 软件开发日志
    5.29 软件开发日志
    5.28 软件开发日志
    对搜狗输入法的评价
    找水王
    用户模板/用户场景
  • 原文地址:https://www.cnblogs.com/xue88ming/p/7183015.html
Copyright © 2011-2022 走看看