Spring Quartz重新安排作业第一次执行两次

时间:2018-01-15 08:48:27

标签: java spring quartz-scheduler quartz

我使用 Quartz1.5.2 Spring3.2.1 来执行调度任务,在我的应用程序中,我需要在某个时间重新安排任务,但我发现每次重新安排任务时,它将在第一次执行两次。

以下是我的 quartz + spring 配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<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-4.3.xsd ">

    <bean id="testScheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
        <property name="startupDelay" value="0"/> 
        <property name="triggers">
            <list>
                <ref bean="testJobTrigger" />
            </list>
        </property>
    </bean>

    <bean id="testJob" class="com.lucumt.quartz.JobScheduler"></bean>

    <bean id="testJobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
        <property name="targetObject" ref="testJob" />
        <property name="targetMethod" value="schedulerJob" />
        <property name="concurrent" value="false"/>
    </bean>

    <bean id="testJobTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
        <property name="jobDetail" ref="testJobDetail" />
        <property name="cronExpression" value="0/10 * * * * ?" />
    </bean>

</beans>

我将其设为网络应用程序,下面是 web.xml 的代码:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee   http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
    <display-name>Dynamic Quartz Scheduler</display-name>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath*:spring-context-*.xml</param-value>
    </context-param>

    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath*:spring-context-*.xml</param-value>
        </init-param>
    </servlet>

    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <filter>
        <filter-name>characterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
    </filter>

    <servlet-mapping>
        <servlet-name>default</servlet-name>
        <url-pattern>*.css</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>default</servlet-name>
        <url-pattern>*.js</url-pattern>
    </servlet-mapping>

</web-app>

在java调度程序文件下面,quartz将在固定时间调用 schedulerJob(),我们可以调用 resetJob(String expression)来重新安排调度程序执行时间。

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.servlet.ServletContext;

import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.springframework.context.ApplicationContext;
import org.springframework.scheduling.quartz.CronTriggerBean;
import org.springframework.web.context.ServletContextAware;
import org.springframework.web.context.support.WebApplicationContextUtils;

public class JobScheduler implements ServletContextAware {

    private DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    private ServletContext context;

    private int count = 0;
    private String type = "10";

    @Override
    public void setServletContext(ServletContext context) {
       this.context=context;        
    }

    public void schedulerJob() {
        count++;
        System.out.println("=========fixed output: " + df.format(new Date())+"\t"+count);
        if(count%4==0){
            if(type.equals("10")){
                this.resetJob("0/30 * * * * ?");
            }else if(type.equals("30")){
                this.resetJob("0/10 * * * * ?");
            }

            if(type.equals("10")){
                type = "30";
            }else{
                type = "10";
            }
        }
    }

    public void resetJob(String expression){
        System.out.println("****************change to:\t" + expression);
        ApplicationContext applicationContext = WebApplicationContextUtils.getRequiredWebApplicationContext(context);
        Scheduler scheduler = (Scheduler) applicationContext.getBean("testScheduler");
        try {
            CronTriggerBean trigger = (CronTriggerBean) scheduler.getTrigger("testJobTrigger", Scheduler.DEFAULT_GROUP);
            trigger.setCronExpression(expression);
            scheduler.rescheduleJob("testJobTrigger", Scheduler.DEFAULT_GROUP, trigger);
        } catch (SchedulerException e) {
            e.printStackTrace();
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }
}

下面是我的IDE中的输出控制台,正如您所看到的,每次重新安排时,作业将在第一次执行两次,我想这可能与以下代码有关,但我不是&# 39;知道如何修改它,任何人都可以帮助我吗? 提前谢谢!

PS:如果将 Quartz 的版本升级到 2.3.0 并使用 CronTriggerImpl 来实现,则不会发生此问题,由于某些原因,我需要使用版本 1.5.2 ,我想在这个版本解决我的问题。

//I think these two lines may cause the problem,but I don't know how to modify it.
ApplicationContext applicationContext = WebApplicationContextUtils.getRequiredWebApplicationContext(context);
Scheduler scheduler = (Scheduler) applicationContext.getBean("testScheduler");

Reschedule will execute twice at the first time

如果我使用新触发器并更新 resetJob ,如下所示,问题将消失,但我很奇怪为什么如果我使用相同的触发器,它会执行两次? 如果使用相同的触发器,我发现 quartz1.5.2 quartz2.3.0 都有同样的问题!

public void resetJob(String expression){
    System.out.println("****************change to:\t" + expression);
    ApplicationContext applicationContext = WebApplicationContextUtils.getRequiredWebApplicationContext(context);
    Scheduler scheduler = (Scheduler) applicationContext.getBean("testScheduler");
    try {
        //CronTriggerBean trigger = (CronTriggerBean) scheduler.getTrigger("testJobTrigger", Scheduler.DEFAULT_GROUP);
        CronTriggerBean trigger = new CronTriggerBean();
        trigger.setName("testJobTrigger");
        trigger.setGroup(Scheduler.DEFAULT_GROUP);
        trigger.setJobName("testJobDetail");
        trigger.setCronExpression(expression);
        scheduler.rescheduleJob("testJobTrigger", Scheduler.DEFAULT_GROUP, trigger);
    } catch (SchedulerException e) {
        e.printStackTrace();
    } catch (ParseException e) {
        e.printStackTrace();
    }
}

1 个答案:

答案 0 :(得分:0)

尝试创建一个新的触发器对象,不要重复使用旧的触发器对象。