项目中需要用到定时任务,考虑了下java方面定时任务无非就三种:

  1. 用Java自带的timer类。稍微看了一下,可以实现大部分的指定频率的任务的调度(timer.schedule()),也可以实现关闭和开启(timer.cancle)。但是用其来实现某天的某个时间或者某月的某一天调度任务有点不方便。
  2. 采用Quartz 调度器实现。这是一个功能很强大的开源的专门用于定时任务调度的框架,也很好的和springboot整合,缺点:配置复杂,需要花费一定的时间去了解和研究。
  3. spring3.0以后自带的scheduletask任务调度,可以实现quartz的大部分功能,不需要额外引用jar,也不需要另外配置。而且支持注解和配置文件两种。

  鉴于项目有些地方要考虑动态管理定时任务的,所以考虑吧quartz也集成进去,方便调用。

  一、首先引入依赖(必需)

 <!--任务调度相关依赖-->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.2.3</version>
</dependency>
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz-jobs</artifactId>
<version>2.2.3</version>
</dependency>    

二、创建job 实例工厂,解决spring注入问题,如果使用默认会导致spring的@Autowired 无法注入问题

 package com.qunyi.jifenzhi_zx.core.quartz.taskjobfactory;

 import org.quartz.spi.TriggerFiredBundle;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.scheduling.quartz.AdaptableJobFactory;
import org.springframework.stereotype.Component; /**
* @author xujingyang
* @Description: 解决quartz无法注入spring bean问题
* @date 2018/5/30.
*/
@Component
public class TaskJobFactory extends AdaptableJobFactory {
@Autowired
private AutowireCapableBeanFactory capableBeanFactory; @Override
protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
//调用父类的方法
Object jobInstance = super.createJobInstance(bundle);
//进行注入
capableBeanFactory.autowireBean(jobInstance);
return jobInstance;
}
}

TaskJobFactory

三、创建job管理类,对job进行增加,暂停,恢复,更新,删除等操作

import com.qunyi.jifenzhi_zx.common.core.quartz.BaseTaskJob;
import org.quartz.*;
import org.quartz.impl.matchers.GroupMatcher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import java.util.*; /**
* @author xujingyang
* @Description: task任务创建工具类
* @date 2018/5/30.
*/
@Component
public class QuartzJobManager {
private static final Logger logger = LoggerFactory.getLogger(QuartzJobManager.class); private static QuartzJobManager jobUtil; @Autowired
private Scheduler scheduler; public QuartzJobManager() {
logger.info("init jobUtil");
jobUtil = this;
} public static QuartzJobManager getInstance() {
logger.info("retun JobCreateUtil");
return QuartzJobManager.jobUtil;
} /**
* 创建job
*
* @param clazz 任务类
* @param jobName 任务名称
* @param jobGroupName 任务所在组名称
* @param cronExpression cron表达式
* @throws Exception
* @author xujingyang
* @date 2018/5/30.
*/
public void addJob(Class clazz, String jobName, String jobGroupName, String cronExpression) throws Exception { // 启动调度器
scheduler.start(); //构建job信息
JobDetail jobDetail = JobBuilder.newJob(((BaseTaskJob) clazz.newInstance()).getClass()).withIdentity(jobName, jobGroupName).build(); //表达式调度构建器(即任务执行的时间)
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression); //按新的cronExpression表达式构建一个新的trigger
CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(jobName, jobGroupName)
.withSchedule(scheduleBuilder).build();
scheduler.scheduleJob(jobDetail, trigger);
} /**
* 创建job,可传参
*
* @param clazz 任务类
* @param jobName 任务名称
* @param jobGroupName 任务所在组名称
* @param cronExpression cron表达式
* @param argMap map形式参数
* @throws Exception
* @author xujingyang
* @date 2018/5/30.
*/
public void addJob(Class clazz, String jobName, String jobGroupName, String cronExpression, Map<String, Object> argMap) throws Exception { // 启动调度器
scheduler.start(); //构建job信息
JobDetail jobDetail = JobBuilder.newJob(((BaseTaskJob) clazz.newInstance()).getClass()).withIdentity(jobName, jobGroupName).build(); //表达式调度构建器(即任务执行的时间)
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression); //按新的cronExpression表达式构建一个新的trigger
CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(jobName, jobGroupName)
.withSchedule(scheduleBuilder).build(); //获得JobDataMap,写入数据
trigger.getJobDataMap().putAll(argMap); scheduler.scheduleJob(jobDetail, trigger);
} /**
* 暂停job
*
* @param jobName 任务名称
* @param jobGroupName 任务所在组名称
* @throws SchedulerException
* @author xujingyang
* @date 2018/5/30.
*/
public void pauseJob(String jobName, String jobGroupName) throws SchedulerException {
scheduler.pauseJob(JobKey.jobKey(jobName, jobGroupName));
} /**
* 恢复job
*
* @param jobName 任务名称
* @param jobGroupName 任务所在组名称
* @throws SchedulerException
* @author xujingyang
* @date 2018/5/30.
*/
public void resumeJob(String jobName, String jobGroupName) throws SchedulerException { scheduler.resumeJob(JobKey.jobKey(jobName, jobGroupName));
} /**
* job 更新,只更新频率
*
* @param jobName 任务名称
* @param jobGroupName 任务所在组名称
* @param cronExpression cron表达式
* @throws Exception
* @author xujingyang
* @date 2018/5/30.
*/
public void updateJob(String jobName, String jobGroupName, String cronExpression) throws Exception {
TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroupName);
// 表达式调度构建器
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression); CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey); // 按新的cronExpression表达式重新构建trigger
trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build(); // 按新的trigger重新设置job执行
scheduler.rescheduleJob(triggerKey, trigger); } /**
* job 更新,更新频率和参数
*
* @param jobName 任务名称
* @param jobGroupName 任务所在组名称
* @param cronExpression cron表达式
* @param argMap 参数
* @throws Exception
* @author xujingyang
* @date 2018/5/30.
*/
public void updateJob(String jobName, String jobGroupName, String cronExpression, Map<String, Object> argMap) throws Exception {
TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroupName);
// 表达式调度构建器
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression); CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey); // 按新的cronExpression表达式重新构建trigger
trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build(); //修改map
trigger.getJobDataMap().putAll(argMap); // 按新的trigger重新设置job执行
scheduler.rescheduleJob(triggerKey, trigger); } /**
* job 更新,只更新更新参数
*
* @param jobName 任务名称
* @param jobGroupName 任务所在组名称
* @param argMap 参数
* @throws Exception
* @author xujingyang
* @date 2018/5/30.
*/
public void updateJob(String jobName, String jobGroupName, Map<String, Object> argMap) throws Exception {
TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroupName); CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey); //修改map
trigger.getJobDataMap().putAll(argMap); // 按新的trigger重新设置job执行
scheduler.rescheduleJob(triggerKey, trigger); } /**
* job 删除
*
* @param jobName 任务名称
* @param jobGroupName 任务所在组名称
* @throws Exception
* @author xujingyang
* @date 2018/5/30.
*/
public void deleteJob(String jobName, String jobGroupName) throws Exception {
scheduler.pauseTrigger(TriggerKey.triggerKey(jobName, jobGroupName));
scheduler.unscheduleJob(TriggerKey.triggerKey(jobName, jobGroupName));
scheduler.deleteJob(JobKey.jobKey(jobName, jobGroupName));
} /**
* 启动所有定时任务
*
* @author xujingyang
* @date 2018/5/30.
*/
public void startAllJobs() {
try {
scheduler.start();
} catch (Exception e) {
throw new RuntimeException(e);
}
} /**
* 关闭所有定时任务
*
* @author xujingyang
* @date 2018/5/30.
*/
public void shutdownAllJobs() {
try {
if (!scheduler.isShutdown()) {
scheduler.shutdown();
}
} catch (Exception e) {
throw new RuntimeException(e);
} } /**
* 获取所有任务列表
*
* @return
* @throws SchedulerException
*/
public List<Map<String, Object>> getAllJob() throws SchedulerException {
GroupMatcher<JobKey> matcher = GroupMatcher.anyJobGroup();
Set<JobKey> jobKeys = scheduler.getJobKeys(matcher);
List<Map<String, Object>> jobList = new ArrayList<>();
for (JobKey jobKey : jobKeys) {
List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);
for (Trigger trigger : triggers) {
Map<String, Object> job = new HashMap<>();
job.put("jobName", jobKey.getName());
job.put("jobGroupName", jobKey.getGroup());
job.put("trigger", trigger.getKey());
Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
job.put("jobStatus", triggerState.name());
if (trigger instanceof CronTrigger) {
CronTrigger cronTrigger = (CronTrigger) trigger;
String cronExpression = cronTrigger.getCronExpression();
job.put("cronExpression", cronExpression);
}
jobList.add(job);
}
}
return jobList;
} }

QuartzJobManager

四、增加quartz 属性配置文件 quartz.properties,放置resource目录下,此文件主要提供schedule自动注入提供属性

# 固定前缀org.quartz
org.quartz.scheduler.instanceName = DefaultQuartzScheduler
org.quartz.scheduler.instanceId = AUTO
org.quartz.scheduler.rmi.export = false
org.quartz.scheduler.rmi.proxy = false
org.quartz.scheduler.wrapJobExecutionInUserTransaction = false

五、创建quartz的配置文件QuartzrConfiguration,进行属性配置

 package com.qunyi.jifenzhi_zx.core.config;

 import com.qunyi.jifenzhi_zx.core.quartz.taskjobfactory.TaskJobFactory;
import org.quartz.Scheduler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.PropertiesFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.scheduling.quartz.SchedulerFactoryBean; import javax.sql.DataSource;
import java.io.IOException; /**
* @author xujingyang
* @Description: 任务调度配置
* @date 2018/5/30.
*/
@Configuration
public class QuartzConfiguration {
@Autowired
private DataSource dataSource;
@Autowired
private TaskJobFactory jobFactory; @Bean(name = "SchedulerFactory")
public SchedulerFactoryBean schedulerFactoryBean() throws IOException {
//获取配置属性
PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
propertiesFactoryBean.setLocation(new ClassPathResource("/quartz.properties"));
//在quartz.properties中的属性被读取并注入后再初始化对象
propertiesFactoryBean.afterPropertiesSet();
//创建SchedulerFactoryBean
SchedulerFactoryBean factory = new SchedulerFactoryBean();
factory.setQuartzProperties(propertiesFactoryBean.getObject());
factory.setJobFactory(jobFactory);
return factory;
} /*
* 通过SchedulerFactoryBean获取Scheduler的实例
*/
@Bean(name = "scheduler")
public Scheduler scheduler() throws IOException {
return schedulerFactoryBean().getScheduler();
}
}

六、创建基础任务调度接口

 package com.qunyi.jifenzhi_zx.core.quartz;

 import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException; /**
* @author xujingyang
* @Description: 基础任务调度taskJob接口
* @date 2018/5/30
* <p>
*/
public interface BaseTaskJob extends Job {
void execute(JobExecutionContext context)
throws JobExecutionException;
}

七、创建任务实现类

 package com.qunyi.jifenzhi_zx.module.taskJob;

 import com.qunyi.jifenzhi_zx.core.quartz.BaseTaskJob;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component; @Component
public class TestQuartz implements BaseTaskJob { Logger logger = LoggerFactory.getLogger(this.getClass()); public int i = 0; @Override
public void execute(JobExecutionContext context) throws JobExecutionException {
i++;
logger.error("task2>>>>>>> " + i); try {
// QuartzJobManager.getInstance().jobdelete(this.getClass().getSimpleName(),"ah");//执行完此任务就删除自己
} catch (Exception e) {
e.printStackTrace();
}
}
}

八、创建controller测试动态添加任务

 @PostMapping("/task")
public void task(HttpServletRequest request) throws Exception {
String name = PrimaryKeyUtil.nextId();
QuartzJobManager.getInstance().addJob(TestQuartz.class, name, "*/1 * * * * ?");
}

九、访问测试结果

总结及注意:

  这种任务执行时是整个类都要初始化一遍的,不像spring的schedule只初始执行方法,这种每次执行类中的变量都会初始化。

  添加新任务调度时,只需要新建类然后继承任务接口实现方法即可,这样在添加任务的时候只需要传新建类的class就可以了。

  传同一个class的时候,是同一个任务方法,只不过新建了开了一个线程来执行而已。

springBoot集成 quartz动态定时任务的更多相关文章

  1. SpringBoot集成Quartz实现定时任务

    1 需求 在我的前后端分离的实验室管理项目中,有一个功能是学生状态统计.我的设计是按天统计每种状态的比例.为了便于计算,在每天0点,系统需要将学生的状态重置,并插入一条数据作为一天的开始状态.另外,考 ...

  2. Spring Boot集成quartz实现定时任务并支持切换任务数据源

    org.quartz实现定时任务并自定义切换任务数据源 在工作中经常会需要使用到定时任务处理各种周期性的任务,org.quartz是处理此类定时任务的一个优秀框架.随着项目一点点推进,此时我们并不满足 ...

  3. Spring整合quartz2.2.3总结,quartz动态定时任务,Quartz定时任务集群配置

    Spring整合quartz2.2.3总结,quartz动态定时任务,Quartz定时任务集群配置 >>>>>>>>>>>>&g ...

  4. spring boot1.0 集成quartz 动态配置定时任务

    转载自 https://www.imooc.com/article/36278 一.Quartz简介了解 Quartz Quartz 是一个完全由 Java 编写的开源作业调度框架,为在 Java 应 ...

  5. 【spring-boot】 springboot整合quartz实现定时任务

    在做项目时有时候会有定时器任务的功能,比如某某时间应该做什么,多少秒应该怎么样之类的. spring支持多种定时任务的实现.我们来介绍下使用spring的定时器和使用quartz定时器 1.我们使用s ...

  6. SpringBoot集成Quartz(解决@Autowired空指针Null问题即依赖注入的属性为null)

    使用spring-boot作为基础框架,其理念为零配置文件,所有的配置都是基于注解和暴露bean的方式. Quartz的4个核心概念: 1.Job表示一个工作,要执行的具体内容.此接口中只有一个方法v ...

  7. Springboot集成Quartz

    之前学习过spring的定时任务 :https://www.cnblogs.com/slimshady/p/10112515.html 本文主要学习记录下springboot使用quartz 1.   ...

  8. ssh中使用spring的集成quartz 编写定时任务

    之前没有使用框架开发时对于开发定时任务都是 使用java的原声timer类,重写线程的run方法跑要执行的任务.刚刚换的新公司,项目使用ssh2,目前该项目中的定时任务的使用spirng集成的quar ...

  9. springboot整合Quartz实现定时任务

    1.maven依赖: <!--quartz--> <dependency> <groupId>org.quartz-scheduler</groupId> ...

随机推荐

  1. ORM版,学生管理系统03

    关于老师信息管理 建立多对多关系 第一种(通过外键建立) 自己写类,自己使其建立关系 缺点: 不能用Django ORM 多对多操作的语法 class Teacher(models.Model): t ...

  2. 创建Oracle数据库需要注意的几点

    规划表和存储空间,防止出现空间不足或者空间的浪费 规划快速恢复区,将快速恢复区定义在与数据文件不同的存储区域,减少IO争用 规划数据库的名称,db_name,db_main,sid 规划spfile内 ...

  3. 微软发布WCF教程及大量示例

    继前面 微软公司发布Windows Communication Foundation (WCF)和Windows CardSpace的示例程序之后,微软今天又发布了WF的教程和大量示例,对于学习WF的 ...

  4. selenium - xpath - 定位

    前言: XPath 是一门在 XML 文档中查找信息的语言.XPath 可用来在 XML 文档中对元素和属性进行遍历. 看这里介绍:w3school 首先来看一下xpath常用的语法: 一.xpath ...

  5. laravel中session的过期时间

    在项目开发的过程中,前后端分离 需要用session保存用户的登陆信息 这就涉及到session的有效期了 session又分为php中的session有效期和laravel中的session的有效期 ...

  6. CAN总线优点

    废除传统的站地址编码,代之以对通信数据块进行编码,可以多主方式工作: 采用非破坏性仲裁技术,当两个节点同时向网络上传送数据时,优先级低的节点主动停止数据发送,而优先级高的节点可不受影响继续传输数据,有 ...

  7. appium 中swipe()方法向左滑动时

    应该在UI Automator Viewer中读取到的例如ImageView [180,600][900,1320],如果要左滑,代码中应该是写为driver.swipe(900,1320,180,6 ...

  8. 1120 Friend Numbers

    题意:略. 思路:水题,略. 代码: #include <iostream> #include <string> using namespace std; ; }; int m ...

  9. 红黑树(Red-Black Tree)

    概念解析: 红黑树是一种自平衡二叉查找树(self-balancing binary search tree).因此,红黑树本身就是二叉树的一个变种.典型的用途是实现关联数组(Associative ...

  10. Java面试(4)

    1 哈希函数满足什么条件? 计算简单/散列地址分布均匀. 2 hash处理冲突方式?HashMap采用的什么办法? 开放地址法: 线性探测 . 线性补偿法.伪随机数法. 拉链法:HashMap采用链地 ...