适用于:
动态修改定时任务,根据数据库的定时任务进行任务的激活和暂停,带参定时任务,指定时间和执行次数的定时任务等。
1、概述
在开发中有的时候需要去手动禁止和启用定时任务,修改定时任务的cron表达式然后再让其动态生效,之前有过SSM的类似的业务的开发但是忘记写下来了。。。只好重新温习了一次,加上最近比较流行springBoot所以升级了一下用springBoot来完成.
2、关联技术
SpringBoot、Quartz、mysql、thymeleaf (好像就这么多)
3、涉及核心API 类
4、具体流程
1)首先去手动创建一个调度器工厂对象-SchedulerFactoryBean;其实应该不用手动创建的但是为了顾及到业务的复杂性所以还是创建一个好用。
2)继承job,实现方法execute。此处手写的原因是因为我们需要对定时任务的功能进行扩展,比如文中提到的参数注入和执行日志记录.注意jobExecutionContext.getMergedJobDataMap() 它可以获得 JobDataMap这个是Job实例化的一些信息,可以用于定时任务的带参。如下:
1 import com.study.www.enums.ConfigEnum; 2 import com.study.www.model.Config; 3 import com.study.www.model.Logger; 4 import com.study.www.model.mapper.LoggerRepository; 5 import com.study.www.utils.TaskUtils; 6 import org.quartz.DisallowConcurrentExecution; 7 import org.quartz.Job; 8 import org.quartz.JobExecutionContext; 9 import org.quartz.JobExecutionException; 10 import org.springframework.scheduling.annotation.Async; 11 import org.springframework.stereotype.Component; 12 13 import java.util.ArrayList; 14 import java.util.List; 15 16 17 //当上一个任务未结束时下一个任务需进行等待 18 @DisallowConcurrentExecution 19 @Component 20 public class MyJob implements Job { 21 22 //注意此处的 Dao 直接 @Autowired 注入是获取不到的,我们可以通过Spring容器去进行手动注入 23 static LoggerRepository loggerRepository; 24 //定时任务日志落地 25 static List<Logger> loggers=new ArrayList<>(); 26 //每10条日志进行一下落地 27 private final static Integer SIZE=9; 28 29 //execute会根据cron的规则进行执行 30 @Override 31 public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException { 32 Config config = (Config) jobExecutionContext.getMergedJobDataMap().get(ConfigEnum.SCHEDULEJOB.getCode()); 33 Long beginTime=null; 34 if (config.getIsLogger()){ 35 beginTime=System.currentTimeMillis(); 36 } 37 TaskUtils.invokMethod(config); 38 if (beginTime != null) { 39 //手动注入 Dao 40 if (MyJob.loggerRepository == null){ 41 MyJob.loggerRepository = SpringUtils.getBean("loggerRepository"); 42 } 43 saveSysLog(beginTime,config); 44 } 45 } 46 47 48 @Async 49 void saveSysLog(Long beginTime, Config config) { 50 Logger logger = new Logger(); 51 logger.setBeginTime(beginTime); 52 logger.setEndTime(System.currentTimeMillis()); 53 logger.setClassPath(config.getClassPath()); 54 logger.setMethName(config.getMethodName()); 55 logger.setName(config.getName()); 56 logger.setGroupName(config.getGroup()); 57 logger.setTime(System.currentTimeMillis()-beginTime); 58 logger.setParams(config.getReqParms()); 59 if (loggers.size() > SIZE) { 60 synchronized (MyJob.class) { 61 loggerRepository.save(loggers); 62 loggers.clear(); 63 } 64 }else{ 65 loggers.add(logger); 66 } 67 } 68 69 }
3)获取到调度器-Scheduler和JobBuilder以及TriggerBuilder
4)实现动态新增、删除定时任务的方法.此处的 trigger 触发机制有两种 一种是Cron 一种是 选择时间和时间间隔的。因为有一种业务情况为客户去手动选择时间进行定时任务发送。
5)创建对定时任务的方法进行反射执行的方法。如下:
提示: 页面用户修改Cron 表达式如果需要对Cron表达式进行校验可以使用如下方法。
提示: 如果定时任务的带参为不固定的比如是另外的一个请求等,可以修改 步骤 5中的规则。例如可以在Config 中加个用来进行参数类型判断的字段,然后参数为 一个http请求这样可以做到在定时任务中进行一个请求后再任务的执行。
若时间充裕推荐这封博客其对Quartz将的更加详细,配合示例看可以有着事半功倍的效果。http://ifeve.com/quartz-tutorial-using-quartz/
代码例子:
码云:https://gitee.com/zhuyanpengWorld/springboots/blob/master/quartz.rar