最近工作中需要用到定时任务,Scheduled可以满足我们的需求,但是领导要求我把它平台化,后面就自己查阅资料和自己的探索自己写了一个可配置的平台化的定时任务。
先来看看我们常规的Scheduled
package com.wr.app;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
/**
* SpringBoot 启动类
* @author Administrator
*
*/
@SpringBootApplication
@EnableScheduling
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
package com.wr.app.scheduler;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
public class SimpleScheduler {
@Scheduled(cron = "*/5 * * * * *")
public void test() throws InterruptedException {
System.out.println("test()");
}
}
可以正常打印处理业务
下面是我自己写的可配置的
package com.wr.app;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
/**
* SpringBoot 启动类
* @author Administrator
*
*/
@SpringBootApplication
//@EnableScheduling
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
package com.wr.app.baen;
public class SchedulerTaskInfo {
// id
private String id;
// 任务名称
private String taskName;
// 任务类
private String taskClass;
// cron表达式
private String cron;
// 状态
private String status;
// 描述
private String remark;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getTaskName() {
return taskName;
}
public void setTaskName(String taskName) {
this.taskName = taskName;
}
public String getCron() {
return cron;
}
public void setCron(String cron) {
this.cron = cron;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getRemark() {
return remark;
}
public void setRemark(String remark) {
this.remark = remark;
}
public String getTaskClass() {
return taskClass;
}
public void setTaskClass(String taskClass) {
this.taskClass = taskClass;
}
}
package com.wr.app.controller;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.wr.app.baen.SchedulerTaskInfo;
import com.wr.app.scheduler.TaskScheduler;
/**
* SpringBoot HelloWorld
* @author Administrator
*
*/
@Controller
public class HelloWorld {
@Autowired
TaskScheduler taskScheduler;
@RequestMapping("/hello")
@ResponseBody
public Map<String, Object> showHelloWorld(){
Map<String, Object> map = new HashMap<>();
map.put("msg", "HelloWorld");
return map;
}
@RequestMapping("/startAll")
@ResponseBody
public Map<String, Object> startAll(){
Map<String, Object> map = new HashMap<>();
try {
taskScheduler.startAll();
map.put("msg", "success");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return map;
}
@RequestMapping("/stopAll")
@ResponseBody
public Map<String, Object> stopAll(){
Map<String, Object> map = new HashMap<>();
try {
taskScheduler.stopAll();
map.put("msg", "success");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return map;
}
@RequestMapping("/start")
@ResponseBody
public Map<String, Object> start(String id){
Map<String, Object> map = new HashMap<>();
try {
//需要先去数据库通过id查询对应的任务信息
//List<SchedulerTaskInfo> list = dao.getById(id);
//这里还是使用模拟的数据
List<SchedulerTaskInfo> list = taskScheduler.getAllSchedulerTaskInfo();
SchedulerTaskInfo st = list.get(0);
taskScheduler.start(st);
map.put("msg", "success");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return map;
}
@RequestMapping("/stop")
@ResponseBody
public Map<String, Object> stop(String id){
Map<String, Object> map = new HashMap<>();
try {
//直接传id,去任务池中找对应的任务并且stop
taskScheduler.stop(id);
map.put("msg", "success");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return map;
}
}
package com.wr.app.Runnable;
//处理具体的定时任务业务
public class SchedulerTask implements Runnable{
@Override
public void run() {
System.out.println("执行SchedulerTask中的run方法");
}
}
package com.wr.app.Runnable;
//处理具体的定时任务业务
public class SchedulerTask2 implements Runnable{
@Override
public void run() {
System.out.println("执行SchedulerTask2中的run方法");
}
}
package com.wr.app.scheduler;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Component;
import com.alibaba.fastjson.JSONObject;
import com.wr.app.baen.SchedulerTaskInfo;
import java.util.concurrent.ScheduledFuture;
@Component
public class TaskScheduler {
private static final Logger logger = LoggerFactory.getLogger(TaskScheduler.class);
private static TaskScheduler instance;
private static ThreadPoolTaskScheduler threadPoolTaskScheduler;
//任务调度器开关,可配置启动项目是否开启定时任务
@Value("${open}")
private String open;
//存放task
public final Map<String,ScheduledFuture<?>> taskmap = new ConcurrentHashMap<String,ScheduledFuture<?>>();
//单例模式
public static synchronized TaskScheduler getInstance(){
if(instance == null){
instance = new TaskScheduler();
}
return instance;
}
public synchronized ThreadPoolTaskScheduler getThreadPoolTaskScheduler() {
if (threadPoolTaskScheduler == null) {
threadPoolTaskScheduler = new ThreadPoolTaskScheduler();
threadPoolTaskScheduler.initialize();
threadPoolTaskScheduler.setPoolSize(200);
threadPoolTaskScheduler.setAwaitTerminationSeconds(60);
threadPoolTaskScheduler.setWaitForTasksToCompleteOnShutdown(true);
}
return threadPoolTaskScheduler;
}
public TaskScheduler(){
getThreadPoolTaskScheduler();
}
//启动数据库中配置的所有的符合条件的定时任务
public String startAll() throws Exception{
//启动前先清空任务池
stopAll();
JSONObject jsonParam = new JSONObject();
jsonParam.put("status", "enable");
//获取目前所有可执行的定时任务
List<SchedulerTaskInfo> list = getAllSchedulerTaskInfo();
for(SchedulerTaskInfo st : list){
start(st);
}
return "startAll";
}
//将定时任务放入任务池中
public String start(SchedulerTaskInfo st) throws Exception{
//启动任务前线关闭任务
stop(st.getId());
if(taskmap.get(st.getId())==null){
invoke(st);
}else{
logger.info("task " + st.getId() + " is started");
}
return "start";
}
//停止某一个任务
public String stop(String id) throws Exception{
ScheduledFuture<?> future = taskmap.get(id);
if(future!=null){
future.cancel(true);
taskmap.remove(id);
logger.info("task " + id + " is stop");
}
return "stop";
}
// 停止所有
public String stopAll() throws Exception {
Iterator<String> it = taskmap.keySet().iterator();
while(it.hasNext()){
String key = it.next();
stop(key);
}
return "stopAll";
}
// 修改某一个任务
public String changeAndStart(SchedulerTaskInfo st) throws Exception {
//启动任务前线关闭任务
stop(st.getId());
if(taskmap.get(st.getId())==null){
logger.info("task " + st.getId() + " changing");
invoke(st);
}
return "changeAndStart";
}
//invoke方法
public String invoke(SchedulerTaskInfo st) throws Exception {
if("yes".equals(open)){
Class c = Class.forName(st.getTaskClass());
logger.info("task" + st.getId() + " starting");
Runnable runnable = (Runnable) c.newInstance();
ScheduledFuture<?> future = threadPoolTaskScheduler.schedule(runnable, new CronTrigger(st.getCron()));
taskmap.put(st.getId(), future);
logger.info("task " + st.getId() + " started");
}else{
logger.info("任务调度器开关默认关闭。。。");
}
return "invoke";
}
//模拟去数据库查询数据
public List<SchedulerTaskInfo> getAllSchedulerTaskInfo() throws Exception{
List<SchedulerTaskInfo> list = new ArrayList<SchedulerTaskInfo>();
SchedulerTaskInfo st = new SchedulerTaskInfo();
st.setId("1");
st.setTaskName("定时任务1");
st.setStatus("enable");
st.setTaskClass("com.wr.app.Runnable.SchedulerTask");
st.setCron("*/5 * * * * ?");
st.setRemark("1");
list.add(st);
SchedulerTaskInfo st2 = new SchedulerTaskInfo();
st2.setId("2");
st2.setTaskName("定时任务2");
st2.setStatus("enable");
st2.setTaskClass("com.wr.app.Runnable.SchedulerTask2");
st2.setCron("*/10 * * * * ?");
st2.setRemark("2");
list.add(st2);
return list;
}
}
下面是运行结果