SpringBoot:工厂模式实现定时任务可配置

  需要:使用springboot,实现定时任务可配置。

    定时任务可在代码中写死,在配置文件中配置,这些都不能实现定时任务在服务器不重启的情况下可配置。

    为实现需求,使定时任务在时间表达式或者定时任务类更改时,实现定时任务的重新设置并启动。

  1. pom包配置
<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>1.5.8.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
            <version>1.5.8.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <version>1.5.8.RELEASE</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <version>1.5.8.RELEASE</version>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
            <version>1.5.8.RELEASE</version>
        </dependency>
        <!-- jdbc driver -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.44</version>
        </dependency>
    </dependencies>

    项目采用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 <T> T getBean(Class<T> clazz) {
38         return getApplicationContext().getBean(clazz);
39     }
40 
41     // 通过name,以及Clazz返回指定的Bean
42     public static <T> T getBean(String name, Class<T> clazz) {
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.yonyou.mcloud.trigger.McloudTrigger;
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<CronVO> findAll() {
173         return cronService.findAll();
174     }
175 }

猜你喜欢

转载自www.cnblogs.com/deleba/p/9081871.html