pringBoot:工厂模式实现定时任务可配置
需要:使用springboot,实现定时任务可配置。
定时任务可在代码中写死,在配置文件中配置,这些都不能实现定时任务在服务器不重启的情况下可配置。
为实现需求,使定时任务在时间表达式或者定时任务类更改时,实现定时任务的重新设置并启动。
pom包配置
复制代码
复制代码
项目采用springboot框架1.5.8版本,未采用quartz框架,使用spring-boot-devtools包springboot自带的定时任务完成。
因为spring2.0版本下尚未集成quartz,根据需求采用这种模式。
2.配置文件
复制代码
jpa
spring.jpa.generate-ddl: false
spring.jpa.show-sql: true
spring.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 @SpringBootApplication
3 @EnableScheduling
4 public class QuartzApplication {
5
6 public static void main(String[] args) {
7 SpringApplication app = new SpringApplication(MCloudQuartzApplication.class);
8 app.addListeners(new StartApplicationListener());
9 app.run(args);
10 }
11
12 @Bean("sessionFactory")
13 public HibernateJpaSessionFactoryBean sessionFactory() {
14 return new HibernateJpaSessionFactoryBean();
15 }
16
17 @Bean
18 public ThreadPoolTaskScheduler threadPoolTaskScheduler() {
19 return new ThreadPoolTaskScheduler();
20 }
21 }
复制代码
4.定时任务实体
复制代码
1 package com.deleba.quartz.entity;
2
3 import java.io.Serializable;
4 import java.util.Date;
5
6 import javax.persistence.Entity;
7 import javax.persistence.GeneratedValue;
8 import javax.persistence.GenerationType;
9 import javax.persistence.Id;
10 import javax.persistence.Table;
11
12 @Entity
13 @Table(name = "quartz_cron")
14 public class CronVO implements Serializable {
15
16 private static final long serialVersionUID = -3406421161273529348L;
17 @Id
18 @GeneratedValue(strategy = GenerationType.AUTO)
19 private Integer cronId;
20 /**
21 * cron
22 /
23 private String cron;
24 /*
25 * 定时任务名称
26 /
27 private String quartzName;
28 /*
29 * 状态("1":有效 "0":无效)
30 /
31 private Integer status;
32 /*
33 * 定时任务类
34 /
35 private String schedulerClass;
36 /*
37 * 时间戳
38 */
39 private Date ts;
40
41 public CronVO() {
42 }
43
44 public Date getTs() {
45 return ts;
46 }
47
48 public void setTs(Date ts) {
49 this.ts = ts;
50 }
51
52 public String getSchedulerClass() {
53 return schedulerClass;
54 }
55
56 public void setSchedulerClass(String schedulerClass) {
57 this.schedulerClass = schedulerClass;
58 }
59
60 public String getQuartzName() {
61 return quartzName;
62 }
63
64 public void setQuartzName(String quartzName) {
65 this.quartzName = quartzName;
66 }
67
68 public Integer getCronId() {
69 return cronId;
70 }
71
72 public void setCronId(Integer cronId) {
73 this.cronId = cronId;
74 }
75
76 public String getCron() {
77 return cron;
78 }
79
80 public void setCron(String cron) {
81 this.cron = cron;
82 }
83
84 public Integer getStatus() {
85 return status;
86 }
87
88 public void setStatus(Integer status) {
89 this.status = status;
90 }
91
92 }
复制代码
5.定时任务trigger
复制代码
1 package com.deleba.quartz.trigger;
2
3 import java.util.Date;
4
5 import org.apache.commons.lang3.StringUtils;
6 import org.springframework.scheduling.Trigger;
7 import org.springframework.scheduling.TriggerContext;
8 import org.springframework.scheduling.support.CronTrigger;
9
10 /**
11 * 定时任务trigger
12 *
13 * @author Administrator
14 *
15 */
16 public class QuartzTrigger implements Trigger {
17
18 private String cron;
19
20 public McloudTrigger(String cron) {
21 super();
22 this.cron = cron;
23 }
24
25 @Override
26 public Date nextExecutionTime(TriggerContext triggerContext) {
27 if (StringUtils.isBlank(cron)) {
28 return null;
29 }
30 // 定时任务触发,可修改定时任务的执行周期
31 CronTrigger trigger = new CronTrigger(cron);
32 Date nextExecDate = trigger.nextExecutionTime(triggerContext);
33 return nextExecDate;
34 }
35
36 }
复制代码
6.定时任务线程
复制代码
1 package com.deleba.quartz.thread;
2
3 import org.slf4j.Logger;
4 import org.slf4j.LoggerFactory;
5
6 import com.deleba.quartz.service.ILicenseCarrierService;
7 import com.deleba.quartz.utils.SpringUtil;
8
9 /**
10 * 定时任务线程
11 *
12 * @author Administrator
13 *
14 */
15 public class QuartzThread implements Runnable {
16
17 private Logger logger = LoggerFactory.getLogger(QuartzThread.class);
18
19 @Override
20 public void run() {
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 package com.deleba.quartz.utils;
2
3 import org.springframework.beans.BeansException;
4 import org.springframework.context.ApplicationContext;
5 import org.springframework.context.ApplicationContextAware;
6 import org.springframework.stereotype.Component;
7
8 /**
9 * 获取bean工具
10 *
11 * @author Administrator
12 *
13 */
14 @Component
15 public class SpringUtil implements ApplicationContextAware {
16
17 private static ApplicationContext applicationContext;
18
19 @Override
20 public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
21 if (SpringUtil.applicationContext == null) {
22 SpringUtil.applicationContext = applicationContext;
23 }
24 }
25
26 // 获取applicationContext
27 public static ApplicationContext getApplicationContext() {
28 return applicationContext;
29 }
30
31 // 通过name获取 Bean.
32 public static Object getBean(String name) {
33 return getApplicationContext().getBean(name);
34 }
35
36 // 通过class获取Bean.
37 public static
38 return getApplicationContext().getBean(clazz);
39 }
40
41 // 通过name,以及Clazz返回指定的Bean
42 public static
43 return getApplicationContext().getBean(name, clazz);
44 }
45
46 }
复制代码
7.定时任务类
复制代码
1 package com.deleba.quartz.scheduler;
2
3 import java.util.concurrent.ScheduledFuture;
4
5 import org.slf4j.Logger;
6 import org.slf4j.LoggerFactory;
7 import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
8
9 import com.deleba.quartz.trigger.quratzrigger;
10
11 /**
12 * 定时任务
13 *
14 * @author Administrator
15 *
16 /
17 public class QuartzScheduler {
18
19 private Logger logger = LoggerFactory.getLogger(QuartzScheduler.class);
20
21 private ThreadPoolTaskScheduler threadPoolTaskScheduler;
22
23 private ScheduledFuture<?> scheduledFuture;
24
25 private String cron = "";//事件表达式
26
27 private Runnable runnable;//定时任务
28
29 public McloudScheduler(Runnable runnable, String cron, ThreadPoolTaskScheduler threadPoolTaskScheduler) {
30 super();
31 this.runnable = runnable;
32 this.cron = cron;
33 this.threadPoolTaskScheduler = threadPoolTaskScheduler;
34 }
35
36 public String getCron() {
37 return cron;
38 }
39
40 /*
41 * 停止定时任务
42 /
43 public void stop() {
44 if (scheduledFuture != null) {
45 scheduledFuture.cancel(true);
46 }
47 }
48
49 /*
50 * 设置时间表达式
51 *
52 * @param cron
53 */
54 public void setCron(String cron) {
55 this.cron = cron;
56 stop();
57 scheduledFuture = threadPoolTaskScheduler.schedule(runnable, new McloudTrigger(cron));
58 }
59 }
复制代码
8.定时任务工厂类
复制代码
1 package com.deleba.quartz.factory;
2
3 import java.util.HashMap;
4
5 import java.util.Map;
6
7 import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
8
9 import com.deleba.quartz.scheduler.QuzrtzScheduler;
10
11 /**
12 * 定时任务工厂类
13 *
14 * @author Administrator
15 *
16 /
17 public class ScheduledFutureFactory {
18
19 private static Map<Integer, QuartzScheduler> map = new HashMap<>(0);
20
21 /*
22 * 获取定时任务实例
23 *
24 * @param cronId
25 * @param runnable
26 * @param cron
27 * @param threadPoolTaskScheduler
28 * @return
29 /
30 public static QuartzScheduler createQuartzScheduler(Integer cronId, Runnable runnable, String cron,
31 ThreadPoolTaskScheduler threadPoolTaskScheduler) {
32 QuartzScheduler quartzScheduler = new QuartzScheduler(runnable, cron, threadPoolTaskScheduler);
33 map.put(cronId, quartzScheduler);
34 return quartzScheduler;
35 }
36
37 /*
38 * 根据key获取定时任务实例
39 *
40 * @param cronId
41 * @return
42 */
43 public static QuartzScheduler getQuartzScheduler(Integer cronId) {
44 return map.get(cronId);
45 }
46
47 }
复制代码
9.controller
复制代码
1 package com.deleba.quartz.controller;
2
3 import java.util.List;
4
5 import org.apache.commons.lang3.StringUtils;
6 import org.slf4j.Logger;
7 import org.slf4j.LoggerFactory;
8 import org.springframework.beans.factory.annotation.Autowired;
9 import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
10 import org.springframework.web.bind.annotation.RequestBody;
11 import org.springframework.web.bind.annotation.RequestMapping;
12 import org.springframework.web.bind.annotation.RequestMethod;
13 import org.springframework.web.bind.annotation.RequestParam;
14 import org.springframework.web.bind.annotation.ResponseBody;
15 import org.springframework.web.bind.annotation.RestController;
16
17 import com.deleba.quartz.common.response.JsonResponse;
18 import com.deleba.quartz.common.response.JsonResponseBuilder;
19 import com.deleba.quartz.entity.CronVO;
20 import com.deleba.quartz.factory.ScheduledFutureFactory;
21 import com.deleba.quartz.scheduler.QuartzScheduler;
22 import com.deleba.quartz.service.ICronService;
23
24 /***
25 * 定时任务操作--表现层
26 *
27 * @author Administrator
28 *
29 /
30 @RestController
31 @RequestMapping("/scheduler")
32 public class SchedulerController {
33
34 private Logger logger = LoggerFactory.getLogger(SchedulerController.class);
35
36 @Autowired
37 private ICronService cronService;
38
39 @Autowired
40 private ThreadPoolTaskScheduler threadPoolTaskScheduler;
41
42 /*
43 * 开启定时任务
44 *
45 * @param cronId
46 * @return
47 /
48 @RequestMapping(value = "/start", method = RequestMethod.GET)
49 @ResponseBody
50 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 * @param cronId
81 * @return
82 /
83 @RequestMapping(value = "/close", method = RequestMethod.GET)
84 @ResponseBody
85 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 * @param cronVO
116 * @return
117 /
118 @RequestMapping(value = "/update", method = RequestMethod.POST)
119 @ResponseBody
120 public JsonResponse 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 * @param cronId
153 * @return
154 /
155 @RequestMapping(value = "/findById", method = RequestMethod.GET)
156 @ResponseBody
157 public CronVO findById(@RequestParam(name = "cronId", defaultValue = "") Integer cronId) {
158 if (cronId == null) {
159 return null;
160 }
161 CronVO cronVO = cronService.findByCronId(cronId);
162 return cronVO;
163 }
164
165 /**
166 * 获取所有定时任务信息
167 *
168 * @return
169 */
170 @RequestMapping(value = "/findAll", method = RequestMethod.GET)
171 @ResponseBody
172 public List
173 return cronService.findAll();
174 }