Spring4整合quartz2.2.3,quartz动态任务
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
©Copyright 蕃薯耀 2017年8月25日
http://fanshuyao.iteye.com/
可以跳过此篇,直接看总结篇:http://fanshuyao.iteye.com/blog/2392350
quartz下载
http://www.quartz-scheduler.org/downloads/
一、quartz动态任务管理类:
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.Job;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobExecutionContext;
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.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import cn.imovie.common.utils.CC;
import cn.imovie.common.utils.JasonUtils;
import cn.imovie.common.utils.SpringUtils;
import cn.imovie.entity.task.ScheduleJob;
import cn.imovie.service.ScheduleJobService;
public class SchedulerManage {
private Logger log = LoggerFactory.getLogger(SchedulerManage.class);
private Scheduler scheduler = (Scheduler) SpringUtils.getBeanById("scheduler");
@Autowired
private ScheduleJobService scheduleJobService;
/**
* 新增任务
* @param scheduleJob
*/
@SuppressWarnings("unchecked")
public void addJob(ScheduleJob scheduleJob){
TriggerKey triggerKey = TriggerKey.triggerKey(scheduleJob.getJobName(), scheduleJob.getJobGroup());
try {
//任务触发
CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
if (null == trigger) {
JobDetail jobDetail = JobBuilder.newJob((Class<? extends Job>) Class.forName(scheduleJob.getClazz()))
.withIdentity(scheduleJob.getJobName(), scheduleJob.getJobGroup()).build();
jobDetail.getJobDataMap().put("scheduleJob", scheduleJob);
CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleJob.getCronExpression());
/*withMisfireHandlingInstructionDoNothing
——不触发立即执行
——等待下次Cron触发频率到达时刻开始按照Cron频率依次执行
withMisfireHandlingInstructionIgnoreMisfires
——以错过的第一个频率时间立刻开始执行
——重做错过的所有频率周期后
——当下一次触发频率发生时间大于当前时间后,再按照正常的Cron频率依次执行
withMisfireHandlingInstructionFireAndProceed
——以当前时间为触发频率立刻触发一次执行
——然后按照Cron频率依次执行*/
trigger = TriggerBuilder.newTrigger().withIdentity(scheduleJob.getJobName(), scheduleJob.getJobGroup()).withSchedule(cronScheduleBuilder.withMisfireHandlingInstructionDoNothing()).build();
scheduler.scheduleJob(jobDetail, trigger);
log.info(CC.LOG_PREFIX + "新增任务:"+JasonUtils.Object2String(scheduleJob));
}else {
// Trigger已存在,那么更新相应的定时设置
//表达式调度构建器
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleJob.getCronExpression());
//按新的cronExpression表达式重新构建trigger
trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder.withMisfireHandlingInstructionDoNothing()).build();
//按新的trigger重新设置job执行
scheduler.rescheduleJob(triggerKey, trigger);
log.info(CC.LOG_PREFIX + "任务"+JasonUtils.Object2String(scheduleJob)+"已经存在,更新trigger");
}
//scheduleJobService.save(req, sysUserInSession, scheduleJob);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 暂停任务
* @param scheduleJob
*/
public void pauseJob(ScheduleJob scheduleJob){
JobKey jobKey = JobKey.jobKey(scheduleJob.getJobName(), scheduleJob.getJobGroup());
try {
scheduler.pauseJob(jobKey);
log.info(CC.LOG_PREFIX + "暂停任务:"+JasonUtils.Object2String(scheduleJob));
} catch (SchedulerException e) {
e.printStackTrace();
}
}
/**
* 暂停全部任务
*/
public void pauseAll(){
try {
scheduler.pauseAll();
log.info(CC.LOG_PREFIX + "暂停所有任务");
} catch (SchedulerException e) {
e.printStackTrace();
}
}
/**
* 恢复任务
* @param scheduleJob
*/
public void resumeJob(ScheduleJob scheduleJob){
JobKey jobKey = JobKey.jobKey(scheduleJob.getJobName(), scheduleJob.getJobGroup());
try {
scheduler.resumeJob(jobKey);
log.info(CC.LOG_PREFIX + "恢复任务:"+JasonUtils.Object2String(scheduleJob));
} catch (SchedulerException e) {
e.printStackTrace();
}
}
/**
* 恢复所有任务
*/
public void resumeAll(){
try {
scheduler.resumeAll();
log.info(CC.LOG_PREFIX + "恢复所有任务");
} catch (SchedulerException e) {
e.printStackTrace();
}
}
/**
* 删除任务后,所对应的trigger也将被删除
* @param scheduleJob
*/
public void deleteJob(ScheduleJob scheduleJob){
JobKey jobKey = JobKey.jobKey(scheduleJob.getJobName(), scheduleJob.getJobGroup());
try {
scheduler.pauseJob(jobKey);//先暂停任务
scheduler.deleteJob(jobKey);//再删除任务
log.info(CC.LOG_PREFIX + "删除任务:"+JasonUtils.Object2String(scheduleJob));
} catch (SchedulerException e) {
e.printStackTrace();
}
}
/**
* 立即运行任务
* @param scheduleJob
*/
public void triggerJob(ScheduleJob scheduleJob){
JobKey jobKey = JobKey.jobKey(scheduleJob.getJobName(), scheduleJob.getJobGroup());
try {
scheduler.triggerJob(jobKey);
log.info(CC.LOG_PREFIX + "运行任务:"+JasonUtils.Object2String(scheduleJob));
} catch (SchedulerException e) {
e.printStackTrace();
}
}
/**
* 更新任务的时间表达式
* @param scheduleJob
*/
public void updateJob(ScheduleJob scheduleJob){
try {
TriggerKey triggerKey = TriggerKey.triggerKey(scheduleJob.getJobName(), scheduleJob.getJobGroup());
//获取trigger,即在spring配置文件中定义的 bean id="myTrigger"
CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
//表达式调度构建器
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleJob.getCronExpression());
//按新的cronExpression表达式重新构建trigger
trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder.withMisfireHandlingInstructionDoNothing()).build();
//按新的trigger重新设置job执行
scheduler.rescheduleJob(triggerKey, trigger);
log.info(CC.LOG_PREFIX + "更新任务:"+JasonUtils.Object2String(scheduleJob));
} catch (SchedulerException e) {
e.printStackTrace();
}
}
/**
* 获取quartz调度器的计划任务
* @return
*/
public List<ScheduleJob> getScheduleJobList(){
List<ScheduleJob> jobList = null;
try {
GroupMatcher<JobKey> matcher = GroupMatcher.anyJobGroup();
Set<JobKey> jobKeys = scheduler.getJobKeys(matcher);
jobList = new ArrayList<ScheduleJob>();
for (JobKey jobKey : jobKeys) {
List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);
for (Trigger trigger : triggers) {
ScheduleJob job = new ScheduleJob();
job.setJobName(jobKey.getName());
job.setJobGroup(jobKey.getGroup());
job.setClazz(jobKey.getClass().toString());
job.setJobDesc("触发器:" + trigger.getKey());
Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
job.setJobStatus(triggerState.name());
if (trigger instanceof CronTrigger) {
CronTrigger cronTrigger = (CronTrigger) trigger;
String cronExpression = cronTrigger.getCronExpression();
job.setCronExpression(cronExpression);
}
jobList.add(job);
}
}
} catch (Exception e) {
e.printStackTrace();
}
return jobList;
}
/**
* 获取quartz调度器的运行任务
* @return
*/
public List<ScheduleJob> getScheduleJobRunningList(){
List<ScheduleJob> jobList = null;
try {
List<JobExecutionContext> executingJobs = scheduler.getCurrentlyExecutingJobs();
jobList = new ArrayList<ScheduleJob>(executingJobs.size());
for (JobExecutionContext executingJob : executingJobs) {
ScheduleJob job = new ScheduleJob();
JobDetail jobDetail = executingJob.getJobDetail();
JobKey jobKey = jobDetail.getKey();
Trigger trigger = executingJob.getTrigger();
job.setJobName(jobKey.getName());
job.setJobGroup(jobKey.getGroup());
job.setClazz(jobKey.getClass().toString());
job.setJobDesc("触发器:" + trigger.getKey());
Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
job.setJobStatus(triggerState.name());
if (trigger instanceof CronTrigger) {
CronTrigger cronTrigger = (CronTrigger) trigger;
String cronExpression = cronTrigger.getCronExpression();
job.setCronExpression(cronExpression);
}
jobList.add(job);
}
} catch (Exception e) {
e.printStackTrace();
}
return jobList;
}
public Scheduler getScheduler() {
return scheduler;
}
public void setScheduler(Scheduler scheduler) {
this.scheduler = scheduler;
}
}
注意事项:
1、SchedulerFactoryBean 在spring.xml配置了,但不能直接注入,就算加上@Component注解也不行,所以使用SpringUtils 工具类获取。
<bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
2、获取到的SchedulerFactoryBean 并不是SchedulerFactoryBean,而是scheduler
private Scheduler scheduler = (Scheduler) SpringUtils.getBeanById("scheduler");
二、ScheduleJob 类:可以保存计划任务的信息,也可以做为实体参数
public class ScheduleJob implements Serializable{
private Long scheduleJobId;
/** 任务名称 */
private String jobName;
/** 任务分组 */
private String jobGroup;
/** 定时任务对应的类(包括包路径),如:cn.imovie.manage.task.job.TicketMoneyLessThanNormalWarn */
private String clazz;
/** 任务状态:1禁用 2启用 3删除*/
private String jobStatus;
/** 任务运行时间表达式 */
private String cronExpression;
/** 任务描述 */
private String jobDesc;
private Long createMan;
private Date createTime;
private Long updateMan;
private Date updateTime;
// 非持久化属性
private String createManText;
private String updateManText;
public Long getScheduleJobId() {
return scheduleJobId;
}
public void setScheduleJobId(Long scheduleJobId) {
this.scheduleJobId = scheduleJobId;
}
public String getJobName() {
return jobName;
}
public void setJobName(String jobName) {
this.jobName = jobName;
}
public String getJobGroup() {
return jobGroup;
}
public void setJobGroup(String jobGroup) {
this.jobGroup = jobGroup;
}
public String getClazz() {
return clazz;
}
public void setClazz(String clazz) {
this.clazz = clazz;
}
public String getJobStatus() {
return jobStatus;
}
public void setJobStatus(String jobStatus) {
this.jobStatus = jobStatus;
}
public String getCronExpression() {
return cronExpression;
}
public void setCronExpression(String cronExpression) {
this.cronExpression = cronExpression;
}
public String getJobDesc() {
return jobDesc;
}
public void setJobDesc(String jobDesc) {
this.jobDesc = jobDesc;
}
public Long getCreateMan() {
return createMan;
}
public void setCreateMan(Long createMan) {
this.createMan = createMan;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
public Long getUpdateMan() {
return updateMan;
}
public void setUpdateMan(Long updateMan) {
this.updateMan = updateMan;
}
public Date getUpdateTime() {
return updateTime;
}
public void setUpdateTime(Date updateTime) {
this.updateTime = updateTime;
}
@Transient
public String getCreateManText() {
return createManText;
}
public void setCreateManText(String createManText) {
this.createManText = createManText;
}
@Transient
public String getUpdateManText() {
return updateManText;
}
public void setUpdateManText(String updateManText) {
this.updateManText = updateManText;
}
}
三、Spring.xml 文件配置
<!-- 定时任务配置 start --> <bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <property name="dataSource" ref="dataSource"></property> <!--可选,QuartzScheduler 启动时更新己存在的Job,这样就不用每次修改targetObject后删除qrtz_job_details表对应记录了 --> <property name="overwriteExistingJobs" value="true" /> <!--必须的,QuartzScheduler 延时启动,应用启动完后 QuartzScheduler 再启动 --> <property name="startupDelay" value="10" /> <!-- 设置自动启动 --> <property name="autoStartup" value="true" /> <property name="applicationContextSchedulerContextKey" value="applicationContextKey" /> <property name="configLocation" value="classpath:spring-quartz.properties" /> </bean> <bean id="schedulerManage" class="cn.imovie.manage.task.SchedulerManage"></bean> <!-- 定时任务配置 end -->
四、spring-quartz.properties 文件配置:
#配置见:http://www.quartz-scheduler.org/documentation/quartz-2.2.x/configuration/ConfigJDBCJobStoreClustering.html
#============================================================================
# Configure Main Scheduler Properties
#============================================================================
org.quartz.scheduler.instanceName = MyClusteredScheduler
org.quartz.scheduler.instanceId = AUTO
#============================================================================
# Configure ThreadPool
#============================================================================
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 25
org.quartz.threadPool.threadPriority = 5
#============================================================================
# Configure JobStore
#============================================================================
org.quartz.jobStore.misfireThreshold = 60000
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
org.quartz.jobStore.useProperties = false
org.quartz.jobStore.dataSource = myDS
org.quartz.jobStore.tablePrefix = QRTZ_
org.quartz.jobStore.isClustered = true
org.quartz.jobStore.clusterCheckinInterval = 20000
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
©Copyright 蕃薯耀 2017年8月25日
http://fanshuyao.iteye.com/