1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > 动态修改参数cron的值来实现Spring自带定时器动态的执行任务

动态修改参数cron的值来实现Spring自带定时器动态的执行任务

时间:2022-11-01 15:09:30

相关推荐

动态修改参数cron的值来实现Spring自带定时器动态的执行任务

最近在做一个项目二次开发:安防系统中用到了Spring自带的定时器,本来已经实现了。但是考虑到最终会在多家保安公司上线,所以可能每家公司要求执行的定时器任务的执行周期是不会一样的,起初想着直接同意规定死一个执行周期的,后来为了让系统更加的具有灵活了(当然是项目更有卖点)。一开始想着修改定时任务的执行周期还不简单,把服务停下来,改下任务的cron参数,再重启服务就搞定了。但有没有一种可能,在不停服务的情况下,就可以动态的修改任务的cron参数呢?完全是有可能的!所以就开始研究如何动态修改参数cron的值来实现Spring自带定时器动态的执行任务。

说明:Spring框架自3.0版本起,自带了任务调度功能,好比是一个轻量级的Quartz,而且使用起来也方便、简单,且不需要依赖其他的JAR包。秉承着Spring的一贯风格,Spring任务调度的实现同时支持注解配置和XML配置两种方式(ps我是使用注解)。废话不说,直接上代码

配置文件:spring-timer.xml

小提示:为了防止一些不必要的问题的出现,最好将定时器的配置写在一个单独的配置文件中

<?xml version="1.0" encoding="UTF-8"?><beansxmlns="/schema/beans"xmlns:xsi="/2001/XMLSchema-instance"xmlns:p="/schema/p"xmlns:context="/schema/context"xmlns:aop="/schema/aop"xmlns:task="/schema/task"xsi:schemaLocation="/schema/beans /schema/beans/spring-beans-3.2.xsd/schema/context /schema/context/spring-context-3.2.xsd/schema/aop /schema/aop/spring-aop-3.2.xsd/schema/task /schema/task/spring-task-3.2.xsd"> <context:annotation-config /><!-- 自动调度需要扫描的包 --> <context:component-scan base-package="com.honest.sspc.timer" ></context:component-scan><!-- 定时器开关 --><task:executor id="executor" pool-size="5"/><task:scheduler id="scheduler" pool-size="10"/><task:annotation-driven executor="executor" scheduler="scheduler"/> </beans>

关于<task:executor . . . /><task:scheduler . . . />的说明:

请参考——关于Spring 任务调度之task:scheduler与task:executor配置的详解

注意:配置Spring定时任务时,需要在Spring配置文件的xml头部加入xmlns:task="/schema/task"和xsi:schemaLocation位置中加入/schema/task /schema/task/spring-task.xsd

然后是注解式任务逻辑代码StaticCronTask.java(说明:不能动态设置cron的值)

package com.task.demo;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.context.annotation.Lazy;import org.springframework.scheduling.annotation.Scheduled;import org.ponent;/*** 定时任务 */@Lazy(false)@Componentpublic class StaticCronTask {private static Logger log = Logger.getLogger(StaticCronTask .class);@Scheduled(cron="0/5 * * * * ?")public void staticCronTask() {logger.debug("staticCronTask is running...");}}

上述任务适用于具有固定任务周期的任务,若要修改任务执行周期,只能走“停服务→修改任务执行周期→重启服务”这条路。

下面来看看可以在不停服务的情况下动态修改任务周期的实现:

注解式任务逻辑代码DynamicCronTask .java(说明:可能动态设置cron的值)

package timer;import java.util.Date;import javax.servlet.http.HttpServletRequest;import org.apache.log4j.Logger;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.ponent;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.servlet.ModelAndView;@Lazy(value=false)@Component@EnableScheduling@Controllerpublic class DynamicCronTask implements SchedulingConfigurer {private static Logger log = Logger.getLogger(DynamicCronTask.class);public static String cron = "0/10 * * * * ?";@RequestMapping("/setDynamicCronTask")public String setSpringDynamicCronTask(HttpServletRequest request, String setCron) {System.out.println("cron setDynamicCronTaskto:" + setCron);cron = setCron;System.err.println("cron change to:" + cron);return "";}@Overridepublic void configureTasks(ScheduledTaskRegistrar taskRegister) {taskRegister.addTriggerTask(new Runnable() {@Overridepublic void run() {// 逻辑任务System.out.println("dynamicCronTask is running...");}}, new Trigger() {@Overridepublic Date nextExecutionTime(TriggerContext triggerContext) {// 任务触发,可修改任务的执行周期CronTrigger trigger = new CronTrigger(cron);System.out.println("cron:" + cron);Date nextExecutor = trigger.nextExecutionTime(triggerContext);return nextExecutor;}});}}

用于动态设置cron值的jsp页面:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%><%String path = request.getContextPath();String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/";%><!DOCTYPE html><html><style>body{text-align: center;}</style><body><!-- 主页面 --><div class="content"><form action="setDynamicCronTask" method="post"><label>动态设置cron:</label><input id="shopName" type="text" name="setCron"class="form-control" maxlength="20" /><br><br><input type="submit" value="submit"/></form></div></body><script type="text/javascript"></script></html>

运行起来,查看任务执行情况,可以观察到任务的执行周期由5秒变成了15秒,期间服务并未停止。dynamicCronTask is running...

cron :0/5 * * * * ?

dynamicCronTask is running...

cron :0/5 * * * * ?

cron cron setDynamicCronTaskto: to:0/15 * * * * ?

cron change to:0/15 * * * * ?dynamicCronTask is running...

cron :0/15 * * * * ?

dynamicCronTask is running...

cron :0/15 * * * * ?

源码下载:taskTimer.rar

技术文章链接:/xht555/article/details/53121962

补充说明:

最近在看博客是发现很多人都有这个问题:Spring的定时器任务并没有及时执行,经过研究排查发现spring 定时器任务scheduled-tasks默认配置是单线程串行执行的,这就造成了若某个任务执行时间过长,其他任务一直在排队,业务逻辑没有及时处理的问题。

经过网上查阅这个问题其实还是蛮好解决的(前提是静态的Spring定时器),解决方法如下:

在配置文件中配置一下线程调度池即可:参考链接:/weixin_37848710/article/details/79635021

<task:executor id="executor" pool-size="5"/><!-- 任务执行线程池的初始大小 --><task:scheduler id="scheduler" pool-size="10"/><!-- 任务调度线程池的大小 --><task:annotation-driven executor="executor" scheduler="scheduler"/><!-- 定时器开关 -->

但是比较让人头疼的是如果是动态设置cron的参数值的Spring定时器的话就有问题了。

问题描述:假若初始化设置的cron的执行周期较长,项目启动后并没有立马执行定时器,动态的定时器是一定要等到该初始化时的执行周期第一次执行完后才会对动态设置的新的cron执行周期生效,对此本人研究了几天都没啥结果。但网上有个方法是这样的,在这里提供一下:

原文:

新生成的任务cron规则不能及时生效的问题解决了,这边顺便说下,查阅spring framework 文档任务调度段发现

ScheduledTaskRegistrar对象中setScheduler方法中可以通过返回一个新的newScheduledThreadPool将现有的任务shutdown掉,完美解决新生成的任务cron规则不能及时生效的问题

代码

@Bean(destroyMethod="shutdown")public Executor taskExecutor() {return Executors.newScheduledThreadPool(100);}taskRegistrar.setScheduler(taskExecutor());

但是本人可能由于学疏才浅,试来该方法并没什么用,有兴趣的可以试一试。然后想到既然是因为初始时设置了一个cron的执行周期,不妨将次初始值不设不就不会有这个问题了,想法很好,愉快的试了一番,结果还是白高兴一场,不设初始值的话在项目启动的时候就会报空指针异常,所以果断否定;最后想来想去,我最后用的一种不是方法的方法就是:修改cron的初始值,也就是初始执行周期【private static String cron = "0/5 * * * * ?";】,我设改的是每5秒执行一次,这样那么在项目启动后五秒就已经执行过一次了,然后你在动态的设置cron的值就能立马见效了。具体为什么会是这样有待探究,我想一定有解决的办法,如有大神解决了还望不吝赐教。小弟在此提前拜谢啦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。