Quartz+Spring Boot实现动态管理定时任务
项目实践过程中碰到一个动态管理定时任务的需求:针对每个人员进行信息的定时更新,具体更新时间可随时调整、启动、暂定等。
思路
将每个人员信息的定时配置保存到数据库中,这样实现了任务的动态展示和管理。任务的每一次新增或变更,都会去数据库变更信息。
设置一个统一的任务管理器,专门负责动态任务的增删改查。
POM依赖
4.0.0 com.example dynamic-quartz 0.0.1-SNAPSHOT jar dynamic-quartz 动态定时任务管理 org.springframework.boot spring-boot-starter-parent 2.0.2.RELEASE org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter org.springframework spring-context-support org.springframework.boot spring-boot-starter-test test org.mybatis.spring.boot mybatis-spring-boot-starter 1.1.1 mysql mysql-connector-java 5.1.44 org.quartz-scheduler quartz 2.3.0 application.yml spring: datasource: url:jdbc:mysql://localhost:3306/wujiwen username:root password:root driver-class-name:com.mysql.jdbc.Driver profiles: active:dev logback-spring.xml org.springframework.boot spring-boot-maven-plugin CronEntity.java 保存在数据库中的表达式管理器. packagecom.example.dynamicquartz.bean; importjava.io.Serializable; importjava.util.Date; /** *createdwithIntelliJIDEA. *packageName:com.example.dynamicquartz.bean *author:wujw *date:2018/9/916:23 *version:1.0.0 *description:TODO */ publicclassCronEntityimplementsSerializable{ privatestaticfinallongserialVersionUID=-3406421161273529348L; privateStringid; privateStringuserId;//用户标识 privateStringcron;//表达式 privateStringquarzName;//任务名称 privateStringschedulerClass;//定时任务类 privateDatetime; publicStringgetId(){ returnid; } publicvoidsetId(Stringid){ this.id=id; } publicStringgetUserId(){ returnuserId; } publicvoidsetUserId(StringuserId){ this.userId=userId; } publicStringgetCron(){ returncron; } publicvoidsetCron(Stringcron){ this.cron=cron; } publicStringgetQuarzName(){ returnquarzName; } publicvoidsetQuarzName(StringquarzName){ this.quarzName=quarzName; } publicStringgetSchedulerClass(){ returnschedulerClass; } publicvoidsetSchedulerClass(StringschedulerClass){ this.schedulerClass=schedulerClass; } publicDategetTime(){ returntime; } publicvoidsetTime(Datetime){ this.time=time; } @Override publicStringtoString(){ return"CronEntity{"+ "id='"+id+'\''+ ",userId='"+userId+'\''+ ",cron='"+cron+'\''+ ",quarzName='"+quarzName+'\''+ ",schedulerClass='"+schedulerClass+'\''+ ",time="+time+ '}'; } } CronMapper packagecom.example.dynamicquartz.dao; importcom.example.dynamicquartz.bean.CronEntity; importorg.apache.ibatis.annotations.*; importjava.util.List; /** *createdwithIntelliJIDEA. *packageName:com.example.dynamicquartz *author:wujw *date:2018/9/920:14 *version:1.0.0 *description:TODO */ @Mapper publicinterfaceCronMapper{ @Select("select*fromcron_tablewhereid=#{id}") @Results({ @Result(property="id",column="id"), @Result(property="userId",column="user_id"), @Result(property="cron",column="cron"), @Result(property="quarzName",column="quarz_name"), @Result(property="schedulerClass",column="scheduler_class"), @Result(property="time",column="time") }) CronEntityload(Stringid); @Insert("insertintocron_table(id,userId,cron,quartzName,schedulerClass,time)"+ "values(#{id},#{user_id},#{cron},#{quartz_name},#{scheduler_class},#{time})") voidinsert(CronEntitycronEntity); @Select("select*fromcron_table") @Results({ @Result(property="id",column="id"), @Result(property="userId",column="user_id"), @Result(property="cron",column="cron"), @Result(property="quarzName",column="quarz_name"), @Result(property="schedulerClass",column="scheduler_class"), @Result(property="time",column="time") }) List %date[%thread]%-5level%logger{80}-%msg%n queryAll(); @Update("updatecron_tablesetcron=#{1}whereid=#{0}") voidupdateCron(Stringid,Stringcron); } ICronService packagecom.example.dynamicquartz.serivce; importcom.example.dynamicquartz.bean.CronEntity; importjava.util.List; /** *createdwithIntelliJIDEA. *packageName:com.example.dynamicquartz *author:wujw *date:2018/9/919:54 *version:1.0.0 *description:TODO */ publicinterfaceICronService{ voidsendEmail(StringquartzName); voidsendSms(StringquartzName); CronEntityfindByCronId(Stringid); voidupdate(CronEntitycronEntity); List findAll(); } CronServiceImpl packagecom.example.dynamicquartz.serivce; importcom.example.dynamicquartz.bean.CronEntity; importcom.example.dynamicquartz.dao.CronMapper; importorg.springframework.beans.factory.annotation.Autowired; importorg.springframework.stereotype.Service; importjava.util.List; /** *createdwithIntelliJIDEA. *packageName:com.example.dynamicquartz.serivce *author:wujw *date:2018/9/919:55 *version:1.0.0 *description:TODO */ @Service publicclassCronServiceImplimplementsICronService{ @Autowired privateCronMappercronMapper; @Override publicvoidsendEmail(StringquartzName){ System.out.println(quartzName+"正在发送邮件"); } @Override publicvoidsendSms(StringquartzName){ System.out.println(quartzName+"正在发送短信"); } @Override publicCronEntityfindByCronId(Stringid){ returnthis.cronMapper.load(id); } @Override publicvoidupdate(CronEntitycronEntity){ this.cronMapper.insert(cronEntity); } @Override publicList findAll(){ returnthis.cronMapper.queryAll(); } } QuartzManager packagecom.example.dynamicquartz.serivce; importcom.example.dynamicquartz.bean.CronEntity; importorg.quartz.*; importorg.springframework.beans.factory.annotation.Autowired; importorg.springframework.context.annotation.Configuration; importjava.util.Date; /** *createdwithIntelliJIDEA. *packageName:com.example.dynamicquartz *author:wujw *date:2018/9/919:31 *version:1.0.0 *description:TODO */ @Configuration publicclassQuartzManager{ @Autowired privateSchedulerscheduler; @Autowired privateICronServiceiCronService; publicvoidstart(Stringid)throwsSchedulerException{ CronEntitycronEntity=iCronService.findByCronId(id); if(cronEntity!=null){ startJob(scheduler,cronEntity.getQuarzName(),cronEntity.getCron(),cronEntity.getSchedulerClass()); } } privatevoidstartJob(Schedulerscheduler,Stringname,Stringcron,StringclassName)throwsSchedulerException{ //通过JobBuilder构建JobDetail实例,JobDetail规定只能是实现Job接口的实例 //JobDetail是具体Job实例 Class jobClass=null; try{ //实例化具体的Job任务 jobClass=(Class )Class.forName(className); }catch(ClassNotFoundExceptione){ e.printStackTrace(); } JobDetailjobDetail=JobBuilder.newJob(jobClass).withIdentity(name,"group1").build(); //基于表达式构建触发器 CronScheduleBuildercronScheduleBuilder=CronScheduleBuilder.cronSchedule(cron); //CronTrigger表达式触发器继承于Trigger //TriggerBuilder用于构建触发器实例 CronTriggercronTrigger=TriggerBuilder.newTrigger().withIdentity(name,"group1") .withSchedule(cronScheduleBuilder).build(); scheduler.scheduleJob(jobDetail,cronTrigger); } /** *获取Job信息 * *@paramname *@paramgroup *@return *@throwsSchedulerException */ publicStringgetJobInfo(Stringname,Stringgroup)throwsSchedulerException{ TriggerKeytriggerKey=newTriggerKey(name,group); CronTriggercronTrigger=(CronTrigger)scheduler.getTrigger(triggerKey); returnString.format("time:%s,state:%s",cronTrigger.getCronExpression(), scheduler.getTriggerState(triggerKey).name()); } /** *修改某个任务的执行时间 * *@paramname *@paramgroup *@paramtime *@return *@throwsSchedulerException */ publicbooleanmodifyJob(Stringname,Stringgroup,Stringtime)throwsSchedulerException{ Datedate=null; TriggerKeytriggerKey=newTriggerKey(name,group); CronTriggercronTrigger=(CronTrigger)scheduler.getTrigger(triggerKey); StringoldTime=cronTrigger.getCronExpression(); if(!oldTime.equalsIgnoreCase(time)){ CronScheduleBuildercronScheduleBuilder=CronScheduleBuilder.cronSchedule(time); CronTriggertrigger=TriggerBuilder.newTrigger().withIdentity(name,group) .withSchedule(cronScheduleBuilder).build(); date=scheduler.rescheduleJob(triggerKey,trigger); } returndate!=null; } /** *暂停所有任务 * *@throwsSchedulerException */ publicvoidpauseAllJob()throwsSchedulerException{ scheduler.pauseAll(); } /** *暂停某个任务 * *@paramname *@paramgroup *@throwsSchedulerException */ publicvoidpauseJob(Stringname,Stringgroup)throwsSchedulerException{ JobKeyjobKey=newJobKey(name,group); JobDetailjobDetail=scheduler.getJobDetail(jobKey); if(jobDetail==null) return; scheduler.pauseJob(jobKey); } /** *恢复所有任务 * *@throwsSchedulerException */ publicvoidresumeAllJob()throwsSchedulerException{ scheduler.resumeAll(); } /** *恢复某个任务 * *@paramname *@paramgroup *@throwsSchedulerException */ publicvoidresumeJob(Stringname,Stringgroup)throwsSchedulerException{ JobKeyjobKey=newJobKey(name,group); JobDetailjobDetail=scheduler.getJobDetail(jobKey); if(jobDetail==null) return; scheduler.resumeJob(jobKey); } /** *删除某个任务 * *@paramname *@paramgroup *@throwsSchedulerException */ publicvoiddeleteJob(Stringname,Stringgroup)throwsSchedulerException{ JobKeyjobKey=newJobKey(name,group); JobDetailjobDetail=scheduler.getJobDetail(jobKey); if(jobDetail==null) return; scheduler.deleteJob(jobKey); } } 创建两个Task类,分别执行不同的任务 publicclassEmailTaskimplementsJob{ privateLoggerlogger=LoggerFactory.getLogger(EmailTask.class); @Autowired privateICronServiceiCronService; @Override publicvoidexecute(JobExecutionContextjobExecutionContext)throwsJobExecutionException{ logger.info("EmailTasktaskstartexecute."); //模拟任务执行 iCronService.sendEmail(jobExecutionContext.getJobDetail().getKey().getName()); } } publicclassSmsTaskimplementsJob{ privateLoggerlogger=LoggerFactory.getLogger(SmsTask.class); @Autowired privateICronServiceiCronService; @Override publicvoidexecute(JobExecutionContextjobExecutionContext)throwsJobExecutionException{ logger.info("SmsTasktaskstartexecute."); //模拟任务执行 iCronService.sendSms(jobExecutionContext.getJobDetail().getKey().getName()); } } SchedulerController @RestController @RequestMapping("/scheduler") publicclassSchedulerController{ @Autowired QuartzManagerquartzManager; @RequestMapping(value="/start",method=RequestMethod.GET) @ResponseBody publicStringstart(@RequestParam(name="id",defaultValue="")Stringid){ try{ quartzManager.start(id); }catch(SchedulerExceptione){ e.printStackTrace(); } return"启动成功"; } } cron_table.sql CREATETABLE`cron_table`( `id`varchar(11)collateutf8_binNOTNULL, `user_id`varchar(11)collateutf8_bindefaultNULL, `cron`varchar(255)collateutf8_bindefaultNULL, `quarz_name`varchar(255)collateutf8_bindefaultNULL, `scheduler_class`varchar(255)collateutf8_bindefaultNULL, `time`datetimedefaultNULL, PRIMARYKEY(`id`) )ENGINE=MyISAMDEFAULTCHARSET=utf8COLLATE=utf8_bin; ------------------------------ --Recordsofcron_table ------------------------------ INSERTINTO`cron_table`VALUES('1','AAA','0/5****?','用户AAA','com.example.dynamicquartz.job.SmsTask','2018-09-0620:26:55'); INSERTINTO`cron_table`VALUES('2','BBB','0/2****?','用户BBB','com.example.dynamicquartz.job.EmailTask','2018-09-0921:02:08'); 测试结果 http://localhost:8080/scheduler/start?id=1 http://localhost:8080/scheduler/start?id=2 2018-09-0921:05:08,386[http-nio-8080-exec-2]DEBUGcom.example.dynamicquartz.dao.CronMapper.load-==>Preparing:select*fromcron_tablewhereid=? 2018-09-0921:05:08,408[http-nio-8080-exec-2]DEBUGcom.example.dynamicquartz.dao.CronMapper.load-==>Parameters:1(String) 2018-09-0921:05:08,427[http-nio-8080-exec-2]DEBUGcom.example.dynamicquartz.dao.CronMapper.load-<==Total:1 2018-09-0921:05:10,036[quartzScheduler_Worker-1]INFOcom.example.dynamicquartz.job.SmsTask-SmsTasktaskstartexecute. 用户AAA正在发送短信 2018-09-0921:05:11,581[http-nio-8080-exec-1]DEBUGcom.example.dynamicquartz.dao.CronMapper.load-==>Preparing:select*fromcron_tablewhereid=? 2018-09-0921:05:11,582[http-nio-8080-exec-1]DEBUGcom.example.dynamicquartz.dao.CronMapper.load-==>Parameters:2(String) 2018-09-0921:05:11,584[http-nio-8080-exec-1]DEBUGcom.example.dynamicquartz.dao.CronMapper.load-<==Total:1 2018-09-0921:05:12,013[quartzScheduler_Worker-2]INFOcom.example.dynamicquartz.job.EmailTask-EmailTasktaskstartexecute. 用户BBB正在发送邮件 2018-09-0921:05:14,002[quartzScheduler_Worker-3]INFOcom.example.dynamicquartz.job.EmailTask-EmailTasktaskstartexecute. 用户BBB正在发送邮件 2018-09-0921:05:15,001[quartzScheduler_Worker-4]INFOcom.example.dynamicquartz.job.SmsTask-SmsTasktaskstartexecute. 用户AAA正在发送短信 2018-09-0921:05:16,001[quartzScheduler_Worker-5]INFOcom.example.dynamicquartz.job.EmailTask-EmailTasktaskstartexecute. 用户BBB正在发送邮件 2018-09-0921:05:18,001[quartzScheduler_Worker-6]INFOcom.example.dynamicquartz.job.EmailTask-EmailTasktaskstartexecute. 用户BBB正在发送邮件 2018-09-0921:05:20,000[quartzScheduler_Worker-7]INFOcom.example.dynamicquartz.job.SmsTask-SmsTasktaskstartexecute. 用户AAA正在发送短信 2018-09-0921:05:20,001[quartzScheduler_Worker-8]INFOcom.example.dynamicquartz.job.EmailTask-EmailTasktaskstartexecute. 用户BBB正在发送邮件 2018-09-0921:05:22,001[quartzScheduler_Worker-9]INFOcom.example.dynamicquartz.job.EmailTask-EmailTasktaskstartexecute. 用户BBB正在发送邮件 2018-09-0921:05:24,000[quartzScheduler_Worker-10]INFOcom.example.dynamicquartz.job.EmailTask-EmailTasktaskstartexecute. 用户BBB正在发送邮件 2018-09-0921:05:25,001[quartzScheduler_Worker-1]INFOcom.example.dynamicquartz.job.SmsTask-SmsTasktaskstartexecute. 用户AAA正在发送短信 2018-09-0921:05:26,000[quartzScheduler_Worker-2]INFOcom.example.dynamicquartz.job.EmailTask-EmailTasktaskstartexecute. 用户BBB正在发送邮件 2018-09-0921:05:28,001[quartzScheduler_Worker-3]INFOcom.example.dynamicquartz.job.EmailTask-EmailTasktaskstartexecute.
可以看出,AAA的间隔时间时5s,BBB的间隔时间时2s.
到这里我们的测试已经一本完成了,接下来就是针对任务的更新,停止和启动了,只需要调用QuartzManager对应的方法即可,必要时更新一下数据库就好啦。
总结
以上所述是小编给大家介绍的Quartz+SpringBoot实现动态管理定时任务,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对毛票票网站的支持!