Quartz + Spring在启动时双重执行

时间:2013-11-04 21:50:48

标签: spring-mvc quartz-scheduler

我有Quartz 2.2.1和Spring 3.2.2。 Eclipse Juno上的应用程序

这是我的bean配置:

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

<!-- Spring Quartz -->

<bean id="checkAndRouteDocumentsTask" class="net.tce.task.support.CheckAndRouteDocumentsTask" />

<bean name="checkAndRouteDocumentsJob" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">

    <property name="jobClass" value="net.tce.task.support.CheckAndRouteDocumentsJob" />
    <property name="jobDataAsMap">
        <map>
            <entry key="checkAndRouteDocumentsTask" value-ref="checkAndRouteDocumentsTask" />
        </map>
    </property>
    <property name="durability" value="true" />

</bean>

<!-- Simple Trigger, run every 30 seconds -->
<bean id="checkAndRouteDocumentsTaskTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">

    <property name="jobDetail" ref="checkAndRouteDocumentsJob" />
    <property name="repeatInterval" value="30000" />
    <property name="startDelay" value="15000" />

</bean>

<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
    <property name="jobDetails">
        <list>
            <ref bean="checkAndRouteDocumentsJob" />
        </list>
    </property>

    <property name="triggers">
        <list>
            <ref bean="checkAndRouteDocumentsTaskTrigger" />
        </list>
    </property>
</bean>

我的mvc spring servlet config:

    <?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans     
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context-3.0.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">  
    <bean id="propertyConfigurer" 
     class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    </bean>
    <mvc:annotation-driven />
    <context:annotation-config />
    <context:component-scan base-package="net.tce" />
    <import resource="spring-quartz.xml"/>  
</beans>

的web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
  <display-name>OperationalTCE</display-name>
  <servlet>
    <servlet-name>mvc-dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>0</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>mvc-dispatcher</servlet-name>
    <url-pattern>/rest/*</url-pattern>
  </servlet-mapping>
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/mvc-dispatcher-servlet.xml</param-value>
  </context-param>
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
</web-app>

我的问题是,在启动我的应用程序时,Quartz会同时创建两个作业。我的工作必须每30秒执行一次:

INFO: Starting TASK on Mon Nov 04 15:36:46 CST 2013...
INFO: Starting TASK on Mon Nov 04 15:36:46 CST 2013...
INFO: Starting TASK on Mon Nov 04 15:37:16 CST 2013...
INFO: Starting TASK on Mon Nov 04 15:37:16 CST 2013...
INFO: Starting TASK on Mon Nov 04 15:37:46 CST 2013...
INFO: Starting TASK on Mon Nov 04 15:37:46 CST 2013...

感谢您的帮助。

2 个答案:

答案 0 :(得分:2)

您的ContextLoaderListenerDispatcherServlet都加载了mvc-dispatcher-servlet.xml。基本上复制所有bean,导致2次执行,因为它也是重复的。

将您的配置拆分为由ContextLoaderListener(包含您的服务,dao,计时器等)加载的配置和由DispatcherServlet加载的配置(仅包含与Web相关的bean控制器,查看resovlers)等)。

完全放弃ContextLoaderListener,只使用DispatcherServlet加载所有内容。

答案 1 :(得分:1)

确保您没有在项目的web.xml文件中加载这两个文件。如果单独加载spring-quartz.xml文件,然后分别加载“import”spring-quartz.xml文件的servlet-config.xml文件,那么你将加载文件两次,这将导致你的2个实例调度。简单的解决方法是(1)确保您没有在web.xml文件中加载spring-quartz.xml或(2)删除其他xml文件中的import语句。

已更新:感谢您向我们展示了用于排除规则的web.xml。仔细检查xml文件后,您将使用作业详细信息和触发器设置SchedulerFactoryBean。这是你的问题。作业详细信息包含在触发器的一部分中,因此将它们再次放入会导致它被安排两次。请阅读有关setJobDetails()方法的这两个链接的文档:

http://docs.spring.io/spring/docs/2.5.6/api/org/springframework/scheduling/quartz/SchedulerFactoryBean.html

http://docs.spring.io/spring/docs/2.5.6/api/org/springframework/scheduling/quartz/SchedulerAccessor.html#setJobDetails%28org.quartz.JobDetail []%29

http://docs.spring.io/spring/docs/2.5.6/api/org/springframework/scheduling/quartz/SchedulerAccessor.html#setTriggers%28org.quartz.Trigger []%29

重要信息摘录:

setJobDetails public void setJobDetails(JobDetail [] jobDetails) 使用此FactoryBean创建的Scheduler注册JobDetail对象列表,以供Triggers引用。 当Trigger确定JobDetail本身时,这不是必需的:在这种情况下,JobDetail将与Trigger一起隐式注册。

解决方案是从SchedulerFactoryBean中删除jobDetails,如下所示:

<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
    <list>
        <ref bean="checkAndRouteDocumentsTaskTrigger" />
    </list>
</property>
</bean>