利用quartz实现动态创建任务,主要涉及的类有Job
,JobDetail
,CronScheduleBuilder
,CronTrigger
,Scheduler
.
- Job:接口,对应到具体要做的事情。通常是业务代码实现。
- JobDetail:接口,封装了
Job
相关的信息,比如key,description,jobDataMap等。JobDataMap
用来传递数据到job中。
- CronScheduleBuilder:表达式任务的builder。
- CronTrigger:支持表达式的trigger。
ScheduleJob
为了动态添加,我们自己也封装了一下job相关的信息,包括名称,分组,表达式以及要执行的java方法。
1 2 3 4 5 6 7 8 9 10 11 12 13
|
private String jobId;
private String jobName;
private String jobGroup;
private String jobStatus;
private String cronExpression;
private String description;
|
数据来源可以是配置在数据库中,通过查询来构造ScheduleJob
信息;测试的时候可以直接new一个ScheduleJob
对象。
QuartzStatefulJobFactory
实现一个Job,去调用我们自己的业务类。这种方式可以使用我们的job无需实现任务quartz的接口,从而实现解耦。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| @DisallowConcurrentExecution public class QuartzStatefulJobFactory implements Job{ public static final String JOB_NAME_SEPARATOR = "."; private static Logger logger = LoggerFactory.getLogger(QuartzStatefulJobFactory.class); @Override public void execute(JobExecutionContext context) throws JobExecutionException { logger.debug("任务开始运行"); ScheduleJob scheduleJob = (ScheduleJob)context.getMergedJobDataMap().get("scheduleJob"); logger.debug("任务名称 = [" + scheduleJob.getJobName() + "]"); String classPath = scheduleJob.getClassPath(); if (StringUtils.isBlank(classPath)){ logger.warn("任务类为空,忽略"); return; } String className = classPath; String methodName = "execute"; if (StringUtils.endsWith(classPath,"()")){ int lastNameIndex = StringUtils.lastIndexOf(classPath,JOB_NAME_SEPARATOR); className = StringUtils.substring(classPath,0,lastNameIndex); methodName = StringUtils.substring(classPath,lastNameIndex + 1, StringUtils.indexOf(classPath, "()")); } try { Class jobClass = ClassUtils.forName(className,ClassUtils.getDefaultClassLoader());
Object target = jobClass.newInstance(); Method method = ReflectionUtils.findMethod(jobClass,methodName); ReflectionUtils.invokeMethod(method,target); } catch (Exception e) { logger.error("未找到所描述的类",e); throw new JobExecutionException(e); } } }
|
QuartzManager
提供一个静态方法来添加job
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| public class QuartzManager {
public static void addJob(Scheduler sched, ScheduleJob job, JobListener listener) { try { JobDetail jobDetail = JobBuilder.newJob( QuartzStatefulJobFactory.class) .withIdentity(job.getJobName(),job.getJobGroup()).withDescription(job.getDescription()).build(); jobDetail.getJobDataMap().put("scheduleJob", job); CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression()); CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(job.getJobName(), job.getJobGroup()).withSchedule(scheduleBuilder).build();
sched.getListenerManager().addJobListener(listener); sched.scheduleJob(jobDetail,trigger); } catch (Exception e) { throw new JobScheduleException(e); } } }
|
Quartz
也提供了一些诸如一天的某点、重复这样简单的表达式,如CronScheduleBuilder
的dailyAtHourAndMinute方法,DailyTimeIntervalScheduleBuilder
,SimpleScheduleBuilder
。