前言:
最近在做Java开发对接微信公众平台之类的工作,在开发过程中遇到一个需求是定时任务这块的,但是普通的定时任务还远远不能满足;最后要实现的效果是每个任务都是不同的定时时间来执行而且是在前台页面上来控制这些任务的创建,取消,开启,暂停;就好比是向数据库添加一条记录(任务)那么在添加成功后这个任务就是进入定时执行状态了,每次执行的时间是由添加任务时前台页面选择的时间;
要实现的效果如下:
该项目的整体框架和环境选用的时SpringBoot,所以当时在网上看了大部分的boot整合Quartz的文章发现都存在bug和漏洞并且很麻烦和繁琐;通过在网上参考相关的文章加上之前积攒的知识,整合了一套简单并且实用的以上需求相关代码,可以参考。
pom:
<dependency> <groupId>org.quartz-schedulergroupId> <artifactId>quartzartifactId> <version>2.2.1version>dependency>
在项目的基础上需要添加上quartz的依赖包;(其他boot之类的依赖包就不一一说明了)
需要在启动类上开启定时任务
定时任务管理类:
import com.redleaves.wechat.api.core.Result;import com.redleaves.wechat.api.core.ResultGenerator;import com.redleaves.wechat.api.model.TTemplateMessage;import lombok.extern.slf4j.Slf4j;import org.quartz.*;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;/** * @author Mr.Gu * @date 2020/8/3 16:17 * @function : 定时任务的管理 **/@Slf4j@Servicepublic class SchedulerBuilder { @Autowired private Scheduler scheduler; /** * 新建job * @param job * @param clazz * @return */ public Result createJob(TTemplateMessage job, Class clazz) { try { if (!((clazz.newInstance()) instanceof Job)){ return ResultGenerator.genFailResult("必须实现job接口"); } TriggerKey triggerKey = TriggerKey.triggerKey(job.getId().toString()); //获取trigger CronTrigger trigger = null; trigger = (CronTrigger) scheduler.getTrigger(triggerKey); //不存在,创建一个 if (null == trigger) { JobDetail jobDetail = JobBuilder.newJob(clazz) .withIdentity(job.getId().toString()).build(); jobDetail.getJobDataMap().put("scheduleJob", job); //表达式调度构建器 CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCorn()); //按新的cronExpression表达式构建一个新的trigger trigger = TriggerBuilder.newTrigger().withIdentity(job.getId().toString()).withSchedule(scheduleBuilder).build(); scheduler.scheduleJob(jobDetail, trigger); log.info("id为:{},推送名称为:{}的任务创建成功",job.getId(),job.getName()); return ResultGenerator.genSuccessResult(); }else{ return ResultGenerator.genFailResult("job已经存在,请检查名称是否重复"); } } catch (Exception e) { e.printStackTrace(); } return null; } /** * 立即执行job 是对已经存在的定时任务执行 * @param job * @return */ public Result executeJob(TTemplateMessage job) { JobKey jobKey = JobKey.jobKey(job.getId().toString()); try { scheduler.triggerJob(jobKey); return ResultGenerator.genSuccessResult(); } catch (SchedulerException e) { e.printStackTrace(); return ResultGenerator.genFailResult("操作失败"); } } /** * 更新执行时间 * @param job * @return */ public Result updateJobCron(TTemplateMessage job) { TriggerKey triggerKey = TriggerKey.triggerKey(job.getId().toString()); //获取trigger,即在spring配置文件中定义的 bean id="myTrigger" CronTrigger trigger = null; try { trigger = (CronTrigger) scheduler.getTrigger(triggerKey); } catch (SchedulerException e) { e.printStackTrace(); } //表达式调度构建器 CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCorn()); //按新的cronExpression表达式重新构建trigger trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build(); //按新的trigger重新设置job执行 try { scheduler.rescheduleJob(triggerKey, trigger); return ResultGenerator.genSuccessResult(); } catch (SchedulerException e) { e.printStackTrace(); return ResultGenerator.genFailResult("操作失败"); } } /** * 暂停job运行 * @param job * @return*/ public Result pauseJob(TTemplateMessage job) { JobKey jobKey = JobKey.jobKey(job.getId().toString()); try { scheduler.pauseJob(jobKey); return ResultGenerator.genSuccessResult(); } catch (SchedulerException e) { e.printStackTrace(); return ResultGenerator.genFailResult("操作失败"); } } /** * 恢复job运行 * @param job * @return*/ public Result resumeJob(TTemplateMessage job) { JobKey jobKey = JobKey.jobKey(job.getId().toString()); try { scheduler.resumeJob(jobKey); return ResultGenerator.genSuccessResult(); } catch (SchedulerException e) { e.printStackTrace(); return ResultGenerator.genFailResult("操作失败"); } } /* * * 删除job信息 * @param job * @return*/ public Result delJob(TTemplateMessage job) { JobKey jobKey = JobKey.jobKey(job.getId().toString()); TriggerKey triggerKey = TriggerKey.triggerKey(job.getId().toString()); try { scheduler.pauseTrigger(triggerKey);// 停止触发器 scheduler.unscheduleJob(triggerKey);// 移除触发器 scheduler.deleteJob(jobKey);//删除job return ResultGenerator.genSuccessResult(); } catch (SchedulerException e) { e.printStackTrace(); return ResultGenerator.genFailResult("操作失败"); } }}
任务触发后具体的执行逻辑的实现:
import com.redleaves.wechat.api.dao.TTemplateMessageMapper;import com.redleaves.wechat.api.model.TTemplateMessage;import com.redleaves.wechat.api.service.SendTemplateService;import lombok.extern.slf4j.Slf4j;import org.quartz.*;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.context.support.SpringBeanAutowiringSupport;import javax.annotation.Resource;/** * @author Mr.Gu * @date 2020/8/3 13:36 * @function : 定时任务触发器 **/@Slf4jpublic class MyJob implements Job { private JobDataMap jobmap = null; /** * 定时任务触发后任务的具体执行逻辑 * @param paramJobExecutionContext * @throws JobExecutionException */ @Override public void execute(JobExecutionContext paramJobExecutionContext) throws JobExecutionException { SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this); TTemplateMessage tTemplateMessage = new TTemplateMessage(); this.jobmap = paramJobExecutionContext.getJobDetail().getJobDataMap(); tTemplateMessage = (TTemplateMessage) jobmap.get("scheduleJob"); log.info("开始执行任务id:{};推送名称为:{}",tTemplateMessage.getId(),tTemplateMessage.getName()); ----------------------任务的具体执行逻辑----------------------------------- }}
在控制层中接收到请求后创建任务:
@RestController@RequestMapping("/template/message")public class TTemplateMessageController { @Resource private TTemplateMessageService tTemplateMessageService; @Autowired private SendTemplateService sendTemplateService; @Resource private SchedulerBuilder schedulerBuilder; /** * 新建模板消息推送 * @param templateMessageRequest * @return */ @PostMapping("/sendTemplateMessage") public Result sendTemplateMessage(@RequestBody TTemplateMessage templateMessageRequest) { try { schedulerBuilder.createJob(templateMessageRequest,MyJob.class); return ResultGenerator.genSuccessResult(); } catch (Exception e) { e.printStackTrace(); return ResultGenerator.genFailResult("操作失败"); } } }
以上就可以实现前言中所说的动态管理;就分享了可以实现定时任务部分,我是先将任务保存到数据库中,之后任务在execute()触发后进行具体执行相关逻辑处理的时候再从数据库中查询到;以及其他的相关处理逻辑可以根据自己的业务来添加;
以上分享希望可以帮助到正在做定时任务的你,如果其他更好的意见和改善望指点;
如果这篇文章帮助到你了,分享出去让他帮助到更多挠头扣手的童鞋;
更多技术分享可以关注我的私人公众号,探索出Java更多的未知;
喜欢就分享、点赞、加关注哦!!