一、使用 @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* @return */ public static t getbean(class type) { return context.getbean(type); } public static t getbean(string name,class clazz){ return context.getbean(name, clazz); } public static object getbean(string name){ return context.getbean(name); } /** * springboot动态注册bean * @param clazz * @param * @return */ public static t register(class 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 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 maptasks = 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 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 jobs = tasks.keyset(); if(jobs.size() == 0) { return null; } iterator 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 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 mapscheduledtasks = new concurrenthashmap<>(16); private final map 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 getscheduledtasks() { return scheduledtasks; } public map 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 findalltask() { list scheduleresults = new arraylist<>(); set > entries = schedulerjob.entryset(); for (map.entry 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 statict getbean(class clazz) { return getapplicationcontext().getbean(clazz); } // 通过name,以及clazz返回指定的bean public static t getbean(string name, class 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 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 listfindalltask() { 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") listget() throws exception { list 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{ classjobclass = null; try { jobclass = (class ) 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动态定时任务的资料请关注其它相关文章!