quartz1.8和spring3.2.9。
quartz2.0以上和之下的版本差别有些不同。
我使用的是1.8版本的。
CREATE TABLE `report_tasks_manager` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键id',
`task_desc` varchar(255) DEFAULT NULL COMMENT '任务描述',
`task_name` varchar(100) NOT NULL COMMENT '任务名称',
`cron_expression` varchar(20) DEFAULT NULL COMMENT '任务执行表达式',
`method_name` varchar(20) DEFAULT NULL COMMENT '要执行的方法名',
`state` int(3) NOT NULL COMMENT '任务状态 0加入任务1取消任务',
`con_current` int(3) DEFAULT NULL COMMENT '是否并发执行 0并发1不并发',
`reserved1` varchar(32) DEFAULT NULL COMMENT '预留字段',
`reserved2` varchar(32) DEFAULT NULL COMMENT '预留字段2',
`reserved3` varchar(32) DEFAULT NULL COMMENT '预留字段3',
`start_time` datetime DEFAULT NULL COMMENT '任务开始执行时间',
`end_time` datetime DEFAULT NULL COMMENT '任务结束时间',
`create_time` datetime DEFAULT NULL COMMENT '任务创建时间',
PRIMARY KEY (`id`),
UNIQUE KEY `task_name` (`task_name`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8;
流程说明:
定时任务在后台开启,读取数据库中的任务信息(任务类,执行方法,执行时间等),判断定时触发器(trigger)中是否存在该任务。
1.1 如果存在该任务,比较数据库中的任务表达式(cron)是否与当前定时器中的时间一致。
1.1.1 如果不一致,更新当前任务时间表达式。
1.1.2 如果一致,跳至方法3。
1.2 如果不存在该任务,跳至方法2。
2. 如果不存在该任务,加入定时器任务中。
3.触发定时任务,执行定时任务方法。
主要包括spring的配置文件和java类的设计。
<bean id="taskExecutor"
class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
<property name="corePoolSize" value="1" />
<property name="maxPoolSize" value="20" />
<property name="queueCapacity" value="100" />
<property name="keepAliveSeconds" value="2000" />
<property name="rejectedExecutionHandler">
<bean class="java.util.concurrent.ThreadPoolExecutor$AbortPolicy" />
property>
bean>
<bean id="quartzManager" class="com.wasu.upm.report.quartz.QuartzManager">
<property name="scheduler" ref="schedulerManager" />
bean>
<bean id="quartzManagerJobDetail"
class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject" ref="quartzManager" />
<property name="targetMethod" value="reScheduleJob" />
<property name="concurrent" value="false" />
bean>
<bean id="cronTriggerBean" class="org.springframework.scheduling.quartz.SimpleTriggerBean">
<property name="jobDetail" ref="quartzManagerJobDetail" />
<property name="startDelay" value="0"/>
<property name="repeatInterval" value="20000" />
bean>
<bean id="schedulerManager" lazy-init="false" autowire="no"
class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<ref bean="cronTriggerBean" />
list>
property>
<property name="taskExecutor" ref="taskExecutor"/>
bean>
解释说明:
taskExecutor:设置任务的并发数量。例如我们想让线程单线程执行,即taskA开始执行–>taskA执行结束;taskB开始执行–>taskB执行结束;
quartzManager:定义一个定时任务,来进行其他定时任务的管理。
quartzManagerJobDetail:具体的任务类定义执行的方法。以及该任务是否并发执行。
concurrent=false指该任务不并发执行,为true指并发执行。
cronTriggerBean:设置执行的时间。
package com.wasu.upm.report.quartz;
import java.util.Date;
import java.util.List;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.CronTriggerBean;
import org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean;
import com.wasu.upm.commons.bo.ReportTasksManagerBo;
import com.wasu.upm.report.service.IReportManagerService;
public class QuartzManager implements BeanFactoryAware{
private final static Logger log = LoggerFactory
.getLogger(QuartzManager.class);
private Scheduler scheduler;
/**每隔1小时执行一次
*/
private static final String DEFAULT_CRON="* * */1 * * ?";
@Autowired
private IReportManagerService reportManagerService;
private static BeanFactory beanFactory;
public Scheduler getScheduler() {
return scheduler;
}
public void setScheduler(Scheduler scheduler) {
this.scheduler = scheduler;
}
/**
* 定时要执行的方法类。
*/
public void reScheduleJob(){
// 1.读取数据库中的任务列表,状态为0的任务。
Date currentDate = new Date();
List expireList = reportManagerService.findExpireTasks(currentDate);
if(expireList!=null && expireList.size()>0){
for(ReportTasksManagerBo bo : expireList){
//配置任务列表
removeExpireTasks(bo);
}
}
List list = reportManagerService.findTasks(currentDate);
if(list==null||list.size()==0){
log.warn("查询的任务列表为空");
return;
}
for(ReportTasksManagerBo bo : list){
//配置任务列表
configSchedul(bo);
}
}
/**
* 移除过期任务
* @param bo
*/
private void removeExpireTasks(ReportTasksManagerBo bo) {
try {
CronTriggerBean trigger = (CronTriggerBean) scheduler.getTrigger(bo.getTaskName(), Scheduler.DEFAULT_GROUP);
if(trigger!=null){
System.out.println("==移除任务=="+bo.getTaskName());
scheduler.pauseTrigger(trigger.getName(), trigger.getGroup());// 停止触发器
scheduler.unscheduleJob(trigger.getName(), trigger.getGroup());// 移除触发器
scheduler.deleteJob(trigger.getJobName(), trigger.getJobGroup());// 删除任务
}
} catch (SchedulerException e) {
log.error("移除任务失败...");
e.printStackTrace();
}
}
/**
* 配置任务列表
* @param bo
*/
private void configSchedul(ReportTasksManagerBo bo) {
try {
CronTriggerBean trigger = (CronTriggerBean) scheduler.getTrigger(bo.getTaskName(), Scheduler.DEFAULT_GROUP);
if(trigger==null){//说明schedule中不存在该定时任务
createTriggerTask(bo);
}else{
updateTriggerTask(bo,trigger);
}
} catch (SchedulerException e) {
log.error("获取触发器trigger失败...");
e.printStackTrace();
}
}
/**
* 更新任务列表
* @param bo
*/
private void updateTriggerTask(ReportTasksManagerBo bo,CronTriggerBean trigger) {
if(bo.getState()==0){
try{
// 判断从DB中取得的任务时间和现在的quartz线程中的任务时间是否相等
// 如果相等,则表示用户并没有重新设定数据库中的任务时间,这种情况不需要重新rescheduleJob
if(trigger.getCronExpression()!=null&&
!trigger.getCronExpression().equalsIgnoreCase(bo.getCronExpression())) {
System.out.println("=真正更新方法:="+bo.getTaskName());
trigger.setCronExpression(bo.getCronExpression());
scheduler.rescheduleJob(bo.getTaskName(),Scheduler.DEFAULT_GROUP, trigger);
log.info("更新任务时间失败...");
}
}catch(Exception e){
log.error("更新任务时间失败...");
e.printStackTrace();
}
}else{
this.removeExpireTasks(bo);
}
}
/**
* 创建任务列表
* @param bo
*/
private void createTriggerTask(ReportTasksManagerBo bo) {
if(bo.getState()==0){
System.out.println("=创建:="+bo.getTaskName());
MethodInvokingJobDetailFactoryBean mjdfb = new MethodInvokingJobDetailFactoryBean();
mjdfb.setBeanName(bo.getTaskName());
try{
Object obj = beanFactory.getBean(bo.getTaskName());
mjdfb.setTargetObject(obj);
mjdfb.setTargetMethod(bo.getMethodName());
boolean isConcurrent=false;
if(bo.getConCurrent()==0){
isConcurrent = true;
}
mjdfb.setConcurrent(isConcurrent);
mjdfb.afterPropertiesSet(); //将管理Job类提交到计划管理类
JobDetail jobDetail = new JobDetail();
jobDetail = mjdfb.getObject();
jobDetail.setName(bo.getTaskName());
scheduler.addJob(jobDetail, true); // 将Job添加到管理类
String cronExpression=null;
if(bo.getCronExpression()==null||"".equals(bo.getCronExpression())){
cronExpression=DEFAULT_CRON;
}else{
cronExpression = bo.getCronExpression();
}
// 新一个基于Spring的时间类
CronTriggerBean c = new CronTriggerBean();
c.setCronExpression(cronExpression);// 设置时间表达式
c.setName(bo.getTaskName());// 设置名称
c.setJobDetail(jobDetail);// 注入Job
c.setJobName(bo.getTaskName());// 设置Job名称
scheduler.scheduleJob(c);// 注入到管理类
scheduler.rescheduleJob(bo.getTaskName(), Scheduler.DEFAULT_GROUP,c);// 刷新管理类
}catch(Exception e){
log.error("创建"+bo.getTaskName()+"任务失败...");
e.printStackTrace();
}
}else{
this.removeExpireTasks(bo);
}
}
public void setBeanFactory(BeanFactory factory) throws BeansException {
this.beanFactory = factory;
}
public BeanFactory getBeanFactory() {
return beanFactory;
}
}