动态创建quartz作业
最近在公司的业务中遇到了需要动态创建quartz作业的需求(在定时推送任务创建后,还可以更改任务的执行方法、时间、参数等),这对于之前没用过quartz的我来说十分蛋疼。但在捣鼓了两三天后,还是做了出来,回过头再看也不是很难,这里记录一下大致的使用方法。
- spring版本4.1.6
- quartz版本2.2.1
1.首先新增一个JobDetail类,需要继承org.springframework.scheduling.quartz.QuartzJobBean类。如下:
此处命名为MyJobDetail
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.context.ApplicationContext;
import org.springframework.scheduling.quartz.QuartzJobBean;
import java.lang.reflect.Method;
/**
* 带参的JobClass
* Created by xiaoming on 2017/5/4.
*/
public class MyJobClass extends QuartzJobBean {
private Log logger = LogFactory.getLog(JobDetailWithParamBean.class);
private String targetObject; //执行job的对象
private String targetMethod; //执行job的方法
private Object arguments; //执行job的方法参数(如果方法不带参可以删除此参数)
private ApplicationContext ctx;//ApplicationContext
@Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
try {
//从ApplicationContext中获取job对象
Object bean = ctx.getBean(targetObject);
//通过反射获取job方法
Method m = bean.getClass().getMethod(targetMethod,String.class);
//执行方法(带参)
m.invoke(bean, arguments);
//执行方法(不带参)
//m.invoke(bean, null);
} catch (Exception e) {
logger.error(e);
}
}
//以下是注入方法
public void setApplicationContext(ApplicationContext applicationContext) {
this.ctx = applicationContext;
}
public void setTargetObject(String targetObject) {
this.targetObject = targetObject;
}
public void setTargetMethod(String targetMethod) {
this.targetMethod = targetMethod;
}
public void setArguments(Object arguments) {
this.arguments = arguments;
}
}
2.创建一个作业对象。如下:
此处命名为MyJob
public class MyJob {
public myMethod(String arguments){
/*
业务逻辑
*/
Date currentTime = new Date();
System.out.println(currentTime + "执行了作业方法,参数为:"+arguments);
}
}
在spring-application-task.xml中注册MyJob
quartz的配置就不贴了
<bean id="MyJob" class="com.xxx.MyJob"/>
3.创建一个作业对象的管理类。如下:
此处命名为JobManager
import com.mrwind.common.framework.spring.SpringContextHolder;
import com.mrwind.common.timeJob.MyJobDetail;
import org.quartz.*;
import org.quartz.utils.Key;
import org.springframework.scheduling.quartz.JobDetailFactoryBean;
import org.springframework.stereotype.Service;
/**
* Created by xiaoming on 2017/5/10.
* 动态管理trigger类
*/
@Service
public class JobManager {
//公用scheduler
private static Scheduler scheduler = (Scheduler)SpringContextHolder.getApplicationContext().getBean("schedulerFactory");
/**
* 清空定时作业
* 由于更新可能影响到执行的方法、时间等,并不能简单的只更改cron表达式,因此需要先删除相关作业再重新创建
* 仅更改时间可通过更改cron表达式来更新trigger的方法,不需要删除,这里不做赘述。
*
* @Param : scheduler 公用scheduler
* @Param : keyStringList triggerKey字符串集合
*/
private void clearScheduler(Scheduler scheduler,List<String> keyStringList)throws Exception{
for(String keyString : keyStringList){
//根据keyString和group获取TriggerKey(本例中为默认group)
TriggerKey triggerKey = TriggerKey.triggerKey(keyString, Key.DEFAULT_GROUP);
//根据TriggerKey获取trigger
CronTrigger trigger = (CronTrigger)scheduler.getTrigger(triggerKey);
if(trigger != null){
scheduler.pauseTrigger(triggerKey); // 停止触发器
scheduler.unscheduleJob(triggerKey); // 移除触发器
scheduler.deleteJob(trigger.getJobKey());// 删除任务
}
}
}
/**
* 创建一个定时任务
* @return triggerKey
* @Param scheduler 公用scheduler
* @Param targetTime 目标执行时间
* @Param objectName 作业对象名
* @Param method 作业方法
* @Param arguments 作业参数
*/
private void createSheduler(Scheduler scheduler,
Date targetTime,
String objectName,
String method,
Object arguments
)throws Exception{
//判断是否过期
if(targetTime.after(Calendar.getInstance().getTime())){
String jobName,keyString;
/*
业务逻辑定义jobName、keyString
*/
// 新建一个基于Spring的管理Job类
JobDetailFactoryBean jobDetailFactoryBean = new JobDetailFactoryBean();
Map<String,String> jobDataAsMap = new HashMap<>();
jobDataAsMap.put("targetObject",objectName); //作业对象
jobDataAsMap.put("targetMethod",method); //作业方法
jobDataAsMap.put("arguments",arguments); //作业方法的参数
jobDetailFactoryBean.setName(jobName); //job类命名
jobDetailFactoryBean.setJobDataAsMap(jobDataAsMap);
jobDetailFactoryBean.setJobClass(MyJobClass.class); //JobClass,就是在1中定义的类
jobDetailFactoryBean.afterPropertiesSet();
JobDetail jobDetail = jobDetailFactoryBean.getObject(); //获取JobDetail对象
String cronExpression = createCronExpression(targetTime);//创建cron表达式
// 表达式调度构建器
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression);
// 根据cronExpression表达式构建一个新的trigger
CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(keyString,Key.DEFAULT_GROUP)
.withSchedule(scheduleBuilder).build();
// 注入到管理类
scheduler.scheduleJob(jobDetail, trigger);
}
}
/**
* 创建cron表达式(此处为创建指定的时间点)
* @param targetTime
* @return
*/
private String createCronExpression(Date targetTime){
Calendar calendar = Calendar.getInstance();
calendar.setTime(remindTime);
int min = calendar.get(Calendar.MINUTE);
int hour = calendar.get(Calendar.HOUR_OF_DAY);
int day = calendar.get(Calendar.DATE);
int mon = calendar.get(Calendar.MONTH) + 1;
int year = calendar.get(Calendar.YEAR);
String cronExpression = "0 "+min+" "+hour+" "+day+" "+mon+" ? "+year;
return cronExpression;
}
}
Note:第一篇csdn博客结束。