需要:使用springboot,实现定时任务可配置。
定时任务可在代码中写死,在配置文件中配置,这些都不能实现定时任务在服务器不重启的情况下可配置。
为实现需求,使定时任务在时间表达式或者定时任务类更改时,实现定时任务的重新设置并启动。
pom包配置
org.springframework.boot
spring-boot-starter-web
1.5.8.RELEASE
org.springframework.boot
spring-boot-starter
1.5.8.RELEASE
org.springframework.boot
spring-boot-starter-test
1.5.8.RELEASE
test
org.springframework.boot
spring-boot-devtools
1.5.8.RELEASE
true
org.springframework.boot
spring-boot-starter-data-jpa
1.5.8.RELEASE
mysql
mysql-connector-java
5.1.44
项目采用springboot框架1.5.8版本,未采用quartz框架,使用spring-boot-devtools包springboot自带的定时任务完成。
因为spring2.0版本下尚未集成quartz,根据需求采用这种模式。
2.配置文件
#jpa
spring.jpa.generate-ddl: falsespring.jpa.show-sql: truespring.jpa.hibernate.ddl-auto: none
spring.jpa.properties.hibernate.format_sql:false#DataSource配置
spring.datasource.url=${pom.datasource.url}
spring.datasource.username=${pom.datasource.username}
spring.datasource.password=${pom.datasource.password}
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.jpa.properties.hibernate.current_session_context_class=org.springframework.orm.hibernate4.SpringSessionContext
3.application启动项
1 @ComponentScan(basePackages = { "com.deleba.quartz"})2 @SpringBootApplication3 @EnableScheduling4 public classQuartzApplication {5
6 public static voidmain(String[] args) {7 SpringApplication app = new SpringApplication(MCloudQuartzApplication.class);8 app.addListeners(newStartApplicationListener());9 app.run(args);10 }11
12 @Bean("sessionFactory")13 publicHibernateJpaSessionFactoryBean sessionFactory() {14 return newHibernateJpaSessionFactoryBean();15 }16
17 @Bean18 publicThreadPoolTaskScheduler threadPoolTaskScheduler() {19 return newThreadPoolTaskScheduler();20 }21 }
4.定时任务实体
1 packagecom.deleba.quartz.entity;2
3 importjava.io.Serializable;4 importjava.util.Date;5
6 importjavax.persistence.Entity;7 importjavax.persistence.GeneratedValue;8 importjavax.persistence.GenerationType;9 importjavax.persistence.Id;10 importjavax.persistence.Table;11
12 @Entity13 @Table(name = "quartz_cron")14 public class CronVO implementsSerializable {15
16 private static final long serialVersionUID = -3406421161273529348L;17 @Id18 @GeneratedValue(strategy =GenerationType.AUTO)19 privateInteger cronId;20 /**
21 * cron22 */
23 privateString cron;24 /**
25 * 定时任务名称26 */
27 privateString quartzName;28 /**
29 * 状态("1":有效 "0":无效)30 */
31 privateInteger status;32 /**
33 * 定时任务类34 */
35 privateString schedulerClass;36 /**
37 * 时间戳38 */
39 privateDate ts;40
41 publicCronVO() {42 }43
44 publicDate getTs() {45 returnts;46 }47
48 public voidsetTs(Date ts) {49 this.ts =ts;50 }51
52 publicString getSchedulerClass() {53 returnschedulerClass;54 }55
56 public voidsetSchedulerClass(String schedulerClass) {57 this.schedulerClass =schedulerClass;58 }59
60 publicString getQuartzName() {61 returnquartzName;62 }63
64 public voidsetQuartzName(String quartzName) {65 this.quartzName =quartzName;66 }67
68 publicInteger getCronId() {69 returncronId;70 }71
72 public voidsetCronId(Integer cronId) {73 this.cronId =cronId;74 }75
76 publicString getCron() {77 returncron;78 }79
80 public voidsetCron(String cron) {81 this.cron =cron;82 }83
84 publicInteger getStatus() {85 returnstatus;86 }87
88 public voidsetStatus(Integer status) {89 this.status =status;90 }91
92 }
5.定时任务trigger
1 packagecom.deleba.quartz.trigger;2
3 importjava.util.Date;4
5 importorg.apache.commons.lang3.StringUtils;6 importorg.springframework.scheduling.Trigger;7 importorg.springframework.scheduling.TriggerContext;8 importorg.springframework.scheduling.support.CronTrigger;9
10 /**
11 * 定时任务trigger12 *13 *@authorAdministrator14 *15 */
16 public class QuartzTrigger implementsTrigger {17
18 privateString cron;19
20 publicMcloudTrigger(String cron) {21 super();22 this.cron =cron;23 }24
25 @Override26 publicDate nextExecutionTime(TriggerContext triggerContext) {27 if(StringUtils.isBlank(cron)) {28 return null;29 }30 //定时任务触发,可修改定时任务的执行周期
31 CronTrigger trigger = newCronTrigger(cron);32 Date nextExecDate =trigger.nextExecutionTime(triggerContext);33 returnnextExecDate;34 }35
36 }
6.定时任务线程
1 packagecom.deleba.quartz.thread;2
3 importorg.slf4j.Logger;4 importorg.slf4j.LoggerFactory;5
6 importcom.deleba.quartz.service.ILicenseCarrierService;7 importcom.deleba.quartz.utils.SpringUtil;8
9 /**
10 * 定时任务线程11 *12 *@authorAdministrator13 *14 */
15 public class QuartzThread implementsRunnable {16
17 private Logger logger = LoggerFactory.getLogger(QuartzThread.class);18
19 @Override20 public voidrun() {21 try{22 //获取bean
23 IDemoService licenseCarrierService = SpringUtil.getBean(IDemoService.class);24 //执行任务
25 lDemoService.method();26 logger.info("执行成功");27 } catch(Exception e) {28 logger.error("执行失败: " +e.getLocalizedMessage());29 }30 }31
32 }
由此定时任务线程,没在注入springbean,使用@Autowired获取不到bean,需要写一个获取bean的util来获取springbean
1 packagecom.deleba.quartz.utils;2
3 importorg.springframework.beans.BeansException;4 importorg.springframework.context.ApplicationContext;5 importorg.springframework.context.ApplicationContextAware;6 importorg.springframework.stereotype.Component;7
8 /**
9 * 获取bean工具10 *11 *@authorAdministrator12 *13 */
14 @Component15 public class SpringUtil implementsApplicationContextAware {16
17 private staticApplicationContext applicationContext;18
19 @Override20 public void setApplicationContext(ApplicationContext applicationContext) throwsBeansException {21 if (SpringUtil.applicationContext == null) {22 SpringUtil.applicationContext =applicationContext;23 }24 }25
26 //获取applicationContext
27 public staticApplicationContext getApplicationContext() {28 returnapplicationContext;29 }30
31 //通过name获取 Bean.
32 public staticObject getBean(String name) {33 returngetApplicationContext().getBean(name);34 }35
36 //通过class获取Bean.
37 public static T getBean(Classclazz) {38 returngetApplicationContext().getBean(clazz);39 }40
41 //通过name,以及Clazz返回指定的Bean
42 public static T getBean(String name, Classclazz) {43 returngetApplicationContext().getBean(name, clazz);44 }45
46 }
7.定时任务类
1 packagecom.deleba.quartz.scheduler;2
3 importjava.util.concurrent.ScheduledFuture;4
5 importorg.slf4j.Logger;6 importorg.slf4j.LoggerFactory;7 importorg.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;8
9 importcom.deleba.quartz.trigger.quratzrigger;10
11 /**
12 * 定时任务13 *14 *@authorAdministrator15 *16 */
17 public classQuartzScheduler {18
19 private Logger logger = LoggerFactory.getLogger(QuartzScheduler.class);20
21 privateThreadPoolTaskScheduler threadPoolTaskScheduler;22
23 private ScheduledFuture>scheduledFuture;24
25 private String cron = "";//事件表达式
26
27 private Runnable runnable;//定时任务
28
29 publicMcloudScheduler(Runnable runnable, String cron, ThreadPoolTaskScheduler threadPoolTaskScheduler) {30 super();31 this.runnable =runnable;32 this.cron =cron;33 this.threadPoolTaskScheduler =threadPoolTaskScheduler;34 }35
36 publicString getCron() {37 returncron;38 }39
40 /**
41 * 停止定时任务42 */
43 public voidstop() {44 if (scheduledFuture != null) {45 scheduledFuture.cancel(true);46 }47 }48
49 /**
50 * 设置时间表达式51 *52 *@paramcron53 */
54 public voidsetCron(String cron) {55 this.cron =cron;56 stop();57 scheduledFuture = threadPoolTaskScheduler.schedule(runnable, newMcloudTrigger(cron));58 }59 }
8.定时任务工厂类
1 packagecom.deleba.quartz.factory;2
3 importjava.util.HashMap;4
5 importjava.util.Map;6
7 importorg.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;8
9 importcom.deleba.quartz.scheduler.QuzrtzScheduler;10
11 /**
12 * 定时任务工厂类13 *14 *@authorAdministrator15 *16 */
17 public classScheduledFutureFactory {18
19 private static Map map = new HashMap<>(0);20
21 /**
22 * 获取定时任务实例23 *24 *@paramcronId25 *@paramrunnable26 *@paramcron27 *@paramthreadPoolTaskScheduler28 *@return
29 */
30 public staticQuartzScheduler createQuartzScheduler(Integer cronId, Runnable runnable, String cron,31 ThreadPoolTaskScheduler threadPoolTaskScheduler) {32 QuartzScheduler quartzScheduler = newQuartzScheduler(runnable, cron, threadPoolTaskScheduler);33 map.put(cronId, quartzScheduler);34 returnquartzScheduler;35 }36
37 /**
38 * 根据key获取定时任务实例39 *40 *@paramcronId41 *@return
42 */
43 public staticQuartzScheduler getQuartzScheduler(Integer cronId) {44 returnmap.get(cronId);45 }46
47 }
9.controller
1 packagecom.deleba.quartz.controller;2
3 importjava.util.List;4
5 importorg.apache.commons.lang3.StringUtils;6 importorg.slf4j.Logger;7 importorg.slf4j.LoggerFactory;8 importorg.springframework.beans.factory.annotation.Autowired;9 importorg.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;10 importorg.springframework.web.bind.annotation.RequestBody;11 importorg.springframework.web.bind.annotation.RequestMapping;12 importorg.springframework.web.bind.annotation.RequestMethod;13 importorg.springframework.web.bind.annotation.RequestParam;14 importorg.springframework.web.bind.annotation.ResponseBody;15 importorg.springframework.web.bind.annotation.RestController;16
17 importcom.deleba.quartz.common.response.JsonResponse;18 importcom.deleba.quartz.common.response.JsonResponseBuilder;19 importcom.deleba.quartz.entity.CronVO;20 importcom.deleba.quartz.factory.ScheduledFutureFactory;21 importcom.deleba.quartz.scheduler.QuartzScheduler;22 importcom.deleba.quartz.service.ICronService;23
24 /***25 * 定时任务操作--表现层26 *27 *@authorAdministrator28 *29 */
30 @RestController31 @RequestMapping("/scheduler")32 public classSchedulerController {33
34 private Logger logger = LoggerFactory.getLogger(SchedulerController.class);35
36 @Autowired37 privateICronService cronService;38
39 @Autowired40 privateThreadPoolTaskScheduler threadPoolTaskScheduler;41
42 /**
43 * 开启定时任务44 *45 *@paramcronId46 *@return
47 */
48 @RequestMapping(value = "/start", method =RequestMethod.GET)49 @ResponseBody50 public JsonResponse start(@RequestParam(name = "cronId", defaultValue = "") Integer cronId) {51 //1.参数校验
52 CronVO cronVO =cronService.findByCronId(cronId);53 if (cronVO == null) {54 return JsonResponseBuilder.buildFailResponse("cronId无效");55 }56 String cron =cronVO.getCron();57 String schedulerClass =cronVO.getSchedulerClass();58 //2.开启任务
59 try{60 Runnable runnable =(Runnable) Class.forName(schedulerClass).newInstance();61 QuartzScheduler quartzScheduler =ScheduledFutureFactory.getQuartzScheduler(cronId);62 if (quartzScheduler == null) {63 quartzScheduler =ScheduledFutureFactory.createQuartzScheduler(cronId, runnable, cron,64 threadPoolTaskScheduler);65 }66 quartzScheduler.setCron(cron);67 cronVO.setStatus(1);68 cronService.update(cronVO);69 logger.info("开启定时任务成功");70 return JsonResponseBuilder.buildSuccessResponse("开启定时任务成功");71 } catch(Exception e) {72 logger.error(e.getMessage(), e);73 return JsonResponseBuilder.buildFailResponse("开启定时任务失败");74 }75 }76
77 /**
78 * 关闭定时任务79 *80 *@paramcronId81 *@return
82 */
83 @RequestMapping(value = "/close", method =RequestMethod.GET)84 @ResponseBody85 public JsonResponse close(@RequestParam(name = "cronId", defaultValue = "") Integer cronId) {86 //1.参数校验
87 CronVO cronVO =cronService.findByCronId(cronId);88 if (cronVO == null) {89 return JsonResponseBuilder.buildFailResponse("cronId无效");90 }91 String cron =cronVO.getCron();92 String schedulerClass =cronVO.getSchedulerClass();93 //2.关闭任务
94 try{95 Runnable runnable =(Runnable) Class.forName(schedulerClass).newInstance();96 QuartzScheduler quartzScheduler =ScheduledFutureFactory.getQuartzScheduler(cronId);97 if (mcloudScheduler == null) {98 quartzScheduler =ScheduledFutureFactory.createQuartzScheduler(cronId, runnable, cron,99 threadPoolTaskScheduler);100 }101 quartzScheduler.stop();102 cronVO.setStatus(0);103 cronService.update(cronVO);104 logger.info("关闭定时任务成功");105 return JsonResponseBuilder.buildSuccessResponse("关闭定时任务成功");106 } catch(Exception e) {107 logger.error(e.getMessage(), e);108 return JsonResponseBuilder.buildFailResponse("关闭定时任务失败");109 }110 }111
112 /***113 * 更新定时任务114 *115 *@paramcronVO116 *@return
117 */
118 @RequestMapping(value = "/update", method =RequestMethod.POST)119 @ResponseBody120 publicJsonResponse update(@RequestBody CronVO cronVO) {121 //1.参数校验
122 Integer cronId =cronVO.getCronId();123 String cron =cronVO.getCron();124 Integer status =cronVO.getStatus();125 String schedulerClass =cronVO.getSchedulerClass();126 if (StringUtils.isBlank(cron) ||StringUtils.isBlank(schedulerClass)) {127 return JsonResponseBuilder.buildFailResponse("时间表达式和定时任务类不可为空");128 }129 try{130 //2.更新实体,定时任务开启状态则重新设置表达式
131 cronService.update(cronVO);132 if (status == 1) {133 Runnable runnable =(Runnable) Class.forName(schedulerClass).newInstance();134 QuartzScheduler quartzScheduler =ScheduledFutureFactory.getQuartzScheduler(cronId);135 if (mcloudScheduler == null) {136 mcloudScheduler =ScheduledFutureFactory.createQuartzScheduler(cronId, runnable, cron,137 threadPoolTaskScheduler);138 }139 mcloudScheduler.setCron(cron);140 }141 } catch(Exception e) {142 logger.error(e.getMessage(), e);143 return JsonResponseBuilder.buildFailResponse("更新定时任务失败");144 }145 logger.info("更新定时任务成功");146 return JsonResponseBuilder.buildFailResponse("更新定时任务成功");147 }148
149 /***150 * 根据主键获取定时任务相关信息151 *152 *@paramcronId153 *@return
154 */
155 @RequestMapping(value = "/findById", method =RequestMethod.GET)156 @ResponseBody157 public CronVO findById(@RequestParam(name = "cronId", defaultValue = "") Integer cronId) {158 if (cronId == null) {159 return null;160 }161 CronVO cronVO =cronService.findByCronId(cronId);162 returncronVO;163 }164
165 /***166 * 获取所有定时任务信息167 *168 *@return
169 */
170 @RequestMapping(value = "/findAll", method =RequestMethod.GET)171 @ResponseBody172 public ListfindAll() {173 returncronService.findAll();174 }175 }