我当时配置的方式是,可能大部分人的配置方式和我类似,如:
1、配置spring-quartz.xml的配置文件,内容如下
<!-- 声明任务工厂 -->
<bean id="scheduler" autowire="no" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation" value="classpath:quartz.properties" />
<property name="applicationContextSchedulerContextKey" value="applicationContextKey"/>
</bean>
可以看到 scheduler的对象来源是spring的类 org.springframework.scheduling.quartz.SchedulerFactoryBean
配置数据源 ref="dataSource" ,加载quartz的配置文件
<property name="configLocation" value="classpath:quartz.properties" />
通过quartz的上下文获取spring上下文的配置
<property name="applicationContextSchedulerContextKey" value="applicationContextKey"/>
2、quartz的任务实现方式ScheduleJobServiceImpl
package com.credithc.accent.service.impl;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.quartz.impl.matchers.GroupMatcher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.credithc.accent.model.ScheduleJob;
import com.credithc.accent.service.ScheduleJobService;
/**
* 定时任务 service
* @author ty
* @date 2015年1月13日
*/
@Service("scheduleJobService")
public class ScheduleJobServiceImpl implements ScheduleJobService{
@Autowired
private Scheduler scheduler;
/**
* 添加定时任务
* @param ScheduleJob
*/
public void add(ScheduleJob scheduleJob){
@SuppressWarnings("rawtypes")
Class job = null;
try {
job = Class.forName(scheduleJob.getClassName());
} catch (ClassNotFoundException e1) {
e1.printStackTrace();
}
@SuppressWarnings("unchecked")
JobDetail jobDetail = JobBuilder.newJob(job).withIdentity(scheduleJob.getName(), scheduleJob.getGroup()).build();
//表达式调度构建器(可判断创建SimpleScheduleBuilder)
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleJob.getCronExpression());
jobDetail.getJobDataMap().put("scheduleJob", scheduleJob);
//按新的cronExpression表达式构建一个新的trigger
CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(scheduleJob.getName(), scheduleJob.getGroup()).withSchedule(scheduleBuilder).build();
try {
scheduler.scheduleJob(jobDetail, trigger);
} catch (SchedulerException e) {
e.printStackTrace();
}
}
/**
* 获取所有计划中的任务
* @return 结果集合
*/
public List<ScheduleJob> getAllScheduleJob(){
List<ScheduleJob> scheduleJobList=new ArrayList<ScheduleJob>();
GroupMatcher<JobKey> matcher = GroupMatcher.anyJobGroup();
try {
Set<JobKey> jobKeys = scheduler.getJobKeys(matcher);
for (JobKey jobKey : jobKeys) {
List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);
for (Trigger trigger : triggers) {
ScheduleJob scheduleJob = new ScheduleJob();
scheduleJob.setName(jobKey.getName());
scheduleJob.setGroup(jobKey.getGroup());
Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
scheduleJob.setStatus(triggerState.name());
//获取要执行的定时任务类名
JobDetail jobDetail=scheduler.getJobDetail(jobKey);
scheduleJob.setClassName(jobDetail.getJobClass().getName());
if (trigger instanceof CronTrigger) {
CronTrigger cron = (CronTrigger) trigger;
scheduleJob.setCronExpression(cron.getCronExpression());
}
scheduleJobList.add(scheduleJob);
}
}
} catch (Exception e) {
e.printStackTrace();
}
return scheduleJobList;
}
/**
* 恢复任务
* @param name 任务名
* @param group 任务组
*/
public void restartJob(String[] name,String[] group){
for(int i=0;i<name.length;i++){
JobKey key = new JobKey(name[i], group[i]);
try {
scheduler.resumeJob(key);
} catch (SchedulerException e) {
e.printStackTrace();
}
}
}
/**
* 立马执行一次任务
* @param name 任务名
* @param group 任务组
*/
public void startNowJob(String[] name,String[] group){
for(int i=0;i<name.length;i++){
JobKey jobKey = JobKey.jobKey(name[i], group[i]);
try {
scheduler.triggerJob(jobKey);
} catch (SchedulerException e) {
e.printStackTrace();
}
}
}
/**
* 删除任务
* @param name 任务名
* @param group 任务组
*/
public void delJob(String[] name,String[] group){
for(int i=0;i<name.length;i++){
JobKey key = new JobKey(name[i], group[i]);
try {
scheduler.deleteJob(key);
} catch (SchedulerException e) {
e.printStackTrace();
}
}
}
/**
* 修改触发器时间
* @param name 任务名
* @param group 任务组
* @param cron cron表达式
*/
public void modifyTrigger(ScheduleJob scheduleJob){
try {
TriggerKey key = TriggerKey.triggerKey(scheduleJob.getName(), scheduleJob.getGroup());
//Trigger trigger = scheduler.getTrigger(key);
CronTrigger newTrigger = (CronTrigger) TriggerBuilder.newTrigger()
.withIdentity(key)
.withSchedule(CronScheduleBuilder.cronSchedule(scheduleJob.getCronExpression()))
.build();
scheduler.rescheduleJob(key, newTrigger);
} catch (SchedulerException e) {
e.printStackTrace();
}
}
/**
* 暂停任务
* @param name 任务名
* @param group 任务组
*/
public void stopJob(String[] name,String[] group){
for(int i=0;i<name.length;i++){
JobKey key = new JobKey(name[i], group[i]);
try {
scheduler.pauseJob(key);
} catch (SchedulerException e) {
e.printStackTrace();
}
}
}
}
上面代码可以看到Scheduler 是通过spring工厂类注入生成的,然后进行任务的调度。
这样运行的话,就会出现同时运行多个任务,然后可能只有一个任务执行,再或者一个都不允许(第一次正常,下一次就全部error
情况。
然后可以修改整体的方式:
只需要一个 quartz.properties配置文件在src下,内容
#==============================================================
#Configure Main Scheduler Properties
#==============================================================
org.quartz.scheduler.instanceName = TestScheduler1
org.quartz.scheduler.instanceId = AUTO
#==============================================================
#Configure ThreadPool
#==============================================================
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 5
org.quartz.threadPool.threadPriority = 5
#==============================================================
#Configure JobStore
#==============================================================
org.quartz.jobStore.misfireThreshold = 60000
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.tablePrefix = QRTZ_
org.quartz.jobStore.dataSource = qzDS
org.quartz.jobStore.isClustered = true
org.quartz.jobStore.clusterCheckinInterval = 15000
#==============================================================
#Non-Managed Configure Datasource
#==============================================================
#JDBC
org.quartz.dataSource.qzDS.driver:com.mysql.jdbc.Driver
org.quartz.dataSource.qzDS.URL:jdbc:mysql://10.100.19.157:3306/accent-sys-dev?useUnicode=true&characterEncoding=utf-8
org.quartz.dataSource.qzDS.user:root
org.quartz.dataSource.qzDS.password:root
org.quartz.dataSource.qzDS.maxConnection:10
然后修改实现类
package com.credithc.accent.service.impl;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import javax.annotation.PostConstruct;
import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.quartz.impl.StdSchedulerFactory;
import org.quartz.impl.matchers.GroupMatcher;
import org.springframework.stereotype.Service;
import com.credithc.accent.model.ScheduleJob;
import com.credithc.accent.service.ScheduleJobService;
/**
* 定时任务 service
* @author ty
* @date 2015年1月13日
*/
@Service("scheduleJobService")
public class ScheduleJobServiceImpl implements ScheduleJobService{
@PostConstruct
public void initSchedule(){
Scheduler scheduler;
try {
scheduler = StdSchedulerFactory.getDefaultScheduler();
scheduler.start();
} catch (SchedulerException e) {
e.printStackTrace();
}
}
/**
* 添加定时任务
* @param ScheduleJob
*/
public void add(ScheduleJob scheduleJob){
@SuppressWarnings("rawtypes")
Class job = null;
try {
job = Class.forName(scheduleJob.getClassName());
} catch (ClassNotFoundException e1) {
e1.printStackTrace();
}
@SuppressWarnings("unchecked")
JobDetail jobDetail = JobBuilder.newJob(job).withIdentity(scheduleJob.getName(), scheduleJob.getGroup()).build();
//表达式调度构建器(可判断创建SimpleScheduleBuilder)
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleJob.getCronExpression());
jobDetail.getJobDataMap().put("scheduleJob", scheduleJob);
//按新的cronExpression表达式构建一个新的trigger
CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(scheduleJob.getName(), scheduleJob.getGroup()).withSchedule(scheduleBuilder).build();
try {
// 3、创建Scheduler
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
scheduler.start();
// 4、调度执行
scheduler.scheduleJob(jobDetail, trigger);
} catch (SchedulerException e) {
e.printStackTrace();
}
}
/**
* 获取所有计划中的任务
* @return 结果集合
*/
public List<ScheduleJob> getAllScheduleJob(){
List<ScheduleJob> scheduleJobList=new ArrayList<ScheduleJob>();
GroupMatcher<JobKey> matcher = GroupMatcher.anyJobGroup();
try {
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
Set<JobKey> jobKeys = scheduler.getJobKeys(matcher);
for (JobKey jobKey : jobKeys) {
List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);
for (Trigger trigger : triggers) {
ScheduleJob scheduleJob = new ScheduleJob();
scheduleJob.setName(jobKey.getName());
scheduleJob.setGroup(jobKey.getGroup());
Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
scheduleJob.setStatus(triggerState.name());
//获取要执行的定时任务类名
JobDetail jobDetail=scheduler.getJobDetail(jobKey);
scheduleJob.setClassName(jobDetail.getJobClass().getName());
if (trigger instanceof CronTrigger) {
CronTrigger cron = (CronTrigger) trigger;
scheduleJob.setCronExpression(cron.getCronExpression());
}
scheduleJobList.add(scheduleJob);
}
}
} catch (Exception e) {
e.printStackTrace();
}
return scheduleJobList;
}
/**
* 恢复任务
* @param name 任务名
* @param group 任务组
*/
public void restartJob(String[] name,String[] group){
for(int i=0;i<name.length;i++){
JobKey key = new JobKey(name[i], group[i]);
try {
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
scheduler.start();
scheduler.resumeJob(key);
} catch (SchedulerException e) {
e.printStackTrace();
}
}
}
/**
* 立马执行一次任务
* @param name 任务名
* @param group 任务组
*/
public void startNowJob(String[] name,String[] group){
for(int i=0;i<name.length;i++){
JobKey jobKey = JobKey.jobKey(name[i], group[i]);
try {
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
scheduler.start();
scheduler.triggerJob(jobKey);
} catch (SchedulerException e) {
e.printStackTrace();
}
}
}
/**
* 删除任务
* @param name 任务名
* @param group 任务组
*/
public void delJob(String[] name,String[] group){
for(int i=0;i<name.length;i++){
JobKey key = new JobKey(name[i], group[i]);
try {
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
scheduler.deleteJob(key);
} catch (SchedulerException e) {
e.printStackTrace();
}
}
}
/**
* 修改触发器时间
* @param name 任务名
* @param group 任务组
* @param cron cron表达式
*/
public void modifyTrigger(ScheduleJob scheduleJob){
try {
TriggerKey key = TriggerKey.triggerKey(scheduleJob.getName(), scheduleJob.getGroup());
//Trigger trigger = scheduler.getTrigger(key);
CronTrigger newTrigger = (CronTrigger) TriggerBuilder.newTrigger()
.withIdentity(key)
.withSchedule(CronScheduleBuilder.cronSchedule(scheduleJob.getCronExpression()))
.build();
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
scheduler.start();
scheduler.rescheduleJob(key, newTrigger);
} catch (SchedulerException e) {
e.printStackTrace();
}
}
/**
* 暂停任务
* @param name 任务名
* @param group 任务组
*/
public void stopJob(String[] name,String[] group){
for(int i=0;i<name.length;i++){
JobKey key = new JobKey(name[i], group[i]);
try {
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
scheduler.start();
scheduler.pauseJob(key);
} catch (SchedulerException e) {
e.printStackTrace();
}
}
}
}
注意红色的代码(后面代码也有修改没有标记),通过quartz 的工厂方式生成,必须执行start();,默认这样工厂方式会直接加载 classpath下的quartz.properties配置文件
这样就完美解决了,多个任务执行会出现问题的情况。
其中蓝色代码 是解决,每次服务重启的话,定时任务不会自动起来执行的情况。