在Java中定时任务是很常见的,使用@Scheduled注解即可实现定时,但是在生产环境中可能会遇到页面上自主配置定时任务的定时时间,这种情况下单独用@Scheduled注解很难实现定时任务,所以我们可以将定时任务存储在数据库中并通过quartz实现动态定时任务。
- <dependency>
- <groupId>org.quartz-scheduler</groupId>
- <artifactId>quartz</artifactId>
- <version>2.2.1</version>
- </dependency>
- <dependency>
- <groupId>org.quartz-scheduler</groupId>
- <artifactId>quartz-jobs</artifactId>
- <version>2.2.1</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-context</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-context-support</artifactId>
- </dependency>
- @Data
- @TableName("SCHEDULE_JOB")
- public class ScheduleJob {
-
- /**
- * 序号
- */
- @TableId(value = "ID", type = IdType.ID_WORKER_STR)
- private String id;
-
- /**
- * 任务名称
- */
- @TableField("JOB_NAME")
- private String jobName;
-
- /**
- * 任务分组
- */
- @TableField("JOB_GROUP")
- private String jobGroup;
-
- /**
- * 任务状态 是否启动任务,2:失效;1:有效
- */
- @TableField("JOB_STATUS")
- private Integer jobStatus;
-
- /**
- * cron表达式,推荐使用6域的
- */
- @TableField("CRON_EXPRESSION")
- private String cronExpression;
-
- /**
- * 描述
- */
- @TableField("DESCRIPTION")
- private String description;
-
- /**
- * 任务执行时调用哪个类的方法 包名+类名,全路径
- */
- @TableField("BEAN_CLASS")
- private String beanClass;
-
- /**
- * 任务是否有状态
- */
- @TableField("IS_CONCURRENT")
- private Integer isConcurrent;
-
- /**
- * spring bean 对应定时任务的类名,首字母小写
- */
- @TableField("SPRING_ID")
- private String springId;
-
- /**
- * 任务调用的方法名
- */
- @TableField("method_name")
- private String methodName;
-
- @TableField("CREATE_TIME")
- private Date createTime;
-
- @TableField("UPDATE_TIME")
- private Date updateTime;
- }
- import com.saas.reptile.common.result.Result;
- import com.saas.reptile.entity.po.ScheduleJob;
- import com.saas.reptile.utils.LogUtils;
- import com.saas.reptile.utils.SpringUtils;
- import com.saas.reptile.utils.StringUtils;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.context.ApplicationContext;
-
- import java.lang.reflect.Method;
-
- public class TaskUtils {
-
- @Autowired
- private ApplicationContext applicationContext;
- /**
- * 通过反射调用scheduleJob中定义的方法
- *
- * @param scheduleJob
- */
- public static void invokMethod(ScheduleJob scheduleJob) {
-
- try {//添加最大的异常捕获
- String springId = scheduleJob.getSpringId();
- Object object = null;
- Class clazz = null;
-
- //根据反射来进行
- if (StringUtils.isNotBlank(springId)) {
- object = SpringUtils.getBean(springId);
- }
-
- if (object == null && StringUtils.isNotBlank(scheduleJob.getBeanClass())) {
- String jobStr = "定时任务名称 = [" + scheduleJob.getJobName() + "]-在spring 中没有这个 springId, 通过 class type 获取中...";
- LogUtils.info(jobStr, scheduleJob.getBeanClass());
- try {
- clazz = Class.forName(scheduleJob.getBeanClass());
- object = SpringUtils.getBean(clazz);
- if(object == null){
- jobStr = "定时任务名称 = [" + scheduleJob.getJobName() + "]-在spring 中没有获得 bean, 调用 spring 方法再次构建中...";
- LogUtils.info(jobStr, scheduleJob.getBeanClass());
- object = SpringUtils.getBeanByType(clazz);
- }
- if (StringUtils.isNotBlank(springId)) {
- SpringUtils.setBean(springId, object);
- LogUtils.info("spring bean 构建完成并加入到容器中 ", scheduleJob.getBeanClass());
- }
- LogUtils.info("定时任务 spring bean 构建成功! ", scheduleJob.getBeanClass());
- } catch (Exception e) {
- LogUtils.error("定时任务 spring bean 构建失败了!!! ", scheduleJob.getBeanClass(), e);
- Result.fail(e);
- return;
- }
- }
-
- clazz = object.getClass();
- Method method = null;
- try {
- method = clazz.getDeclaredMethod(scheduleJob.getMethodName());
- } catch (NoSuchMethodException e) {
- String jobStr = "定时任务名称 = [" + scheduleJob.getJobName() + "] = 未启动成功,方法名设置错误!!!";
- LogUtils.error(jobStr, e);
- } catch (SecurityException e) {
- LogUtils.error("TaskUtils发生异常", e);
- Result.fail(e);
- }
- if (method != null) {
- try {
- method.invoke(object);
- LogUtils.info("定时任务名称 = [" + scheduleJob.getJobName() + "] = 启动成功");
- } catch (Exception e) {
- Result.fail(e);
- LogUtils.error("定时任务名称 = [" + scheduleJob.getJobName() + "] = 启动失败了!!!", e);
- return;
- }
- } else {
- String jobStr = "定时任务名称 = [" + scheduleJob.getJobName() + "] = 启动失败了!!!";
- LogUtils.error(jobStr, clazz.getName(), "not find method ");
- }
-
- } catch (Exception e) {//添加最大的异常捕获
- Result.fail(e);
- LogUtils.error("定时任务名称 = [" + scheduleJob.getJobName() + "] = 启动失败了!!!", e);
- }
-
- }
- }
- import com.saas.reptile.entity.po.ScheduleJob;
- import org.quartz.Job;
- import org.quartz.JobExecutionContext;
- import org.quartz.JobExecutionException;
-
- public class QuartzJobFactory implements Job {
-
- @Override
- public void execute(JobExecutionContext context) throws JobExecutionException {
- ScheduleJob scheduleJob = (ScheduleJob) context.getMergedJobDataMap().get("scheduleJob");
- TaskUtils.invokMethod(scheduleJob);
- }
- }
- import com.saas.reptile.entity.po.ScheduleJob;
- import org.quartz.DisallowConcurrentExecution;
- import org.quartz.Job;
- import org.quartz.JobExecutionContext;
- import org.quartz.JobExecutionException;
-
- @DisallowConcurrentExecution
- public class QuartzJobFactoryDisallowConcurrentExecution implements Job {
-
- @Override
- public void execute(JobExecutionContext context) throws JobExecutionException {
- ScheduleJob scheduleJob = (ScheduleJob) context.getMergedJobDataMap().get("scheduleJob");
- TaskUtils.invokMethod(scheduleJob);
- }
- }
- @Component
- public class ClassAtmosphereTask {
-
- public void work(){
- // do something
- }
-
- }
- import org.springframework.beans.BeansException;
- import org.springframework.beans.factory.NoSuchBeanDefinitionException;
- import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
- import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
- import org.springframework.stereotype.Component;
-
- @Component
- public class SpringUtils implements BeanFactoryPostProcessor {
-
- // Spring应用上下文环境
- private static ConfigurableListableBeanFactory beanFactory;
-
- @Override
- public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
- SpringUtils.beanFactory = beanFactory;
- }
-
- /**
- * 获取对象
- *
- * @param name
- * @return Object 一个以所给名字注册的bean的实例
- * @throws BeansException
- */
- @SuppressWarnings("unchecked")
- public static <T> T getBean(String name) throws BeansException {
- return (T) beanFactory.getBean(name);
- }
-
- /**
- * 获取对象
- * @return Object 一个以所给名字注册的bean的实例
- * @throws BeansException
- */
- @SuppressWarnings("unchecked")
- public static <T> T getBeanByType(Class<T> clzee) throws BeansException {
- try {
- return beanFactory.createBean(clzee);
- } catch (NoSuchBeanDefinitionException e) {
- return null;
- }
-
- }
-
- /**
- * 注入一个对象
- * @return Object 一个以所给名字注册的bean的实例
- * @throws BeansException
- */
- @SuppressWarnings("unchecked")
- public static void setBean(String springId, Object obj) throws BeansException {
- beanFactory.registerSingleton(springId, obj);
- }
-
- /**
- * 获取类型为requiredType的对象
- * @return
- * @throws BeansException
- */
- public static <T> T getBean(Class<T> clz) throws BeansException {
- try {
- @SuppressWarnings("unchecked")
- T result = (T) beanFactory.getBean(clz);
- return result;
- } catch (NoSuchBeanDefinitionException e) {
- return null;
- }
- }
-
- /**
- * 如果BeanFactory包含一个与所给名称匹配的bean定义,则返回true
- *
- * @param name
- * @return boolean
- */
- public static boolean containsBean(String name) {
- return beanFactory.containsBean(name);
- }
-
- /**
- * 判断以给定名字注册的bean定义是一个singleton还是一个prototype。
- * 如果与给定名字相应的bean定义没有被找到,将会抛出一个异常(NoSuchBeanDefinitionException)
- *
- * @param name
- * @return boolean
- * @throws NoSuchBeanDefinitionException
- */
- public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException {
- return beanFactory.isSingleton(name);
- }
-
- /**
- * @param name
- * @return Class 注册对象的类型
- * @throws NoSuchBeanDefinitionException
- */
- public static Class<?> getType(String name) throws NoSuchBeanDefinitionException {
- return beanFactory.getType(name);
- }
-
- /**
- * 如果给定的bean名字在bean定义中有别名,则返回这些别名
- *
- * @param name
- * @return
- * @throws NoSuchBeanDefinitionException
- */
- public static String[] getAliases(String name) throws NoSuchBeanDefinitionException {
- return beanFactory.getAliases(name);
- }
- }
- public class StringUtils {
- public final static String REG_DIGIT = "[0-9]*";
- public final static String REG_CHAR = "[a-zA-Z]*";
- public final static String EMPTY = "";
-
- /**
- * 判断是否为空
- */
- public static boolean isEmpty(Object... obj) {
- if(obj == null)
- return true;
- for(Object object : obj) {
- if (object == null)
- return true;
- if (object.toString().trim().length() == 0)
- return true;
- }
-
- return false;
- }
-
- public static boolean isBlankEmpty(Object obj) {
- if (obj == null || "".equals(obj) || "".equals(obj.toString().trim()) || "null".equalsIgnoreCase(obj.toString()))
- return true;
-
- return false;
- }
-
- /**
- * 是否空,或者为空串,或者为"null"
- * @author guoyu
- */
- public static boolean isBlankEmpty(Object... objs) {
- if (objs == null || objs.length == 0)
- return true;
- for (Object obj : objs) {
- if (isBlankEmpty(obj)) {
- return true;
- }
- }
-
- return false;
- }
-
- public static boolean isNotBlank(String pattern) {
- return !isBlankEmpty(pattern);
- }
-
- public static boolean isBlank(String pattern) {
- return isBlankEmpty(pattern);
- }
-
- public static String formatCountNames(String nameList) {
- String[] names = nameList.split(",");
-
- Map<String, Integer> nameCount = new HashMap<String, Integer>();
- for(String name : names) {
- if(StringUtils.isEmpty(name)) continue;
- if(nameCount.containsKey(name)) {
- Integer count = nameCount.get(name) + 1;
- nameCount.put(name, count);
- } else {
- nameCount.put(name, 1);
- }
- }
-
- StringBuilder newNames = new StringBuilder();
- for(String key : nameCount.keySet()) {
- if(StringUtils.isEmpty(key)) continue;
- Integer count = nameCount.get(key);
- String splitChar = newNames.length() > 0 ? "," : "";
- newNames.append(splitChar).append(key).append("x").append(count);
- }
-
- return newNames.toString();
- }
-
-
- public static boolean isDigit(String str){
- return isNumeric(str);
- }
-
- public static boolean isChar(String str){
- return str.matches(REG_CHAR);
- }
-
- public static Boolean isNotEmpty(Object... obj) {
- Boolean r = StringUtils.isEmpty(obj);
- return !r;
- }
-
- public static boolean isNumeric(String str) {
- if(isBlankEmpty(str)) return false;
- for (int i = str.length(); --i >= 0;) {
- if (!Character.isDigit(str.charAt(i))) {
- return false;
- }
- }
-
- return true;
- }
-
- /**
- * string 中的 str 在倒数 num 中的位置
- * @author guoyu
- */
- public static int stringLastlndex(String string, String str, int num) {
- int indexOf = string.lastIndexOf(str);
- if(num > 1){
- return stringLastlndex(string.substring(0, indexOf), str, num - 1);
- } else {
- return indexOf;
- }
- }
-
-
- public static String getValue(Object val) {
- return val == null ? "" : val.toString().replace("\n", "");
- }
-
- public static String getFileName(boolean type, Date startDate, String tableName){
- String dateString = dateFormat(startDate,"yyyyMMdd");
- StringBuffer stringBuffer = new StringBuffer(dateString);
- stringBuffer.append("_");
- stringBuffer.append(tableName);
- stringBuffer.append("_");
- if (type) {
- stringBuffer.append("insert&");
- } else {
- stringBuffer.append("update&");
- }
- return stringBuffer.toString();
- }
-
- public static String getRefundNumber(Integer payRefundNum) {
- if (payRefundNum == null) payRefundNum = 0;
- payRefundNum = payRefundNum + 1;
- String string = String.valueOf(payRefundNum);
- if (string.length() == 1) {
- return "0"+string;
- }
- return string;
-
- }
-
- private static String dateFormat(Date date, String datePattern) {
- if(date == null) return "";
- if(datePattern == null) datePattern = "yyyy-MM-dd";
- SimpleDateFormat df = new SimpleDateFormat(datePattern, Locale.UK);
- return df.format(date);
- }
- }
- import org.apache.commons.logging.LogFactory;
-
-
- public class LogUtils {
- private static final org.apache.commons.logging.Log logger;
- private static final Object lock = new Object();
-
- static {
- synchronized (lock) {
- logger = LogFactory.getLog(LogUtils.class);
- }
- }
-
- public static void info(Object... msgs) {
- StringBuilder stringBuilder = new StringBuilder();
- Throwable e = null;
- for (Object msg : msgs) {
- if (msg != null) {
- if (msg instanceof Throwable) {
- e = (Throwable) msg;
- } else {
- stringBuilder.append(msg).append(" ");
- }
- }
- }
- logger.info(stringBuilder, e);
- }
-
- public static void error(Object... msgs) {
- StringBuilder stringBuilder = new StringBuilder();
- Throwable e = null;
- for (Object msg : msgs) {
- if (msg != null) {
- if (msg instanceof Throwable) {
- e = (Throwable) msg;
- } else {
- stringBuilder.append(msg).append(" ");
- }
- }
- }
- logger.error(stringBuilder, e);
- }
-
- public static void warn(Object... msgs) {
- StringBuilder stringBuilder = new StringBuilder();
- Throwable e = null;
- for (Object msg : msgs) {
- if (msg != null) {
- if (msg instanceof Throwable) {
- e = (Throwable) msg;
- } else {
- stringBuilder.append(msg).append(" ");
- }
- }
- }
- logger.warn(stringBuilder, e);
- }
-
- public static void debug(Object... msgs) {
- StringBuilder stringBuilder = new StringBuilder();
- Throwable e = null;
- for (Object msg : msgs) {
- if (msg != null) {
- if (msg instanceof Throwable) {
- e = (Throwable) msg;
- } else {
- stringBuilder.append(msg).append(" ");
- }
- }
- }
- logger.debug(stringBuilder, e);
- }
- }
- public final class Constant {
-
- private Constant() {
- }
-
- // 定时任务运行状态:运行
- public static final Integer STATUS_RUNNING = 1;
-
- // 定时任务运行状态:停止
- public static final Integer STATUS_NOT_RUNNING = 2;
-
- // 定时任务是否有状态:有(默认为1,弃用)
- public static final Integer CONCURRENT_IS = 1;
-
- // 定时任务是否有状态:无(默认为1,弃用)
- public static final Integer CONCURRENT_NOT = 0;
- }
- @Data
- public class Result<T> {
-
- private Integer code;
-
- private T data;
-
- private String msg;
-
- public Result() {
- super();
- }
-
- public Result(T data) {
- this.data = data;
- }
-
- public static Result success()
- {
- return success("");
- }
-
- public static <T> Result success(T data) {
- Result<T> result = new Result<>(ResultEnum.SUCCESS.getCode(), ResultEnum.SUCCESS.getName());
- result.setData(data);
- return result;
- }
-
- public static <T> Result<T> fail(ResultEnum resultEnum) {
- return createResult(null, resultEnum.getCode(), resultEnum.getName());
- }
-
- public static <T> Result<T> fail(Integer code, String message) {
- return createResult(null, code, message);
- }
-
- public static <T> Result<T> fail(Throwable e) {
- //打印异常栈信息到控制台
- e.printStackTrace();
- return createResult(null, 500, "服务器发生错误");
- }
-
- private static <T> Result<T> createResult(T data, Integer code, String message) {
- Result<T> r = new Result<>();
- r.setCode(code);
- r.setData(data);
- r.setMsg(message);
- return r;
- }
-
- public Result(Integer code, String msg)
- {
- this.code = code;
- this.msg = msg;
- }
- }
其中ResultEnum类如下:
- public enum ResultEnum {
-
- SUCCESS(200,"请求成功"),
- UN_KNOWN_ERROR(-1, "未知错误"),
-
- PARAM_NULL_ERROR(10001,"参数为空"),
-
- PERMISSION_ACCESS_DENIED(50001, "permission access denied");
-
-
- private int code;
- private String name;
-
- private ResultEnum(int code, String name) {
- this.code = code;
- this.name = name;
- }
-
- public int getCode() {
- return this.code;
- }
-
- public String getName() {
- return this.name;
- }
-
- public static ResultEnum getNameByCode(int code) {
- for (ResultEnum resultEnum : ResultEnum.values()) {
- if (code == resultEnum.getCode()) {
- return resultEnum;
- }
- }
- return null;
- }
- }
- SET NAMES utf8mb4;
- SET FOREIGN_KEY_CHECKS = 0;
-
- -- ----------------------------
- -- Table structure for schedule_job
- -- ----------------------------
- DROP TABLE IF EXISTS `schedule_job`;
- CREATE TABLE `schedule_job` (
- `id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '主键',
- `job_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '任务名称',
- `job_group` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '任务分组',
- `job_status` int(0) DEFAULT NULL COMMENT '任务状态 是否启动任务;1:有效;2:失效',
- `cron_expression` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT 'cron表达式,推荐使用6域的',
- `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '定时任务描述',
- `bean_class` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '任务执行时调用哪个类的方法 包名+类名,全路径',
- `is_concurrent` int(0) DEFAULT 1 COMMENT '任务是否有状态;0:没有;1:有',
- `spring_id` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '注册的Bean,所以与类名保持一致,首字母小写',
- `method_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '任务调用的方法名',
- `create_time` datetime(0) DEFAULT NULL COMMENT '创建时间',
- `update_time` datetime(0) DEFAULT NULL COMMENT '更新时间',
- PRIMARY KEY (`id`) USING BTREE
- ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
-
- -- ----------------------------
- -- Records of schedule_job
- -- ----------------------------
- INSERT INTO `schedule_job` VALUES ('1', 'ClassAtmosphereTask', 'ClassAtmosphereTask', 1, '0 30 23 * * ?', '班级氛围值定时任务', 'com.saas.reptile.task.ClassAtmosphereTask', 1, 'classAtmosphereTask', 'work', '2022-06-25 21:38:42', '2022-06-25 21:38:45');
-
- SET FOREIGN_KEY_CHECKS = 1;
注释的很详细,其中:
job_name和job_group保持一致即可;
is_concurrent默认为1;
任务执行的类要全路径等等。
写在service的实现类里
- package com.saas.reptile.service.impl;
-
- import com.baomidou.mybatisplus.service.impl.ServiceImpl;
- import com.saas.reptile.common.quartz.QuartzJobFactory;
- import com.saas.reptile.common.quartz.QuartzJobFactoryDisallowConcurrentExecution;
- import com.saas.reptile.entity.po.ScheduleJob;
- import com.saas.reptile.mapper.ScheduleJobMapper;
- import com.saas.reptile.service.ScheduleJobService;
- import com.saas.reptile.utils.Constant;
- import com.saas.reptile.utils.LogUtils;
- import org.quartz.*;
- import org.quartz.impl.matchers.GroupMatcher;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.stereotype.Service;
- import org.springframework.transaction.annotation.Propagation;
- import org.springframework.transaction.annotation.Transactional;
- import org.springframework.scheduling.quartz.SchedulerFactoryBean;
-
- import javax.annotation.PostConstruct;
- import java.util.ArrayList;
- import java.util.List;
- import java.util.Set;
-
-
- @Service
- public class ScheduleJobServiceImpl extends ServiceImpl<ScheduleJobMapper, ScheduleJob>
- implements ScheduleJobService {
-
- @Autowired
- private SchedulerFactoryBean schedulerFactoryBean;
-
- /**
- * 添加定时任务到数据库
- * @param scheduleJob
- */
- @Override
- @Transactional(propagation = Propagation.REQUIRED)
- public void addTask(ScheduleJob scheduleJob) {
- this.baseMapper.insert(scheduleJob);
- }
-
- /**
- * 改变定时任务状态
- * @param id
- * @param status
- */
- @Override
- @Transactional(propagation = Propagation.REQUIRED)
- public void changeJobStatus(String id, Integer status) throws SchedulerException {
- // EntityWrapper<ScheduleJob> wrapper = new EntityWrapper<>();
- // wrapper.eq("id",id);
- // String setSql = "job_status = " + status;
- // this.baseMapper.updateForSet(setSql, wrapper);
- ScheduleJob job = selectById(id);
- if (status == 1){
- // 启动
- job.setJobStatus(status);
- addJob(job);
- } else if (status == 2) {
- // 停止
- deleteJob(job);
- job.setJobStatus(status);
- }
- // 更新定时任务
- updateById(job);
- }
-
- /**
- * 更新定时任务cron表达式与运行状态
- * @param jobId 定时任务主键ID
- * @param cron 表达式
- * @param status 定时状态
- */
- @Override
- @Transactional(propagation = Propagation.REQUIRED)
- public void updateCronStatus(String jobId, String cron, Integer status) throws SchedulerException {
- ScheduleJob job = selectById(jobId);
- if (status == 1){
- // 启动
- job.setJobStatus(status);
- job.setCronExpression(cron);
- addJob(job);
- } else if (status == 2) {
- // 停止
- deleteJob(job);
- job.setJobStatus(status);
- job.setCronExpression(cron);
- }
- // 更新定时任务
- updateById(job);
- }
-
- /**
- * 添加任务
- *
- * @param job
- * @throws SchedulerException
- */
- @Transactional(propagation = Propagation.REQUIRED)
- public void addJob(ScheduleJob job) throws SchedulerException {
- // 定时任务运行状态为1则进入下一步
- if (job == null || !Constant.STATUS_RUNNING.equals(job.getJobStatus())) {
- return;
- }
- Scheduler scheduler = schedulerFactoryBean.getScheduler();
- LogUtils.info(scheduler + ".......................................................................................add");
- TriggerKey triggerKey = TriggerKey.triggerKey(job.getJobName(), job.getJobGroup());
-
- CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
-
- // 不存在,创建一个
- if (null == trigger) {
- Class clazz = Constant.CONCURRENT_IS.equals(job.getIsConcurrent()) ? QuartzJobFactory.class : QuartzJobFactoryDisallowConcurrentExecution.class;
-
- JobDetail jobDetail = JobBuilder.newJob(clazz).withIdentity(job.getJobName(), job.getJobGroup()).build();
-
- jobDetail.getJobDataMap().put("scheduleJob", job);
-
- CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression());
-
- trigger = TriggerBuilder.newTrigger().withIdentity(job.getJobName(), job.getJobGroup()).withSchedule(scheduleBuilder).build();
-
- scheduler.scheduleJob(jobDetail, trigger);
- } else {
- // Trigger已存在,那么更新相应的定时设置
- CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression());
-
- // 按新的cronExpression表达式重新构建trigger
- trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
-
- // 按新的trigger重新设置job执行
- scheduler.rescheduleJob(triggerKey, trigger);
- }
- }
-
- @PostConstruct
- public void init() throws Exception {
- LogUtils.info("实例化List<ScheduleJob>,从数据库读取....",this);
- // 这里获取任务信息数据
- List<ScheduleJob> jobList = selectList(null);
- for (ScheduleJob job : jobList) {
- addJob(job);
- }
- }
-
- /**
- * 获取所有计划中的任务列表
- *
- * @return
- * @throws SchedulerException
- */
- public List<ScheduleJob> getAllJob() throws SchedulerException {
- Scheduler scheduler = schedulerFactoryBean.getScheduler();
- GroupMatcher<JobKey> matcher = GroupMatcher.anyJobGroup();
- Set<JobKey> jobKeys = scheduler.getJobKeys(matcher);
- List<ScheduleJob> jobList = new ArrayList<ScheduleJob>();
- for (JobKey jobKey : jobKeys) {
- List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);
- for (Trigger trigger : triggers) {
- ScheduleJob job = new ScheduleJob();
- job.setJobName(jobKey.getName());
- job.setJobGroup(jobKey.getGroup());
- job.setDescription("触发器:" + trigger.getKey());
- Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
- job.setJobStatus(Integer.parseInt(triggerState.name()));
- if (trigger instanceof CronTrigger) {
- CronTrigger cronTrigger = (CronTrigger) trigger;
- String cronExpression = cronTrigger.getCronExpression();
- job.setCronExpression(cronExpression);
- }
- jobList.add(job);
- }
- }
- return jobList;
- }
-
- /**
- * 所有正在运行的job
- *
- * @return
- * @throws SchedulerException
- */
- public List<ScheduleJob> getRunningJob() throws SchedulerException {
- Scheduler scheduler = schedulerFactoryBean.getScheduler();
- List<JobExecutionContext> executingJobs = scheduler.getCurrentlyExecutingJobs();
- List<ScheduleJob> jobList = new ArrayList<ScheduleJob>(executingJobs.size());
- for (JobExecutionContext executingJob : executingJobs) {
- ScheduleJob job = new ScheduleJob();
- JobDetail jobDetail = executingJob.getJobDetail();
- JobKey jobKey = jobDetail.getKey();
- Trigger trigger = executingJob.getTrigger();
- job.setJobName(jobKey.getName());
- job.setJobGroup(jobKey.getGroup());
- job.setDescription("触发器:" + trigger.getKey());
- Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
- job.setJobStatus(Integer.parseInt(triggerState.name()));
- if (trigger instanceof CronTrigger) {
- CronTrigger cronTrigger = (CronTrigger) trigger;
- String cronExpression = cronTrigger.getCronExpression();
- job.setCronExpression(cronExpression);
- }
- jobList.add(job);
- }
- return jobList;
- }
-
- /**
- * 暂停一个job
- *
- * @param scheduleJob
- * @throws SchedulerException
- */
- public void pauseJob(ScheduleJob scheduleJob) throws SchedulerException {
- Scheduler scheduler = schedulerFactoryBean.getScheduler();
- JobKey jobKey = JobKey.jobKey(scheduleJob.getJobName(), scheduleJob.getJobGroup());
- scheduler.pauseJob(jobKey);
- }
-
- /**
- * 恢复一个job
- *
- * @param scheduleJob
- * @throws SchedulerException
- */
- public void resumeJob(ScheduleJob scheduleJob) throws SchedulerException {
- Scheduler scheduler = schedulerFactoryBean.getScheduler();
- JobKey jobKey = JobKey.jobKey(scheduleJob.getJobName(), scheduleJob.getJobGroup());
- scheduler.resumeJob(jobKey);
- }
-
- /**
- * 删除一个job
- *
- * @param scheduleJob
- * @throws SchedulerException
- */
- public void deleteJob(ScheduleJob scheduleJob) throws SchedulerException {
- Scheduler scheduler = schedulerFactoryBean.getScheduler();
- JobKey jobKey = JobKey.jobKey(scheduleJob.getJobName(), scheduleJob.getJobGroup());
- scheduler.deleteJob(jobKey);
-
- }
-
- /**
- * 立即执行job
- *
- * @param scheduleJob
- * @throws SchedulerException
- */
- public void runAJobNow(ScheduleJob scheduleJob) throws SchedulerException {
- Scheduler scheduler = schedulerFactoryBean.getScheduler();
- JobKey jobKey = JobKey.jobKey(scheduleJob.getJobName(), scheduleJob.getJobGroup());
- scheduler.triggerJob(jobKey);
- }
-
- /**
- * 更新job时间表达式
- *
- * @param scheduleJob
- * @throws SchedulerException
- */
- public void updateJobCron(ScheduleJob scheduleJob) throws SchedulerException {
- Scheduler scheduler = schedulerFactoryBean.getScheduler();
-
- TriggerKey triggerKey = TriggerKey.triggerKey(scheduleJob.getJobName(), scheduleJob.getJobGroup());
-
- CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
-
- CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleJob.getCronExpression());
-
- trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
-
- scheduler.rescheduleJob(triggerKey, trigger);
- }
- }
1、项目启动后首先运行上述方法里的init()方法,查询数据库表里的所有定时任务;
2、然后到添加job方法【addJob】,将状态为1的定时任务推到Scheduler计划中
3、还提供了获取所有计划中的任务列表、查询正在运行的job、暂停一个job等方法,不过暂时我没有用到。
4、本项目是通过mybatis-plus进行数据库操作,当更新运行状态时,如果状态为1则启动job,如果状态为2则停止job。
5、控制层方法省略,按实际生产环境来。