一、使用 @scheduled 注解
@scheduled 是 spring 提供的一个注解,用于标记需要定时执行的方法。常见的属性包括:
- cron :通过 cron 表达式定义任务的执行时间。
- fixedrate :定义任务的固定执行频率,以毫秒为单位。
- fixeddelay :定义任务在前一次执行完毕后延迟多少毫秒再执行。
代码示例:
import org.springframework.scheduling.annotation.scheduled;
import org.springframework.stereotype.component;
@component
public class scheduledtasks {
@scheduled(cron = "0 0 * * * ?") // 每小时整点执行一次
public void reportcurrenttime() {
system.out.println("现在时间:" + system.currenttimemillis());
}
@scheduled(fixedrate = 5000) // 每5秒执行一次
public void fixedratetask() {
system.out.println("每5秒执行一次任务:" + system.currenttimemillis());
}
@scheduled(fixeddelay = 7000) // 前一次执行完毕后延迟7秒执行
public void fixeddelaytask() {
system.out.println("延迟7秒后执行任务:" + system.currenttimemillis());
}
}@scheduled 适用于大多数简单的定时任务场景,如定时发送邮件或生成报告等。然而,它的灵活性较差,对于复杂的任务调度需求,或需要动态调整任务时间的场景,可能并不适用。
二、使用 schedulingconfigurer 接口
schedulingconfigurer 接口允许我们通过编程方式配置任务调度器(taskscheduler)。通过实现这个接口,我们可以灵活地设置任务的调度规则,甚至动态地添加或移除任务。
简单使用代码:
public class taskconfig implements schedulingconfigurer {
@override
public void configuretasks(scheduledtaskregistrar scheduledtaskregistrar) {
scheduledtaskregistrar.addtriggertask(
//1.添加任务内容(runnable)
() -> system.out.println("执行定时任务2: " + localdatetime.now().tolocaltime()),
//2.设置执行周期(trigger)
triggercontext -> {
//2.1 从数据库获取执行周期
string cron = zhymapper.getcron();
//2.2 合法性校验.
if (stringutils.isempty(cron)) {
// omitted code ..
}
//2.3 返回执行周期(date)
return new crontrigger(cron).nextexecutiontime(triggercontext);
}
);
}
}详细增删该查操作:
- 动态注册bean
public class applicationcontextutils implements applicationcontextaware {
private static applicationcontext context;
/**
* 设置spring上下文
* @param ctx spring上下文
* @throws beansexception
* */
@override
public void setapplicationcontext(applicationcontext ctx) throws beansexception {
context = ctx;
}
/**
* 获取容器
* @return
*/
public static applicationcontext getapplicationcontext() {
return context;
}
/**
* 获取容器对象
* @param type
* @param <t>
* @return
*/
public static <t> t getbean(class<t> type) {
return context.getbean(type);
}
public static <t> t getbean(string name,class<t> clazz){
return context.getbean(name, clazz);
}
public static object getbean(string name){
return context.getbean(name);
}
/**
* springboot动态注册bean
* @param clazz
* @param <t>
* @return
*/
public static <t> t register(class<t> clazz) {
configurableapplicationcontext configurableapplicationcontext = (configurableapplicationcontext) applicationcontextutils.getapplicationcontext();
defaultlistablebeanfactory defaultlistablebeanfactory = (defaultlistablebeanfactory) configurableapplicationcontext.getbeanfactory();
beandefinitionbuilder beandefinitionbuilder = beandefinitionbuilder.genericbeandefinition(clazz);
if(defaultlistablebeanfactory.getbeannamesfortype(clazz).length > 0) {
return defaultlistablebeanfactory.getbean(clazz);
}
defaultlistablebeanfactory.registerbeandefinition(clazz.getname(), beandefinitionbuilder.getrawbeandefinition());
return (t) applicationcontextutils.getbean(clazz.getname());
}
}
- 任务实体
public class job {
/**
* 任务id, 用于标识,默认使用全限定类名
*/
private string jobid;
/**
* 任务名称, 默认简单类名
*/
private string jobname;
/**
* cron表达式, 修改后即可生效
*/
private string cron;
/**
* 任务描述
*/
private string description;
/**
* 是否启用, 默认启用, 修改后即可生效
*/
private boolean enable = true;
/**
* 是否处于等待执行下个任务的状态
*/
private boolean active;
/**
* 任务运行类
*/
private class<? extends runnable> clazz;
}- 操作类
public class jobhandler {
private scheduledtask scheduledtask;
private triggertask triggertask;
private triggercontext triggercontext;
}- 配置schedulingconfigurer
public class jobschedulingconfigurer implements schedulingconfigurer {
private scheduledtaskregistrar registrar;
/**
* 线程池任务调度器
*/
@bean
public taskscheduler taskscheduler() {
threadpooltaskscheduler scheduler = new threadpooltaskscheduler();
scheduler.setpoolsize(runtime.getruntime().availableprocessors() / 3 + 1);
scheduler.setthreadnameprefix("taskscheduler-");
scheduler.setremoveoncancelpolicy(true); // 保证能立刻丢弃运行中的任务
taskscheduler = scheduler; // 获取 句柄,方便后期获取 future
return scheduler;
}
@override
public void configuretasks(scheduledtaskregistrar scheduledtaskregistrar) {
scheduledtaskregistrar.settaskscheduler(taskscheduler());
this.registrar = scheduledtaskregistrar;
}
public scheduledtaskregistrar getregistrar() {
return registrar;
}
public void setregistrar(scheduledtaskregistrar registrar) {
this.registrar = registrar;
}
}- 增删改查
public class schedulermanager {
/**
* 任务容器
*/
private map<job, jobhandler> tasks = new concurrenthashmap<>();
/**
* 任务注册
*/
@autowired
private jobschedulingconfigurer register;
/**
* 新增任务, 自生效
* @param job 任务实体
* @return 返回新增的任务
*/
public job addjob(job job) {
assert.notnull(job, "job can't be null");
scheduledtaskregistrar registrar = register.getregistrar();
runnable runnable = applicationcontextutils.register(job.getclazz());
if(job.getjobid() == null || "".equals(job.getjobid())) {
job.setjobid(job.getclazz().getname());
}
assert.isnull(this.getjob(job.getjobid()), "任务[" + job.getjobid() + "]已存在");
if(job.getjobname() == null || "".equals(job.getjobname())) {
job.setjobname(classutils.getshortname(job.getclazz()));
}
cronexpress cron = annotationutils.findannotation(job.getclazz(), cronexpress.class);
if(cron != null && !"".equals(cron.value())) {
// 注解的属性,大于配置的属性,方便调试
job.setcron(cron.value());
}
job.setenable(true);
job.setactive(true);
jobhandler entity = new jobhandler();
triggertask triggertask = new triggertask(runnable, (triggercontext triggercontext) -> {
// 每次任务执行均会进入此方法
crontrigger trigger = new crontrigger(job.getcron());
entity.settriggercontext(triggercontext);
return job.isenable() ? trigger.nextexecutiontime(triggercontext) : null;
});
scheduledtask scheduledtask = registrar.scheduletriggertask(triggertask);
entity.setscheduledtask(scheduledtask);
entity.settriggertask(triggertask);
tasks.put(job, entity);
return job;
}
/**
* 任务类(必须标注了@cronexpress注解,且实现了runnable接口)
* @param clazz 接口类
* @return 任务对象
*/
public job addjob(class<? extends runnable> clazz) {
job job = new job();
job.setclazz(clazz);
return this.addjob(job);
}
/**
* 获取任务操作对象
* @param jobid 任务id
* @return 任务操作对象
*/
public jobhandler getjobhandler(string jobid) {
return tasks.get(new job(jobid));
}
/**
* 根据任务id获取任务
* @param jobid 任务id
* @return 任务实体
*/
public job getjob(string jobid) {
assert.hastext(jobid, "jobid can't be null");
set<job> jobs = tasks.keyset();
if(jobs.size() == 0) {
return null;
}
iterator<job> iterator = jobs.iterator();
while (iterator.hasnext()) {
job next = iterator.next();
if(jobid.equals(next.getjobid())) {
return next;
}
}
return null;
}
/**
* 关闭任务(若任务正在执行,待任务执行完)
* @param jobid 任务id
* @return 是否关闭成功
*/
public boolean shutdown(string jobid) {
try {
jobhandler handler = this.getjobhandler(jobid);
assert.notnull(handler, "任务[" + jobid + "]不存在");
handler.getscheduledtask().cancel();
job job = getjob(jobid);
job.setactive(false);
return true;
} catch (exception e) {
return false;
}
}
/**
* 启动已经注册的任务
* @param jobid 任务id
* @return 是否成功启动
*/
public boolean startup(string jobid) {
try {
jobhandler handler = this.getjobhandler(jobid);
assert.notnull(handler, "任务[" + jobid + "]不存在");
register.getregistrar().scheduletriggertask(handler.gettriggertask());
job job = getjob(jobid);
job.setactive(true);
return true;
} catch (exception e) {
return false;
}
}
/**
* 获取所有的任务实体
* @return
*/
public list<job> getjobs() {
return new arraylist<>(tasks.keyset());
}
/**
* 删除任务,先关闭再删除
* @param jobid
* @return
*/
public boolean deletejob(string jobid) {
try {
job job = this.getjob(jobid);
assert.notnull(job, "任务[" + jobid + "]不存在");
shutdown(jobid);
tasks.remove(job);
return true;
} catch (exception e) {
return false;
}
}
}
- 任务运行类
@cronexpress("0/1 * * * * *")
public class hellojob implements runnable {
@override
public void run() {
system.out.println("hello msg" + thread.currentthread().getid());
}
}- 测试
configurableapplicationcontext ctx = springapplication.run(unifiedtaskschedulestarterapplication.class, args); schedulermanager schedulermanager = ctx.getbean(schedulermanager.class); job job = schedulermanager.addjob(com.github.softwarevax.web.hellojob.class); schedulermanager.shutdown(job.getjobid());
三、使用 taskscheduler
taskscheduler 是spring提供的用于调度任务的核心接口。通过 taskscheduler,你可以灵活地安排任务的执行时间,并且可以在运行时动态地创建、取消任务。
代码示例简单使用:
import org.springframework.context.annotation.bean;
import org.springframework.context.annotation.configuration;
import org.springframework.scheduling.taskscheduler;
import org.springframework.scheduling.concurrent.threadpooltaskscheduler;
@configuration
public class taskschedulerconfig {
@bean
public taskscheduler taskscheduler() {
threadpooltaskscheduler scheduler = new threadpooltaskscheduler();
scheduler.setpoolsize(5);
scheduler.setthreadnameprefix("myscheduler-");
return scheduler;
}
}在使用 taskscheduler 时,可以通过 schedule 方法动态安排任务:
import org.springframework.beans.factory.annotation.autowired;
import org.springframework.scheduling.taskscheduler;
import org.springframework.stereotype.component;
import java.util.date;
@component
public class dynamictask {
@autowired
private taskscheduler taskscheduler;
public void scheduletask() {
taskscheduler.schedule(() -> system.out.println("动态任务执行:" + system.currenttimemillis()), new date(system.currenttimemillis() + 5000));
}
}spring boot使用taskscheduler实现动态增删启停定时任务
- schedulingconfig:添加执行定时任务的线程池配置类
import org.springframework.context.annotation.bean;
import org.springframework.context.annotation.configuration;
import org.springframework.scheduling.taskscheduler;
import org.springframework.scheduling.concurrent.threadpooltaskscheduler;
@configuration
public class schedulingconfig {
@bean
public taskscheduler taskscheduler() {
threadpooltaskscheduler taskscheduler = new threadpooltaskscheduler();
// 定时任务执行线程池核心线程数
taskscheduler.setpoolsize(4);
taskscheduler.setremoveoncancelpolicy(true);
taskscheduler.setthreadnameprefix("taskschedulerthreadpool-");
return taskscheduler;
}
}- scheduledtask:添加scheduledfuture的包装类
scheduledfuture是scheduledexecutorservice定时任务线程池的执行结果。
import java.util.concurrent.scheduledfuture;
public final class scheduledtask {
volatile scheduledfuture<?> future;
/**
* 取消定时任务
*/
public void cancel() {
scheduledfuture<?> future = this.future;
if (future != null) {
future.cancel(true);
}
}
}- schedulingrunnable:添加runnable接口实现类
添加runnable接口实现类,被定时任务线程池调用,用来执行指定bean里面的方法
import org.apache.commons.lang.stringutils;
import org.slf4j.logger;
import org.slf4j.loggerfactory;
import org.springframework.util.reflectionutils;
import java.lang.reflect.method;
import java.util.objects;
public class schedulingrunnable implements runnable {
private static final logger logger = loggerfactory.getlogger(schedulingrunnable.class);
private final string beanname;
private final string methodname;
private final string params;
public schedulingrunnable(string beanname, string methodname) {
this(beanname, methodname, null);
}
public schedulingrunnable(string beanname, string methodname, string params) {
this.beanname = beanname;
this.methodname = methodname;
this.params = params;
}
@override
public void run() {
logger.info("定时任务开始执行 - bean:{},方法:{},参数:{}", beanname, methodname, params);
long starttime = system.currenttimemillis();
try {
object target = springcontextutils.getbean(beanname);
method method = null;
if (stringutils.isnotempty(params)) {
method = target.getclass().getdeclaredmethod(methodname, string.class);
} else {
method = target.getclass().getdeclaredmethod(methodname);
}
reflectionutils.makeaccessible(method);
if (stringutils.isnotempty(params)) {
method.invoke(target, params);
} else {
method.invoke(target);
}
} catch (exception ex) {
logger.error(string.format("定时任务执行异常 - bean:%s,方法:%s,参数:%s ", beanname, methodname, params), ex);
}
long times = system.currenttimemillis() - starttime;
logger.info("定时任务执行结束 - bean:{},方法:{},参数:{},耗时:{} 毫秒", beanname, methodname, params, times);
}
@override
public boolean equals(object o) {
if (this == o) return true;
if (o == null || getclass() != o.getclass()) return false;
schedulingrunnable that = (schedulingrunnable) o;
if (params == null) {
return beanname.equals(that.beanname) &&
methodname.equals(that.methodname) &&
that.params == null;
}
return beanname.equals(that.beanname) &&
methodname.equals(that.methodname) &&
params.equals(that.params);
}
@override
public int hashcode() {
if (params == null) {
return objects.hash(beanname, methodname);
}
return objects.hash(beanname, methodname, params);
}
}- crontaskregistrar:添加定时任务注册类,用来增加、删除定时任务
import com.example.testspringboot.cron.scheduleresult;
import org.springframework.beans.factory.disposablebean;
import org.springframework.beans.factory.annotation.autowired;
import org.springframework.scheduling.taskscheduler;
import org.springframework.scheduling.config.crontask;
import org.springframework.stereotype.component;
import java.util.*;
import java.util.concurrent.concurrenthashmap;
/**
* 添加定时任务注册类,用来增加、删除定时任务。
*/
@component
public class crontaskregistrar implements disposablebean {
private final map<runnable, scheduledtask> scheduledtasks = new concurrenthashmap<>(16);
private final map<integer, scheduleresult> schedulerjob = new hashmap<>();
@autowired
private taskscheduler taskscheduler;
public taskscheduler getscheduler() {
return this.taskscheduler;
}
public void addcrontask(scheduleresult scheduleresult) {
schedulingrunnable task = new schedulingrunnable(scheduleresult.getbeanname(), scheduleresult.getmethodname(), scheduleresult.getmethodparams());
string cronexpression = scheduleresult.getcronexpression();
crontask crontask = new crontask(task, cronexpression);
// 如果当前包含这个任务,则移除
if (this.scheduledtasks.containskey(task)) {
removecrontask(scheduleresult.getbeanname(), scheduleresult.getmethodname(), scheduleresult.getmethodparams());
}
schedulerjob.put(scheduleresult.getjobid(), scheduleresult);
this.scheduledtasks.put(task, schedulecrontask(crontask));
}
public void removecrontask(string beanname, string methodname, string methodparams) {
schedulingrunnable task = new schedulingrunnable(beanname, methodname, methodparams);
scheduledtask scheduledtask = this.scheduledtasks.remove(task);
if (scheduledtask != null) {
scheduledtask.cancel();
}
}
public void removecrontask(scheduleresult scheduleresult) {
schedulerjob.put(scheduleresult.getjobid(), scheduleresult);
removecrontask(scheduleresult.getbeanname(), scheduleresult.getmethodname(), scheduleresult.getmethodparams());
}
public scheduledtask schedulecrontask(crontask crontask) {
scheduledtask scheduledtask = new scheduledtask();
scheduledtask.future = this.taskscheduler.schedule(crontask.getrunnable(), crontask.gettrigger());
return scheduledtask;
}
public map<runnable, scheduledtask> getscheduledtasks() {
return scheduledtasks;
}
public map<integer, scheduleresult> getschedulerjob() {
return schedulerjob;
}
@override
public void destroy() {
for (scheduledtask task : this.scheduledtasks.values()) {
task.cancel();
}
this.scheduledtasks.clear();
}
public scheduleresult getschedulerbyjobid(integer jobid) {
for (scheduleresult job : findalltask()) {
if (jobid.equals(job.getjobid())) {
return job;
}
}
return null;
}
public list<scheduleresult> findalltask() {
list<scheduleresult> scheduleresults = new arraylist<>();
set<map.entry<integer, scheduleresult>> entries = schedulerjob.entryset();
for (map.entry<integer, scheduleresult> en : entries) {
scheduleresults.add(en.getvalue());
}
return scheduleresults;
}
}- cronutils:校验cron表达式的有效性
import org.springframework.scheduling.support.cronexpression;
public class cronutils {
/**
* 返回一个布尔值代表一个给定的cron表达式的有效性
*
* @param cronexpression cron表达式
* @return boolean 表达式是否有效
*/
public static boolean isvalid(string cronexpression) {
return cronexpression.isvalidexpression(cronexpression);
}
}- scheduleresult:添加定时任务实体类
import lombok.data;
@data
public class scheduleresult {
/**
* 任务id
*/
private integer jobid;
/**
* bean名称
*/
private string beanname;
/**
* 方法名称
*/
private string methodname;
/**
* 方法参数: 执行service里面的哪一种方法
*/
private string methodparams;
/**
* cron表达式
*/
private string cronexpression;
/**
* 状态(1正常 0暂停)
*/
private integer jobstatus;
/**
* 备注
*/
private string remark;
/**
* 创建时间
*/
private string createtime;
/**
* 更新时间
*/
private string updatetime;
}- schedulejobstatus:任务状态枚举类型
public enum schedulejobstatus {
/**
* 暂停
*/
pause,
/**
* 正常
*/
normal;
}- springcontextutils类:从spring容器里获取bean
import org.springframework.beans.beansexception;
import org.springframework.context.applicationcontext;
import org.springframework.context.applicationcontextaware;
import org.springframework.stereotype.component;
@component
public class springcontextutils implements applicationcontextaware {
private static applicationcontext applicationcontext = null;
@override
public void setapplicationcontext(applicationcontext applicationcontext) throws beansexception {
if (springcontextutils.applicationcontext == null) {
springcontextutils.applicationcontext = applicationcontext;
}
}
public static applicationcontext getapplicationcontext() {
return applicationcontext;
}
// 通过name获取 bean.
public static object getbean(string name) {
return getapplicationcontext().getbean(name);
}
// 通过class获取bean.
public static <t> t getbean(class<t> clazz) {
return getapplicationcontext().getbean(clazz);
}
// 通过name,以及clazz返回指定的bean
public static <t> t getbean(string name, class<t> clazz) {
return getapplicationcontext().getbean(name, clazz);
}
public static boolean containsbean(string name) {
return getapplicationcontext().containsbean(name);
}
public static boolean issingleton(string name) {
return getapplicationcontext().issingleton(name);
}
public static class<? extends object> gettype(string name) {
return getapplicationcontext().gettype(name);
}
}- schedulejobservice:增删启停service方法
@service
@slf4j
public class schedulejobservice {
@autowired
private crontaskregistrar crontaskregistrar;
public void addschedulejob(scheduleresult scheduleresult) {
long currenttimemillis = system.currenttimemillis();
scheduleresult.setcreatetime(formattimeymd_hms_sss(currenttimemillis));
scheduleresult.setupdatetime(formattimeymd_hms_sss(currenttimemillis));
scheduleresult.setjobid(findalltask().size() + 1);
if (scheduleresult.getjobstatus().equals(schedulejobstatus.normal.ordinal())) {
log.info("stop or pause: is now on");
crontaskregistrar.addcrontask(scheduleresult);
return;
}
crontaskregistrar.getschedulerjob().put(scheduleresult.getjobid(), scheduleresult);
}
public void editschedulejob(scheduleresult currentschedule) {
//先移除
crontaskregistrar.removecrontask(currentschedule.getbeanname(), currentschedule.getmethodname(), currentschedule.getmethodparams());
scheduleresult pastschedulejob = crontaskregistrar.getschedulerbyjobid(currentschedule.getjobid());
if (pastschedulejob == null) {
system.out.println("没有这个任务");
return;
}
//然后判断是否开启, 如果开启的话,现在立即执行
startorstopschedulerjob(currentschedule, true);
}
public void deleteschedulejob(scheduleresult scheduleresult) {
// 清除这个任务
crontaskregistrar.removecrontask(scheduleresult.getbeanname(), scheduleresult.getmethodname(), scheduleresult.getmethodparams());
// 清除这个任务的数据
crontaskregistrar.getschedulerjob().remove(scheduleresult.getjobid());
}
public void startorstopscheduler(scheduleresult scheduleresult) {
crontaskregistrar.getschedulerjob().get(scheduleresult.getjobid()).setjobstatus(scheduleresult.getjobstatus());
startorstopschedulerjob(scheduleresult, false);
}
private void startorstopschedulerjob(scheduleresult scheduleresult, boolean update) {
// 更新时间
scheduleresult.setupdatetime(formattimeymd_hms_sss(system.currenttimemillis()));
if (scheduleresult.getjobstatus().equals(schedulejobstatus.normal.ordinal())) {
system.out.println("停止或暂停:现在是开启");
crontaskregistrar.addcrontask(scheduleresult);
return;
}
system.out.println("停止或暂停:现在是暂停");
if (update){
crontaskregistrar.removecrontask(scheduleresult);
return;
}
crontaskregistrar.removecrontask(scheduleresult.getbeanname(), scheduleresult.getmethodname(), scheduleresult.getmethodparams());
}
public list<scheduleresult> findalltask() {
return crontaskregistrar.findalltask();
}
// 转换为年-月-日 时:分:秒
private string formattimeymd_hms_sss(long time) {
return new simpledateformat("yyyy-mm-dd hh:mm:ss:sss").format(time);
}
}- croncontroller:访问接口
import com.example.testspringboot.cron.scheduleresult;
import com.example.testspringboot.cron.schedulejobservice;
import com.example.testspringboot.cron.utils.cronutils;
import com.google.gson.gson;
import org.springframework.beans.factory.annotation.autowired;
import org.springframework.web.bind.annotation.*;
import java.util.list;
@restcontroller
public class croncontroller {
@autowired
private schedulejobservice schedulejobservice;
/**
* 测试上传的用例文件, 获取详细执行结果
*/
@postmapping("/add")
void executetestonefile(@requestbody scheduleresult scheduleresult) {
boolean valid = cronutils.isvalid(scheduleresult.getcronexpression());
if (valid){
system.out.println("校验成功, 添加任务");
scheduleresult.setmethodparams(scheduleresult.getbranch()+scheduleresult.getcasedir());
schedulejobservice.addschedulejob(scheduleresult);
}else {
system.out.println("校验失败");
}
}
@postmapping("/stop")
void end(@requestbody scheduleresult scheduleresult) {
gson gson = new gson();
system.out.println("================");
system.out.println(scheduleresult);
system.out.println("=================");
scheduleresult.setjobstatus(0);
schedulejobservice.startorstopscheduler(scheduleresult);
}
@postmapping("/start")
void start(@requestbody scheduleresult scheduleresult) {
system.out.println("================");
system.out.println(scheduleresult);
system.out.println("=================");
scheduleresult.setjobstatus(1);
schedulejobservice.startorstopscheduler(scheduleresult);
}
@postmapping("/edit")
void edit(@requestbody scheduleresult scheduleresult) {
system.out.println("=======edit=========");
system.out.println(scheduleresult);
system.out.println("=================");
schedulejobservice.editschedulejob(scheduleresult);
}
@postmapping("/delete")
void delete(@requestbody scheduleresult scheduleresult) {
system.out.println("=======delete=========");
system.out.println(scheduleresult);
system.out.println("=================");
schedulejobservice.deleteschedulejob(scheduleresult);
}
@getmapping("/tasks")
list<scheduleresult> get() throws exception {
list<scheduleresult> alltask = schedulejobservice.findalltask();
system.out.println("现在的定时任务数量 = " + alltask.size());
system.out.println("现在的定时任务 = " + alltask);
return alltask;
}
}- 测试bean
import org.springframework.stereotype.component;
@component
public class c1 {
public void test1(string y){
system.out.println("这个是test1的bean : " + y);
}
public void test2(){
system.out.println("这个是test1的bean中test2方法");
}
}- 项目启动后的定时任务
import com.example.testspringboot.cron.schedulejobservice;
import com.example.testspringboot.cron.scheduleresult;
import org.springframework.beans.factory.annotation.autowired;
import org.springframework.boot.commandlinerunner;
import org.springframework.stereotype.component;
@component
public class init implements commandlinerunner {
@autowired
private schedulejobservice schedulejobservice;
@override
public void run(string... args) throws exception {
system.out.println("开始珍惜");
scheduleresult scheduleresult = new scheduleresult();
scheduleresult.setbeanname("c1");
scheduleresult.setmethodname("test1");
scheduleresult.setcronexpression("0/25 * * * * *");
scheduleresult.setjobstatus(1);
scheduleresult.setmethodparams("test1");
schedulejobservice.addschedulejob(scheduleresult);
schedulejobservice.findalltask();
}
}四、使用 quartz 实现定时任务
quartz 是一个功能强大的开源任务调度框架,支持复杂的任务调度需求,如任务的持久化、分布式任务管理、基于数据库的调度等。spring boot 提供了对 quartz 的良好集成,使得在应用中使用 quartz 变得更加简单。
简单使用:
import org.quartz.*;
import org.springframework.context.annotation.bean;
import org.springframework.context.annotation.configuration;
import org.springframework.scheduling.quartz.jobdetailfactorybean;
import org.springframework.scheduling.quartz.simpletriggerfactorybean;
@configuration
public class quartzconfig {
@bean
public jobdetailfactorybean jobdetail() {
jobdetailfactorybean factorybean = new jobdetailfactorybean();
factorybean.setjobclass(samplejob.class);
factorybean.setdescription("sample quartz job");
factorybean.setdurability(true);
return factorybean;
}
@bean
public simpletriggerfactorybean trigger(jobdetail jobdetail) {
simpletriggerfactorybean factorybean = new simpletriggerfactorybean();
factorybean.setjobdetail(jobdetail);
factorybean.setrepeatinterval(5000); // 每5秒执行一次
factorybean.setrepeatcount(simpletrigger.repeat_indefinitely);
return factorybean;
}
public static class samplejob implements job {
@override
public void execute(jobexecutioncontext context) {
system.out.println("quartz任务执行:" + system.currenttimemillis());
}
}
}springboot整合
- 数据库设计
将任务计划放入数据库中保存。在启动任务是,从数据库中查找任务计划信息,并动态配置进去即可。
drop table if exists `cc_task_info`; create table `cc_task_info` ( `tid` int(11) not null auto_increment, `task_anme` varchar(50) not null, `task_code` varchar(50) not null, `job_class` varchar(200) not null, `job_group` varchar(50) not null, `cron` varchar(50) not null, `del_status` varchar(2) default '1' null, `crt_time` datetime default null, primary key (`tid`) ) engine=innodb auto_increment=1 default charset=utf8 comment='定时任务管理表'; drop table if exists `cc_task_record`; create table `cc_task_record` ( `rid` int(11) not null auto_increment, `task_code` varchar(50) not null, `run_time` datetime not null, `run_code` char(1) not null, `run_msg` varchar(100) null, primary key (`rid`) ) engine=innodb auto_increment=1 default charset=utf8 comment='定时任务运行记录表'; drop table if exists `cc_task_status`; create table `cc_task_status` ( `task_code` varchar(50) not null, `task_status` varchar(10) not null, `lst_succ_time` datetime not null, `lst_time` datetime not null, primary key (`task_code`) ) engine=innodb auto_increment=1 default charset=utf8 comment='定时任务运行状态表';
- 定时任务管理
通过scheduler的方法来实现。scheduler提供了一系列方法来管理定时任务的执行状态。
主要包括:
- schedulejob():添加定时任务
- reschedulejob():修改定时任务
- pausejob():暂停定时任务执行
- resumejob():恢复定时任务执行
- deletejob():删除定时任务执行
针对上述方法,只需要传入对应参数即可。建了一个quartzservice来管理定时任务,供业务层调用。
详细代码如下:
/**
* 定时任务管理服务
*/
@service
public class quartzservice {
public static string scheduler_opr_start = "start";
public static string scheduler_opr_pause = "pause";
public static string scheduler_opr_resume = "resume";
public static string scheduler_opr_remove = "remove";
@autowired
private scheduler scheduler;
/**
* 启动任务
*/
public void startjob(string taskcode, string taskanme, string cron, string jobgroup,
string classname) throws exception{
class<job> jobclass = null;
try {
jobclass = (class<job>) class.forname(classname);//获取任务执行类
} catch (classnotfoundexception e) {
throw new exception("任务类不存在");
}
//创建job,指定job名称和分组
jobdetail jobdetail = jobbuilder.newjob(jobclass).withidentity(taskcode, jobgroup).build();
//创建表达式工作计划
cronschedulebuilder cronschedulebuilder = cronschedulebuilder.cronschedule(cron);
//创建触发器
crontrigger crontrigger = triggerbuilder.newtrigger().withidentity(taskcode, jobgroup)
.withschedule(cronschedulebuilder).build();
scheduler.schedulejob(jobdetail, crontrigger);
}
/**
* 修改定时任务执行时间
* @param taskcode
* @param jobgroup
* @param cron 新的时间
* @throws exception
*/
public void modifyjob(string taskcode, string jobgroup, string cron) throws exception{
triggerkey triggerkey = new triggerkey(taskcode, jobgroup);
crontrigger trigger = (crontrigger) scheduler.gettrigger(triggerkey);
string oldcron = trigger.getcronexpression();
if(!oldcron.equals(cron)){
crontrigger crontrigger = triggerbuilder.newtrigger().withidentity(taskcode, jobgroup)
.withschedule(cronschedulebuilder.cronschedule(cron)).build();
date date = scheduler.reschedulejob(triggerkey, crontrigger);
if(date == null){
throw new exception("修改定时任务执行时间报错");
}
}
}
/**
* 暂停某个定时任务(任务恢复后,暂停时间段内未执行的任务会继续执行,如暂停时间段内有2次,则会执行2次)
* @param taskcode
* @param jobgroup
* @throws exception
*/
public void pausejob(string taskcode, string jobgroup) throws exception{
jobkey jobkey = new jobkey(taskcode, jobgroup);
jobdetail jobdetail = scheduler.getjobdetail(jobkey);
if(jobdetail == null){
return;
}
scheduler.pausejob(jobkey);
}
/**
* 恢复某个定时任务
* @param taskcode
* @param jobgroup
* @throws exception
*/
public void resumejob(string taskcode, string jobgroup) throws exception{
jobkey jobkey = new jobkey(taskcode, jobgroup);
jobdetail jobdetail = scheduler.getjobdetail(jobkey);
if(jobdetail == null){
return;
}
scheduler.resumejob(jobkey);
}
/**
* 删除某个定时任务
* @param taskcode
* @param jobgroup
* @throws exception
*/
public void deletejob(string taskcode, string jobgroup) throws exception{
jobkey jobkey = new jobkey(taskcode, jobgroup);
jobdetail jobdetail = scheduler.getjobdetail(jobkey);
if(jobdetail == null){
return;
}
scheduler.deletejob(jobkey);
}
}- 编写任务类job
任务类job就是定时任务具体要处理的系统业务逻辑,需要实现job接口。
在任务启动时,通过jobclass传入jobdetail。
public class demojob implements job {
@override
public void execute(jobexecutioncontext jobexecutioncontext) throws jobexecutionexception {
string taskcode = jobexecutioncontext.getjobdetail().getkey().getname();
system.out.println("执行定时任务:" + taskcode);
}
}- 配置scheduler
在configuration中配置scheduler实例,并启动。
@configuration
public class quartzconfig {
@bean
public scheduler scheduler(){
scheduler scheduler = null;
schedulerfactory factory = new stdschedulerfactory();
try {
scheduler = factory.getscheduler();
} catch (schedulerexception e) {
e.printstacktrace();
}
if(scheduler != null){
try {
//启动定时任务
scheduler.start();
} catch (schedulerexception e) {
e.printstacktrace();
}
}
return scheduler;
}
}- 编写api接口
通过controller提供api接口,这里的taskservice调用了qartzservice的对应接口,并做了一个写数据库读写操作,主要记录定时任务状态、执行记录信息的等。
@restcontroller
@requestmapping("/api/task")
public class taskcontroller {
@autowired
private taskservice service;
@requestmapping("/start")
public object start(int id){
try {
service.startjob(id);
return rtndata.ok();
} catch (exception e) {
return rtndata.fail(e.getmessage());
}
}
@requestmapping("/pause")
public object pause(int id){
try {
service.pausejob(id);
return rtndata.ok();
} catch (exception e) {
return rtndata.fail(e.getmessage());
}
}
@requestmapping("/resume")
public object resume(int id){
try {
service.resumejob(id);
return rtndata.ok();
} catch (exception e) {
return rtndata.fail(e.getmessage());
}
}
@requestmapping("/remove")
public object remove(int id){
try {
service.deletejob(id);
return rtndata.ok();
} catch (exception e) {
return rtndata.fail(e.getmessage());
}
}
}以上就是springboot创建动态定时任务的几种方式小结的详细内容,更多关于springboot动态定时任务的资料请关注代码网其它相关文章!
发表评论