实现动态修改cron表达式来更改定时任务的规则,程序不重启,且使用定时任务线程池加快效率。
一、配置类
@Configuration
@EnableAsync
@EnableScheduling
@Slf4j
public class SchedulerThreadPoolConfig implements SchedulingConfigurer, AsyncConfigurer {
/**
* 定时任务使用的线程池
* @return
*/
@Bean(destroyMethod = "shutdown", name = "taskScheduler")
public ThreadPoolTaskScheduler taskScheduler(){
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
scheduler.setPoolSize(10);
scheduler.setThreadNamePrefix("task-");
scheduler.setAwaitTerminationSeconds(600);
scheduler.setWaitForTasksToCompleteOnShutdown(true);
return scheduler;
}/**
* 异步任务执行线程池
* @return
*/
@Bean(name = "asyncExecutor")
public ThreadPoolTaskExecutor asyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(10);
executor.setQueueCapacity(1000);
executor.setKeepAliveSeconds(600);
executor.setMaxPoolSize(20);
executor.setThreadNamePrefix("taskExecutor-");
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.initialize();
return executor;
}@Override
public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
ThreadPoolTaskScheduler taskScheduler = taskScheduler();
scheduledTaskRegistrar.setTaskScheduler(taskScheduler);
}@Override
public Executor getAsyncExecutor() {
return asyncExecutor();
}@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return (throwable, method, objects) -> {
log.error("异步任务执行出现异常, message {}, emthod {}, params {}", throwable, method, objects);
};
}
}
【springboot动态cron定时任务】二、创建一个定时任务接口,继承runnable(就一个任务可不写)
public interface SchedulerTaskJob extends Runnable {
}
三、任务实现类
import com.mixislink.entity.Data;
import com.mixislink.entity.SubsidyRecord;
import com.mixislink.service.DataService;
import com.mixislink.service.SubsidyRecordService;
import com.mixislink.utils.Constants;
import com.mixislink.utils.RedisTool;
import com.mixislink.utils.UUIDUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.TriggerContext;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* @Author WuSong
* @Date 2020-07-10
* @Time 17:17:14
*/
@Slf4j
@Component
public class SettleAccountsTask implements SchedulerTaskJob {
@Autowired
private RedisTool redisTool;
@Resource(name = "taskScheduler")
private ThreadPoolTaskScheduler threadPoolTaskScheduler;
@Override
public void run() {
//do something
log.info("定时任务执行完毕!");
}//启动或更新定时任务
public void doStartTask(){
//redis中取表达式
String taskCron=redisTool.get(Constants.RULES_KEY);
if (StringUtils.isNotBlank(taskCron)){
Trigger trigger = new Trigger() {
@Override
public Date nextExecutionTime(TriggerContext triggerContext) {
CronTrigger cronTrigger = new CronTrigger(taskCron);
return cronTrigger.nextExecutionTime(triggerContext);
}
};
threadPoolTaskScheduler.schedule(this, trigger);
}
}}
四、加入启动时读cron表达式
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
/**
* @Author WuSong
* @Date 2020-07-13
* @Time 16:55:13
*/
@Component
@Order(1)
public class TaskTriggerRunner implements CommandLineRunner {
@Autowired
private SettleAccountsTask settleAccountsTask;
@Override
public void run(String... args) throws Exception {
settleAccountsTask.doStartTask();
}
}
五、提供web接口方式修改cron表达式
@PutMapping
public HttpEntity updateRules(@RequestBody Rules rules){
try {
String[] time = rules.getTime().split(":");
int date = rules.getDate();
String cron = null;
if (rules.getType() == 1){
//0 0 6 ? * 1每周一6点
cron = new StringBuffer(time[2]).append(" ").append(time[1]).append(" ")
.append(time[0]).append(" ").append("?").append(" ").append("*")
.append(" ").append(date).toString();
}else if (rules.getType() == 2){
//0 0 6 20 * ?每月20号6点
cron = new StringBuffer(time[2]).append(" ").append(time[1]).append(" ")
.append(time[0]).append(" ").append(date).append(" ").append("*")
.append(" ").append("?").toString();
}else if (rules.getType() == 3){
//0 0 6 20 2 ?每年2月20号6点
cron = new StringBuffer(time[2]).append(" ").append(time[1]).append(" ")
.append(time[0]).append(" ").append(date).append(" ").append(rules.getMonth())
.append(" ").append("?").toString();
}
//将cron表达式放入redis
if (cron!=null)
redisTool.set(Constants.RULES_KEY, cron);
//更新一下定时任务的表达式
settleAccountsTask.doStartTask();
return new HttpEntity();
} catch (Exception e) {
log.error("settleAccounts",e);
return new HttpEntity(Define.STATUS_INTERNAL_ERROR,Define.MSG_INTERNAL_ERROR);
}
}//Rules类字段,封装给前端用的
private Integer type;
//1每周 2 每月 3 每年
private Integer date;
//周1234567 月1-31 年1-12
private String time;
//时分秒
private Integer month;
//月份(每年专用)
推荐阅读
- Java|Java基础——数组
- 人工智能|干货!人体姿态估计与运动预测
- java简介|Java是什么(Java能用来干什么?)
- Java|规范的打印日志
- Linux|109 个实用 shell 脚本
- 程序员|【高级Java架构师系统学习】毕业一年萌新的Java大厂面经,最新整理
- Spring注解驱动第十讲--@Autowired使用
- SqlServer|sql server的UPDLOCK、HOLDLOCK试验
- jvm|【JVM】JVM08(java内存模型解析[JMM])
- 技术|为参加2021年蓝桥杯Java软件开发大学B组细心整理常见基础知识、搜索和常用算法解析例题(持续更新...)