Spring task的三种典型的应用模式可以集成在传统springMVC项目,也可以在SpringBoot项目中,优点比较轻量,不需要添加过多依赖,缺点分布式支持不友好
不累赘叙述task的引用了,常用模式有:
1. 静态定时
直接使用@Scheduled注释,缺点cron表达的信息固定不可变
2. 修改定时器
import java.util.Date;
import org.apache.log4j.Logger;
import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.TriggerContext;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@EnableScheduling
@RequestMapping("/task")
public class TaskController implements SchedulingConfigurer {
private Logger logger = Logger.getLogger(TaskController.class);
/**
* 定时任务的定时器表达式: 秒 分 时 日期 月 星期
* 注意:有的地方说定时正则表达式可以有year,即7个元素,但是,在spring-boot里面,只能是6个元素,没有年。
*/
private String cronExpression = "1/5 * * * * *";
/**
* 通过REST API请求对参数进行修改,定时规则进行调整
* @param exp
* @return
*/
@RequestMapping("/change")
public String change(@RequestParam("exp") String exp) {
cronExpression = exp;
logger.info("new cron expression: " + exp);
return cronExpression;
}
/**
* 定时任务要执行的方法
* @return
*/
private Runnable getTask() {
Runnable task = new Runnable() {
@Override
public void run() {
logger.info("==定时任务==开始: " + new Date());
//业务处理,忽视所有异常
try {
//do something
} catch (Exception e) {
e.printStackTrace();
}
logger.info("==定时任务==结束: " + new Date());
}
};
return task;
}
/**
* 调度实现的时间控制
* @param scheduledTaskRegistrar
*/
@Override
public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
Trigger trigger=new Trigger() {
@Override
public Date nextExecutionTime(TriggerContext triggerContext) {
CronTrigger cronTrigger=new CronTrigger(cronExpression);
return cronTrigger.nextExecutionTime(triggerContext);
}
};
scheduledTaskRegistrar.addTriggerTask(getTask(), trigger);
}
}
缺点:控制不强,没有持久化,不随时启动停止
3. 动态启动和停止以及修改定时规则
/**
* 定时任务核心类
* @ClassName: TimmerComponent
*/
@Component
public class TimmerComponent {
// 保存任务
private Map<String, ScheduledFuture<?>> futuresMap = new ConcurrentHashMap<String, ScheduledFuture<?>>();
private Logger logger = Logger.getLogger(TimmerComponent.class);
//持久化任务
//@Autowired
//private ITaskJobDao taskJobDao;
// 创建ThreadPoolTaskScheduler线程池
private ThreadPoolTaskScheduler threadPoolTaskScheduler;
@Bean
public ThreadPoolTaskScheduler getThreadPoolTaskScheduler(){
threadPoolTaskScheduler = new ThreadPoolTaskScheduler();
threadPoolTaskScheduler.setPoolSize(20);
threadPoolTaskScheduler.setThreadNamePrefix("task-");
threadPoolTaskScheduler.setAwaitTerminationSeconds(60);
threadPoolTaskScheduler.setWaitForTasksToCompleteOnShutdown(true);
threadPoolTaskScheduler.initialize();
return threadPoolTaskScheduler;
}
// 初始化任务
@Bean
public Map<String, ScheduledFuture<?>> initTimmer(){
//启动时获取持久化任务,可以避免服务重启任务丢失,如不需要可以注释
// List<WelcomTaskJob> list = welcomTaskJobDao.getList4Enable();
// for (WelcomTaskJob s : list){
// ScheduledFuture<?> future = threadPoolTaskScheduler.schedule(getRunnable(s), getTrigger(s));
// futuresMap.put(s.getTaskJobCode(), future);
// }
return futuresMap;
}
/**
* 添加任务
* @param s
*/
public void addTask(WelcomTaskJob s){
logger.info("定时任务#====>添加: " + new Date());
ScheduledFuture<?> future = threadPoolTaskScheduler.schedule(getRunnable(s), getTrigger(s));
futuresMap.put(s.getTaskJobCode(), future);
}
/**
* 暂停任务
* @param key
* @return
*/
public boolean cancelTask(String key) {
logger.info("定时任务#====>取消: " + new Date());
ScheduledFuture<?> toBeRemovedFuture = futuresMap.remove(key);
if (toBeRemovedFuture != null) {
toBeRemovedFuture.cancel(true);
return true;
} else {
return false;
}
}
/**
* 更新任务
* @param s
*/
public void updateTask(WelcomTaskJob s) {
logger.info("定时任务#====>更新: " + new Date());
ScheduledFuture<?> toBeRemovedFuture = futuresMap.remove(s.getTaskJobCode());
if (toBeRemovedFuture != null) {
toBeRemovedFuture.cancel(true);
}
ScheduledFuture<?> future = threadPoolTaskScheduler.schedule(getRunnable(s), getTrigger(s));
futuresMap.put(s.getTaskJobCode(), future);
}
/**
* 转换首字母小写
*
* @param str
* @return
*/
public static String lowerFirstCapse(String str) {
char[] chars = str.toCharArray();
chars[0] += 32;
return String.valueOf(chars);
}
/**
* runnable
* @param taskJob
* @return
*/
private Runnable getRunnable(WelcomTaskJob taskJob){
return new Runnable() {
@Override
public void run() {
Class<?> clazz;
try {
logger.info("定时任务#====>启动: " + new Date());
//使用反射原理来获取执行操作类及方法,注意可能无法获取登录用户信息,业务操作中请勿绑定
clazz = Class.forName(taskJob.getClassName());
String className = lowerFirstCapse(clazz.getSimpleName());
Object bean = (Object) ApplicationContextHelper.getBean(className);
Method method = ReflectionUtils.findMethod(bean.getClass(), taskJob.getMethodName());
ReflectionUtils.invokeMethod(method, bean);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
};
}
/**
* Trigger
* @param taskJob
* @return
*/
private Trigger getTrigger(WelcomTaskJob taskJob){
return new Trigger() {
@Override
public Date nextExecutionTime(TriggerContext triggerContext) {
CronTrigger trigger = new CronTrigger(taskJob.getCron());
Date nextExec = trigger.nextExecutionTime(triggerContext);
return nextExec;
}
};
}
}
/**
* 获取bean
* @ClassName: ApplicationContextHelper
*/
@Component
public class ApplicationContextHelper implements ApplicationContextAware {
private static ApplicationContext applicationContext;
public ApplicationContextHelper() {
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
ApplicationContextHelper.applicationContext = applicationContext;
}
public static Object getBean(String beanName) {
return applicationContext != null?applicationContext.getBean(beanName):null;
}
}
参考 : https://www.cnblogs.com/shihuc/p/9275780.html
https://blog.csdn.net/xcc_2269861428/article/details/100023788