Spring-Scheduler(定时任务)
1、XML声明task和设置注解(标红段落)
<?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:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:task="http://www.springframework.org/schema/task" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.2.xsd"> <!-- 识别@Scheduled注解 --> <task:annotation-driven/> </beans>
2、创建controller测试
package com.ll.controller; import javax.annotation.Resource; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import com.ll.service.SchedulerJobService; @Controller public class SchedulerController { @Resource(name = "SchedulerJobService") SchedulerJobService schedulerJob; @RequestMapping("scheduler") @ResponseBody public void setSchedulerJob(@RequestParam String cron) { schedulerJob.addTriggerTask("task01", "cron-json", cron); } @RequestMapping("cancelallscheduler") @ResponseBody public void cancelAllSchedulerJob() { schedulerJob.removeTriggerTask("task01"); } }
3、SchedulerJobService.java
package com.ll.service; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ScheduledFuture; import org.springframework.context.annotation.Lazy; import org.springframework.scheduling.SchedulingException; import org.springframework.scheduling.TaskScheduler; 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.Service; import com.ll.utils.BeanUtils; @Service(value = "SchedulerJobService") @Lazy(false) @EnableScheduling public class SchedulerJobService implements SchedulingConfigurer { private final String FIELD_SCHEDULED_FUTURES = "scheduledTasks"; private ScheduledTaskRegistrar taskRegistrar; private Set<ScheduledFuture<?>> scheduledFutures = null; private Map<String, ScheduledFuture<?>> taskFutures = new ConcurrentHashMap<String, ScheduledFuture<?>>(); @Override public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) { this.taskRegistrar = scheduledTaskRegistrar; // taskRegistrar.addTriggerTask(doTask("test"), getTrigger("*/5 * * * * ?")); } /** * 获取ScheduledFutures * * @return */ @SuppressWarnings("all") 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 scheduledTasks field."); } } return scheduledFutures; } /** * 添加定时任务 * * @return */ public void addTriggerTask(String taskId, String jobData, String cron) { if (taskFutures.containsKey(taskId)) { throw new SchedulingException("the taskId[" + taskId + "] was added."); } TaskScheduler scheduler = taskRegistrar.getScheduler(); // cron = "*/5 * * * * ?" ScheduledFuture<?> future = scheduler.schedule(doTask(jobData), getTrigger(cron)); getScheduledFutures().add(future); taskFutures.put(taskId, future); } /** * 是否存在任务 * * @param taskId * @return */ public boolean hasTask(String taskId) { return this.taskFutures.containsKey(taskId); } /** * 任务编号 * * @return */ public Set<String> taskIds() { return taskFutures.keySet(); } /** * 任务调度是否已经初始化完成 * * @return */ public boolean inited() { return this.taskRegistrar != null && this.taskRegistrar.getScheduler() != null; } /** * 删除指定的定时任务 * * @return */ public void removeTriggerTask(String taskId) { ScheduledFuture<?> future = taskFutures.get(taskId); if (future != null) { future.cancel(true); } taskFutures.remove(taskId); getScheduledFutures().remove(future); } /** * 业务执行方法 * * @return */ private Runnable doTask(String jobData) { return new Runnable() { @Override public void run() { SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); System.out.println("-----------------(doTask)---------------"); // 业务逻辑 System.out.println("jobData: " + jobData + ",时间为: " + simpleDateFormat.format(new Date())); } }; } /** * 业务触发器 * * @return */ private Trigger getTrigger(String cron) { return new Trigger() { @Override public Date nextExecutionTime(TriggerContext triggerContext) { // 触发器 CronTrigger trigger = new CronTrigger(cron); return trigger.nextExecutionTime(triggerContext); } }; } }
4.工具类BeanUtils.java
package com.ll.utils; 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, String methodName, Class<?>... paramTypes) { try { return clazz.getDeclaredMethod(methodName, paramTypes); } catch (NoSuchMethodException ex) { if (clazz.getSuperclass() != null) { return findDeclaredMethod(clazz.getSuperclass(), methodName, 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); } }
5、运行
主要写法:
1、实现SchedulingConfigurer接口
2、重写configureTasks方法,本地储存定时器对象, 方便后期维护
@Override public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) { this.taskRegistrar = scheduledTaskRegistrar; }
3、执行定时器
TaskScheduler scheduler = taskRegistrar.getScheduler(); // cron = "*/5 * * * * ?" ScheduledFuture<?> future = scheduler.schedule(doTask(jobData), getTrigger(cron));