Spring Schedule Task动态改写Cron配置方式
spring schedule task动态改写cron配置
使用spring @scheduled标签可以很简单地定义scheduled task,但是有时我们需要在程序里动态地改写cron的配置。
什么时候呢?
额,比如:
老板觉得cron配置太难看了,想直接这样:10:15
scheduling tasks的常规使用
两个标签: @enablescheduling, @scheduled
@springbootapplication @enablescheduling public class schedulingtasksapplication { public static void main(string[] args) { springapplication.run(schedulingtasksapplication.class); } }
public class scheduletasksimplejob { @scheduled(cron = "0 15 10 * * ?") public void schedulecrontask() { long now = system.currenttimemillis() / 1000; system.out.println( "schedule tasks using cron jobs - " + now); } }
动态改写cron
implements schedulingconfigurer就可以,想怎么改怎么改。 public class scheduletasksimplejob implements schedulingconfigurer { public void schedulecrontask() { long now = system.currenttimemillis() / 1000; system.out.println( "schedule tasks using cron jobs - " + now); } @override public void configuretasks(scheduledtaskregistrar taskregistrar) { taskregistrar.addtriggertask(new runnable() { @override public void run() { schedulecrontask(); } }, new trigger() { @override public date nextexecutiontime(triggercontext triggercontext) { //todo 将时间配置10:15转换为cron string cron = "0 15 10 * * ?"; crontrigger trigger = new crontrigger(cron); date nextexecdate = trigger.nextexecutiontime(triggercontext); return nextexecdate; } }); } }
@scheduled定时任务动态修改cron参数
spring框架自3.0版本起,自带了任务调度功能,好比是一个轻量级的quartz,而且使用起来也方便、简单,且不需要依赖其他的jar包。秉承着spring的一贯风格,spring任务调度的实现同时支持注解配置和xml配置两种方式。
再来谈谈变态的项目需求:我们正在做一个智能数字电表的数据采集项目,项目最终会在多个工业园上线,每个工业园对电表数据的采集周期可以进行自定义,例如a工业园想每10分钟采集一次数据,b工业园想每15分钟采集一次数据。因为数据采集是个重复的周期性工作,那么就可以考虑使用spring框架的定时任务功能了。
按正常来讲,修改定时任务的执行周期还不简单,把服务停下来,改下任务的cron参数,再重启服务就搞定了。但有没有一种可能,在不停服务的情况下,就可以动态的修改任务的cron参数呢?完全是有可能的!
先来看下spring常规定时任务的配置
如下
<?xml version="1.0" encoding="utf-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xmlns:task="http://www.springframework.org/schema/task" xmlns:context="http://www.springframework.org/schema/context" xsi:schemalocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd "> <context:component-scan base-package="com.pes_soft.task.demo" /> <!-- spring注解方式配置调度任务 --> <task:executor id="executor" pool-size="3"/> <task:scheduler id="scheduler" pool-size="3"/> <task:annotation-driven executor="executor" scheduler="scheduler"/> </beans>
注意:配置spring定时任务时,需要在spring配置文件的xml头部加入
xmlns:task="http://www.springframework.org/schema/task"和xsi:schemalocation位置中加入
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd
然后是注解式任务逻辑代码springstaticcrontask.java
package com.pes_soft.task.demo; import org.slf4j.logger; import org.slf4j.loggerfactory; import org.springframework.context.annotation.lazy; import org.springframework.scheduling.annotation.scheduled; import org.springframework.stereotype.component; @lazy(false) @component public class springstaticcrontask { private static final logger logger = loggerfactory.getlogger(springstaticcrontask.class); @scheduled(cron="0/5 * * * * ?") public void staticcrontask() { logger.debug("staticcrontask is running..."); } }
上述任务适用于具有固定任务周期的任务,若要修改任务执行周期,只能走“停服务→修改任务执行周期→重启服务”这条路。
下面来看看可以在不停服务的情况下动态修改任务周期的实现
步骤如下:
在定时任务类上增加@enablescheduling注解,并实现schedulingconfigurer接口。(值得注意的是:@enablescheduling对spring的版本要求比较高,一开始使用的3.2.6版本时一直未成功,后来改成4.2.5版本就可以了)
设置一个静态变量cron,用于存放任务执行周期参数。
另辟一线程,用于模拟实际业务中外部原因修改了任务执行周期。
设置任务触发器,触发任务执行,其中就可以修改任务的执行周期。
完整的springdynamiccrontask.java代码如下:
package com.pes_soft.task.demo; import java.util.date; import org.slf4j.logger; import org.slf4j.loggerfactory; import org.springframework.context.annotation.lazy; 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.stereotype.component; @lazy(false) @component @enablescheduling public class springdynamiccrontask implements schedulingconfigurer { private static final logger logger = loggerfactory.getlogger(springdynamiccrontask.class); private static string cron; public springdynamiccrontask() { cron = "0/5 * * * * ?"; // 开启新线程模拟外部更改了任务执行周期 new thread(new runnable() { @override public void run() { try { thread.sleep(15 * 1000); } catch (interruptedexception e) { e.printstacktrace(); } cron = "0/10 * * * * ?"; system.err.println("cron change to: " + cron); } }).start(); } @override public void configuretasks(scheduledtaskregistrar taskregistrar) { taskregistrar.addtriggertask(new runnable() { @override public void run() { // 任务逻辑 logger.debug("dynamiccrontask is running..."); } }, new trigger() { @override public date nextexecutiontime(triggercontext triggercontext) { // 任务触发,可修改任务的执行周期 crontrigger trigger = new crontrigger(cron); date nextexec = trigger.nextexecutiontime(triggercontext); return nextexec; } }); } }
将demo运行起来,查看任务执行情况,可以观察到任务的执行周期由5秒变成了10秒,期间服务并未停止。
以上为个人经验,希望能给大家一个参考,也希望大家多多支持。
上一篇: 麦子金服A轮融资