Spring内置任务调度如何实现添加、取消与重置详解
|
前言 大家应该都有所体会,使用Spring的任务调度给我们的开发带来了极大的便利,不过当我们的任务调度配置完成后,很难再对其进行更改,除非停止服务器,修改配置,然后再重启,显然这样是不利于线上操作的,为了实现动态的任务调度修改,我在网上也查阅了一些资料,大部分都是基于quartz实现的,使用Spring内置的任务调度则少之又少,而且效果不理想,需要在下次任务执行后,新的配置才能生效,做不到立即生效。本着探索研究的原则,查看了一下Spring的源码,下面为大家提供一种Spring内置任务调度实现添加、取消、重置的方法。话不多说了,来一起看看详细的介绍 吧。 实现方法如下 首先,我们需要启用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:context="http://www.springframework.org/schema/context" xmlns:task="http://www.springframework.org/schema/task" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.2.xsd"> <task:annotation-driven executor="jobExecutor" scheduler="jobScheduler" /> <task:executor id="jobExecutor" pool-size="5"/> <task:scheduler id="jobScheduler" pool-size="10" /> </beans> 这一部分配置在网上是很常见的,接下来我们需要联合使用@EnableScheduling与 查看一下ScheduledTaskRegistrar源码,我们发现该对象初始化完成后会执行
protected void scheduleTasks() {
long now = System.currentTimeMillis();
if (this.taskScheduler == null) {
this.localExecutor = Executors.newSingleThreadScheduledExecutor();
this.taskScheduler = new ConcurrentTaskScheduler(this.localExecutor);
}
if (this.triggerTasks != null) {
for (TriggerTask task : this.triggerTasks) {
this.scheduledFutures.add(this.taskScheduler.schedule(
task.getRunnable(),task.getTrigger()));
}
}
if (this.cronTasks != null) {
for (CronTask task : this.cronTasks) {
this.scheduledFutures.add(this.taskScheduler.schedule(
task.getRunnable(),task.getTrigger()));
}
}
if (this.fixedRateTasks != null) {
for (IntervalTask task : this.fixedRateTasks) {
if (task.getInitialDelay() > 0) {
Date startTime = new Date(now + task.getInitialDelay());
this.scheduledFutures.add(this.taskScheduler.scheduleAtFixedRate(
task.getRunnable(),startTime,task.getInterval()));
}
else {
this.scheduledFutures.add(this.taskScheduler.scheduleAtFixedRate(
task.getRunnable(),task.getInterval()));
}
}
}
if (this.fixedDelayTasks != null) {
for (IntervalTask task : this.fixedDelayTasks) {
if (task.getInitialDelay() > 0) {
Date startTime = new Date(now + task.getInitialDelay());
this.scheduledFutures.add(this.taskScheduler.scheduleWithFixedDelay(
task.getRunnable(),task.getInterval()));
}
else {
this.scheduledFutures.add(this.taskScheduler.scheduleWithFixedDelay(
task.getRunnable(),task.getInterval()));
}
}
}
}
所以我的思路就是动态修改该集合,实现任务调度的添加、取消、重置。实现代码如下:
package com.jianggujin.web.util.job;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledFuture;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.config.TriggerTask;
import com.jianggujin.web.util.BeanUtils;
/**
* 默认任务调度配置
*
* @author jianggujin
*
*/
@EnableScheduling
public class DefaultSchedulingConfigurer implements SchedulingConfigurer
{
private final String FIELD_SCHEDULED_FUTURES = "scheduledFutures";
private ScheduledTaskRegistrar taskRegistrar;
private Set<ScheduledFuture<?>> scheduledFutures = null;
private Map<String,ScheduledFuture<?>> taskFutures = new ConcurrentHashMap<String,ScheduledFuture<?>>();
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar)
{
this.taskRegistrar = taskRegistrar;
}
@SuppressWarnings("unchecked")
private Set<ScheduledFuture<?>> getScheduledFutures()
{
if (scheduledFutures == null)
{
try
{
scheduledFutures = (Set<ScheduledFuture<?>>) BeanUtils.getProperty(taskRegistrar,FIELD_SCHEDULED_FUTURES);
}
catch (NoSuchFieldException e)
{
throw new SchedulingException("not found scheduledFutures field.");
}
}
return scheduledFutures;
}
/**
* 添加任务
*
* @param taskId
* @param triggerTask
*/
public void addTriggerTask(String taskId,TriggerTask triggerTask)
{
if (taskFutures.containsKey(taskId))
{
throw new SchedulingException("the taskId[" + taskId + "] was added.");
}
TaskScheduler scheduler = taskRegistrar.getScheduler();
ScheduledFuture<?> future = scheduler.schedule(triggerTask.getRunnable(),triggerTask.getTrigger());
getScheduledFutures().add(future);
taskFutures.put(taskId,future);
}
/**
* 取消任务
*
* @param taskId
*/
public void cancelTriggerTask(String taskId)
{
ScheduledFuture<?> future = taskFutures.get(taskId);
if (future != null)
{
future.cancel(true);
}
taskFutures.remove(taskId);
getScheduledFutures().remove(future);
}
/**
* 重置任务
*
* @param taskId
* @param triggerTask
*/
public void resetTriggerTask(String taskId,TriggerTask triggerTask)
{
cancelTriggerTask(taskId);
addTriggerTask(taskId,triggerTask);
}
/**
* 任务编号
*
* @return
*/
public Set<String> taskIds()
{
return taskFutures.keySet();
}
/**
* 是否存在任务
*
* @param taskId
* @return
*/
public boolean hasTask(String taskId)
{
return this.taskFutures.containsKey(taskId);
}
/**
* 任务调度是否已经初始化完成
*
* @return
*/
public boolean inited()
{
return this.taskRegistrar != null && this.taskRegistrar.getScheduler() != null;
}
}
其中用到的BeanUtils源码如下:
package com.jianggujin.web.util;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class BeanUtils
{
public static Field findField(Class<?> clazz,String name)
{
try
{
return clazz.getField(name);
}
catch (NoSuchFieldException ex)
{
return findDeclaredField(clazz,name);
}
}
public static Field findDeclaredField(Class<?> clazz,String name)
{
try
{
return clazz.getDeclaredField(name);
}
catch (NoSuchFieldException ex)
{
if (clazz.getSuperclass() != null)
{
return findDeclaredField(clazz.getSuperclass(),name);
}
return null;
}
}
public static Method findMethod(Class<?> clazz,String methodName,Class<?>... paramTypes)
{
try
{
return clazz.getMethod(methodName,paramTypes);
}
catch (NoSuchMethodException ex)
{
return findDeclaredMethod(clazz,methodName,paramTypes);
}
}
public static Method findDeclaredMethod(Class<?> clazz,Class<?>... paramTypes)
{
try
{
return clazz.getDeclaredMethod(methodName,paramTypes);
}
catch (NoSuchMethodException ex)
{
if (clazz.getSuperclass() != null)
{
return findDeclaredMethod(clazz.getSuperclass(),paramTypes);
}
return null;
}
}
public static Object getProperty(Object obj,String name) throws NoSuchFieldException
{
Object value = null;
Field field = findField(obj.getClass(),name);
if (field == null)
{
throw new NoSuchFieldException("no such field [" + name + "]");
}
boolean accessible = field.isAccessible();
field.setAccessible(true);
try
{
value = field.get(obj);
}
catch (Exception e)
{
throw new RuntimeException(e);
}
field.setAccessible(accessible);
return value;
}
public static void setProperty(Object obj,String name,Object value) throws NoSuchFieldException
{
Field field = findField(obj.getClass(),name);
if (field == null)
{
throw new NoSuchFieldException("no such field [" + name + "]");
}
boolean accessible = field.isAccessible();
field.setAccessible(true);
try
{
field.set(obj,value);
}
catch (Exception e)
{
throw new RuntimeException(e);
}
field.setAccessible(accessible);
}
public static Map<String,Object> obj2Map(Object obj,Map<String,Object> map)
{
if (map == null)
{
map = new HashMap<String,Object>();
}
if (obj != null)
{
try
{
Class<?> clazz = obj.getClass();
do
{
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields)
{
int mod = field.getModifiers();
if (Modifier.isStatic(mod))
{
continue;
}
boolean accessible = field.isAccessible();
field.setAccessible(true);
map.put(field.getName(),field.get(obj));
field.setAccessible(accessible);
}
clazz = clazz.getSuperclass();
} while (clazz != null);
}
catch (Exception e)
{
throw new RuntimeException(e);
}
}
return map;
}
/**
* 获得父类集合,包含当前class
*
* @param clazz
* @return
*/
public static List<Class<?>> getSuperclassList(Class<?> clazz)
{
List<Class<?>> clazzes = new ArrayList<Class<?>>(3);
clazzes.add(clazz);
clazz = clazz.getSuperclass();
while (clazz != null)
{
clazzes.add(clazz);
clazz = clazz.getSuperclass();
}
return Collections.unmodifiableList(clazzes);
}
}
因为加载的延迟,在使用这种方法自定义配置任务调度是,首先需要调用 (编辑:安卓应用网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
