我使用 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");
如果我使用新触发器并更新 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();
}
}
答案 0 :(得分:0)
尝试创建一个新的触发器对象,不要重复使用旧的触发器对象。