springboot-quartz普通任务与可传参任务
两者区别与作用:
普通任务:总调度(SchedulerFactoryBean)--> 定时调度器(CronTriggerFactoryBean) --> 调度明细自定义执行方法bean(MethodInvokingJobDetailFactoryBean) -->调度bean(我们定义的job类)
可传参任务:总调度(SchedulerFactoryBean)--> 定时调度器(CronTriggerFactoryBean) --> 调度明细bean(JobDetailFactoryBean)
如上是我们在配置调度器时的具体步骤及相互之间的依赖,区别主要在调度明细bean上,普通任务是(MethodInvokingJobDetailFactoryBean),而可传参任务是(JobDetailFactoryBean):
1)普通任务可以自定义执行方法,也就是说在其配置的调度bean(我们定义的job类)中我们可以自定义调度器最终执行的方法,可以叫work1也可以叫work2,and so on。而且要记住的一点,必须是无入参的方法!!!(做了一个测试,测试目的是看通过此类型调度类型是否也能传入参数所以定义了一个带入参的自定义方法即public void work(JobExecutionContext jobExecutionContext),最中测试结果是spring quartz会报找不到work方法及No such method work(),其默认执行我们生命的work无入参的方法。
2)可传参任务必须继承QuartzJobBean,重写protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException方法,其中JobExecutionContext就是我们在定义调度器明细时传入参数的上下文,我们可以通过JobExecutionContext取出传入的map,调度任务最终执行的就是executeInternal方法,使用该调度明细任务无法使用自定义方法。
提供三种形式的定时任务:
1、固定等待时间 @Scheduled(fixedDelay = 时间间隔 )
2、固定间隔时间 @Scheduled(fixedRate = 时间间隔 )
3、Corn表达式 @Scheduled(cron = Corn表达式)
添加依赖(不知道为什么要加jboss-logging依赖,没有会报错)
<!-- 添加springboot对Quartz的支持 -->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.3.0</version>
</dependency> <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency> <!-- https://mvnrepository.com/artifact/org.jboss.logging/jboss-logging -->
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging</artifactId>
</dependency>
配置quartz.properties
#===============================================================
#Configure Main Scheduler Properties 调度器属性
#===============================================================
#调度器的实例名
org.quartz.scheduler.instanceName = QuartzScheduler
#调度器的实例ID,大多数情况设置为auto即可
org.quartz.scheduler.instanceId = AUTO #===============================================================
#Configure ThreadPool 线程池属性
#===============================================================
#处理Job的线程个数,至少为1,但最多的话最好不要超过100,在多数机器上设置该值超过100的话就会显得相当不实用了,特别是在你的 Job 执行时间较长的情况下
org.quartz.threadPool.threadCount = 5
#线程的优先级,优先级别高的线程比级别低的线程优先得到执行。最小为1,最大为10,默认为5
org.quartz.threadPool.threadPriority = 5
#一个实现了 org.quartz.spi.ThreadPool 接口的类,Quartz 自带的线程池实现类是 org.quartz.smpl.SimpleThreadPool
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool #===============================================================
#Configure JobStore 作业存储设置
#===============================================================
#要使 Job 存储在内存中需通过设置 org.quartz.jobStrore.class 属性为 org.quartz.simpl.RAMJobStore
org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore
一、普通任务
1、任务类
package cloud.app.prod.home.quartz.mem; import org.apache.log4j.Logger;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.stereotype.Component; import cloud.app.prod.home.common.FailException; /**
* Author : YongBo Xie </br>
* File Name: ScheduleTask.java </br>
* Created Date: 2018年3月31日 下午3:37:43 </br>
* Modified Date: 2018年3月31日 下午3:37:43 </br>
* Version: 1.0 </br>
*/
@Configuration
@Component // 此注解必加
@EnableScheduling // 此注解必加
public class ScheduleTask { private static Logger logger = Logger.getLogger(ScheduleTask.class); public void marketingActivity() throws FailException {
logger.info("execute activity");
} }
2、Quartz配置类
package cloud.app.prod.home.quartz.mem; import org.quartz.Trigger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.CronTriggerFactoryBean;
import org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean;
import org.springframework.scheduling.quartz.SchedulerFactoryBean; /**
* Author : YongBo Xie </br>
* File Name: QuartzConfigration.java </br>
* Created Date: 2018年3月31日 下午3:42:04 </br>
* Modified Date: 2018年3月31日 下午3:42:04 </br>
* Version: 1.0 </br>
*/
@Configuration
public class QuartzConfigration { /**
* Details:配置定时任务
*/
@Bean(name = "marketingActivityJobDetail")
public MethodInvokingJobDetailFactoryBean detailFactoryBean(ScheduleTask task) {// ScheduleTask为需要执行的任务
MethodInvokingJobDetailFactoryBean jobDetail = new MethodInvokingJobDetailFactoryBean();
/*
* 是否并发执行
* 例如每5s执行一次任务,但是当前任务还没有执行完,就已经过了5s了,
* 如果此处为true,则下一个任务会执行,如果此处为false,则下一个任务会等待上一个任务执行完后,再开始执行
*/
jobDetail.setConcurrent(false); jobDetail.setName("marketing_activity");// 设置任务的名字
jobDetail.setGroup("marketing_activity");// 设置任务的分组,这些属性都可以存储在数据库中,在多任务的时候使用 /*
* 为需要执行的实体类对应的对象
*/
jobDetail.setTargetObject(task); /*
* marketingActivity为需要执行的方法
* 通过这几个配置,告诉JobDetailFactoryBean我们需要执行定时执行ScheduleTask类中的marketingActivity方法
*/
jobDetail.setTargetMethod("marketingActivity");
return jobDetail;
} /**
* Details:配置定时任务的触发器,也就是什么时候触发执行定时任务
*/
@Bean(name = "marketingActivityJobTrigger")
public CronTriggerFactoryBean cronJobTrigger(MethodInvokingJobDetailFactoryBean jobDetail) {
CronTriggerFactoryBean tigger = new CronTriggerFactoryBean();
tigger.setJobDetail(jobDetail.getObject());
tigger.setCronExpression("0 0 1 * * ?");// 初始时的cron表达式 ,每天1点执行
tigger.setName("marketing_activity");// trigger的name
return tigger; } /**
* Details:定义quartz调度工厂
*/
@Bean(name = "marketingActivityScheduler")
public SchedulerFactoryBean schedulerFactory(Trigger cronJobTrigger) {
SchedulerFactoryBean bean = new SchedulerFactoryBean();
// 用于quartz集群,QuartzScheduler 启动时更新己存在的Job
bean.setOverwriteExistingJobs(true);
// 延时启动,应用启动1秒后
bean.setStartupDelay(1);
// 注册触发器
bean.setTriggers(cronJobTrigger);
return bean;
}
}
3、定时查库,并更新任务
package cloud.app.prod.home.quartz.mem; import javax.annotation.Resource; import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component; import cloud.app.prod.home.common.FailException;
import cloud.app.prod.home.mem.vo.MarketingActivitiesVO;
import cloud.app.prod.home.utils.DSHUtils; /**
* Author : YongBo Xie </br>
* File Name: ScheduleRefreshDatabase.java </br>
* Created Date: 2018年3月31日 下午3:58:08 </br>
* Modified Date: 2018年3月31日 下午3:58:08 </br>
* Version: 1.0 </br>
*/
@Configuration
@EnableScheduling
@Component
public class ScheduleRefreshCron { @Resource(name = "marketingActivityJobDetail")
private JobDetail jobDetail; @Resource(name = "marketingActivityJobTrigger")
private CronTrigger cronTrigger; @Resource(name = "marketingActivityScheduler")
private Scheduler scheduler; @Scheduled(fixedRate = 5000) // 每隔5s查库,并根据查询结果决定是否重新设置定时任务
// @Scheduled(cron = "0 0 1 * * ?")
public void scheduleUpdateCronTrigger() throws SchedulerException, FailException {
CronTrigger trigger = (CronTrigger) scheduler.getTrigger(cronTrigger.getKey());
String currentCron = trigger.getCronExpression();// 当前Trigger使用的
String searchCron = "0 41 10 ? * *";// 从数据库查询出来的
System.out.println(currentCron);
System.out.println(searchCron); // 如果当前使用的cron表达式和从数据库中查询出来的cron表达式一致,则不刷新任务
if (!currentCron.equals(searchCron)) {
MarketingActivitiesVO marketingActivitiesVO = new MarketingActivitiesVO();
marketingActivitiesVO.setId(DSHUtils.generateUUID()); // 表达式调度构建器
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(searchCron);
// 按新的cronExpression表达式重新构建trigger
trigger = (CronTrigger) scheduler.getTrigger(cronTrigger.getKey());
trigger = trigger.getTriggerBuilder().withIdentity(cronTrigger.getKey())
.withSchedule(scheduleBuilder).build();
// 按新的trigger重新设置job执行
scheduler.rescheduleJob(cronTrigger.getKey(), trigger);
currentCron = searchCron;
}
}
}
二、可传参任务
在Spring Boot中使用Quartz时,如果job涉及到调用其他自定义方法,需要通过定义Job Factory实现自动注入
传参关键代码:
1)、接收参数
@Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
JobDataMap dataMap = context.getJobDetail().getJobDataMap();
MarketingActivitiesVO marketingActivitiesVO = (MarketingActivitiesVO) dataMap.get("marketingActivitiesVO");
}
2)、传入参数
// 创建一项作业
JobDetail job = JobBuilder.newJob(ScheduleTask.class)
.withIdentity("marketingActivityJob", "marketingActivityGroup")
.build(); // 设置参数
MarketingActivitiesVO marketingActivitiesVO = new MarketingActivitiesVO();
marketingActivitiesVO.setId(DSHUtils.generateUUID());
job.getJobDataMap().put("marketingActivitiesVO", marketingActivitiesVO);
1、自定义MyJobFactory类
package cloud.app.prod.home.quartz; 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 : YongBo Xie </br>
* File Name: MyJobFactory.java </br>
* Created Date: 2018年4月2日 下午3:27:30 </br>
* Modified Date: 2018年4月2日 下午3:27:30 </br>
* Version: 1.0 </br>
*/
@Component
public class MyJobFactory extends AdaptableJobFactory { @Autowired
private AutowireCapableBeanFactory capableBeanFactory; @Override
protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
// 调用父类的方法
Object jobInstance = super.createJobInstance(bundle);
// 进行注入
capableBeanFactory.autowireBean(jobInstance);
return jobInstance;
}
}
2、配置SchedulerFactoryBean
package cloud.app.prod.home.quartz; import java.io.IOException;
import java.util.Properties; 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.annotation.EnableScheduling;
import org.springframework.scheduling.quartz.SchedulerFactoryBean; import cloud.app.prod.home.quartz.MyJobFactory; /**
* Author : YongBo Xie </br>
* File Name: QuartzConfigration.java </br>
* Created Date: 2018年3月31日 下午3:42:04 </br>
* Modified Date: 2018年3月31日 下午3:42:04 </br>
* Version: 1.0 </br>
*/
@Configuration
@EnableScheduling
public class QuartzConfigration { @Autowired
private MyJobFactory myJobFactory; @Bean
public SchedulerFactoryBean schedulerFactoryBean() throws IOException {
SchedulerFactoryBean factory = new SchedulerFactoryBean(); // 用于quartz集群,QuartzScheduler 启动时更新己存在的Job
factory.setOverwriteExistingJobs(true); // 延时启动,应用启动1秒后
// factory.setStartupDelay(1); // 加载quartz数据源配置
// factory.setQuartzProperties(quartzProperties()); // 自定义Job Factory,用于Spring注入
factory.setJobFactory(myJobFactory); return factory;
} /**
* 加载quartz数据源配置
*
* @return
* @throws IOException
*/
@Bean
public Properties quartzProperties() throws IOException {
PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
propertiesFactoryBean.setLocation(new ClassPathResource("/quartz.properties"));
propertiesFactoryBean.afterPropertiesSet();
return propertiesFactoryBean.getObject();
}
}
3、执行任务类
package cloud.app.prod.home.quartz.mem; import org.apache.log4j.Logger;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.quartz.QuartzJobBean;
import org.springframework.stereotype.Component; import cloud.app.prod.home.common.FailException;
import cloud.app.prod.home.mem.vo.MarketingActivitiesVO;
import cloud.app.prod.home.rabbitmq.mem.MarketingActivitieRabbitMqSender; /**
* Author : YongBo Xie </br>
* File Name: ScheduleTask.java </br>
* Created Date: 2018年3月31日 下午3:37:43 </br>
* Modified Date: 2018年3月31日 下午3:37:43 </br>
* Version: 1.0 </br>
*/
@Configuration
@Component // 此注解必加
@EnableScheduling // 此注解必加
@DisallowConcurrentExecution // 任务同步
public class ScheduleTask extends QuartzJobBean { private static Logger logger = Logger.getLogger(ScheduleTask.class);
@Autowired
private MarketingActivitieRabbitMqSender marketingActivitieRabbitMqSender; @Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
logger.info("execute activity");
JobDataMap dataMap = context.getJobDetail().getJobDataMap();
MarketingActivitiesVO marketingActivitiesVO = (MarketingActivitiesVO) dataMap.get("marketingActivitiesVO");
logger.info("marketingActivitiesVO.id: " + marketingActivitiesVO.getId());
try {
logger.info("marketingActivitieRabbitMqSender: " + marketingActivitieRabbitMqSender);
marketingActivitieRabbitMqSender.sendRabbitmqDirect(marketingActivitiesVO);
} catch (FailException e) {
e.printStackTrace();
}
} }
4、设置任务类
package cloud.app.prod.home.quartz.mem; import java.util.Date; import org.apache.log4j.Logger;
import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.DateBuilder;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.TriggerBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.stereotype.Component; import cloud.app.prod.home.common.FailException;
import cloud.app.prod.home.mem.vo.MarketingActivitiesVO;
import cloud.app.prod.home.utils.DSHUtils; /**
* Author : YongBo Xie </br>
* Project Name: DSH-SCRM </br>
* Created Date: 2018年3月31日 下午3:58:08 </br>
* Modified Date: 2018年3月31日 下午3:58:08 </br>
* Version: 1.0 </br>
*/
@Configuration
@EnableScheduling
@Component
public class ScheduleRefreshCron { private static Logger logger = Logger.getLogger(ScheduleRefreshCron.class); @Autowired
private SchedulerFactoryBean schedulerFactoryBean; @Scheduled(fixedRate = 5000) // 每隔5s查库
// @Scheduled(cron = "0 0 1 * * ?")
public void scheduleUpdateCronTrigger() throws FailException, SchedulerException {
try{
logger.info("----- scheduling job --------"); String searchCron = "*/5 * * * * ?";// 从数据库查询出来的 // 获取一个调度器
// SchedulerFactory factory = new StdSchedulerFactory();
// Scheduler scheduler = factory.getScheduler();
Scheduler scheduler = schedulerFactoryBean.getScheduler(); // 创建一项作业
JobDetail job = JobBuilder.newJob(ScheduleTask.class)
.withIdentity("marketingActivityJob", "marketingActivityGroup")
.build(); // 设置参数
MarketingActivitiesVO marketingActivitiesVO = new MarketingActivitiesVO();
marketingActivitiesVO.setId(DSHUtils.generateUUID());
job.getJobDataMap().put("marketingActivitiesVO", marketingActivitiesVO); // 作业的执行时间(当前时间的下一分钟)
Date runTime = DateBuilder.evenMinuteDate(new Date()); // 创建一个触发器
CronTrigger trigger = (CronTrigger)TriggerBuilder.newTrigger()
.withIdentity("marketingActivityTrigger", "marketingActivityGroup")
.startAt(runTime) //该触发器将在runTime时执行作业
.endAt(new Date(System.currentTimeMillis()+5*1000+60*1000)) //该触发器将在runTime时结束作业
.withSchedule(CronScheduleBuilder.cronSchedule(searchCron)) // 具体执行时间
.build(); // 告诉调度器使用该触发器来安排作业
scheduler.scheduleJob(job, trigger);
// 启动调度器
scheduler.start();
logger.info("------ started scheduler -------"); logger.info("------ waiting 2 minutes ------");
Thread.sleep(2*60*1000); logger.info("------- shutting down ------");
// 关闭调度器
scheduler.shutdown(true);
logger.info("------- shutdown complete -------");
}catch(Exception e){
logger.error(DSHUtils.formatException(e));
throw new FailException(e.getMessage());
}
}
}
springboot-quartz普通任务与可传参任务的更多相关文章
- spring-quartz普通任务与可传参任务
两者区别与作用: 普通任务:总调度(SchedulerFactoryBean)--> 定时调度器(CronTriggerFactoryBean) --> 调度明细自定义执行方法bean(M ...
- SpringBoot系列: Java应用程序传参和SpringBoot参数文件
===========================向java 程序传参的几种形式:===========================1. 使用 OS 环境变量. 这个不推荐. 2. 使用JVM ...
- springboot对传参的拦截统一处理
在学习某网<java秒杀系统方案优化>的课程中,学到了一种springboot对传参的拦截统一处理的方式,特记录一下. 如后台方法一般需要根据token从Session中获取User对象, ...
- SpringBoot 2.x (2):请求和传参
其实请求和传参这些知识属于SpringMVC 不过这也属于必须掌握的知识,巩固基础吧 GET请求: 以第一篇文章自动的方式创建SpringBoot项目: 然后新建Controller: package ...
- SpringBoot传参方式
地址传参 1.创建一个Action类 package com.lion.action; import org.springframework.stereotype.Controller; import ...
- SpringBoot 处理 POST Json 传参枚举
在 Spring 框架中对枚举类型的序列化/反序列化是有限制的. 假设如下面这样在某些情况下就不能正常工作: 123456789 public enum PayChannelEnum implemen ...
- Docker 如何动态给SpringBoot项目传参
关于SpringBoot配置数据源 在项目开发中,我们往往需要配置多套不同的配置环境例如:本地开发.测试环境.部署环境.每一个环境的数据源配置可能都不同,因此需要写不同的数据源配置.如果用Docker ...
- springboot实现xml传参和返回值
1.新建maven工程xml-bean-convert pom.xml如下 <?xml version="1.0" encoding="UTF-8"?&g ...
- 二十一、springboot之定制URL匹配规则(项目中遇到的问题:get方式传参,带有小数点,被忽略)
一.问题描述: get方式传参,在传送价格,积分时(带有小数点),debug后台微服务接受到的参数,却不带小数点,如:price是0.55,后台接受后却是0 二.解决 在WebConfiguratio ...
随机推荐
- Redis 的简单运算
Redis 的简单运算 命令 说明 备注 incr key 在原字段上加 1 只能对整数操作 incrby key increment 在原字段上加上整数 (increment) 只能对整数操作 de ...
- CF831C Jury Marks
思路: 关键在于“插入”一个得分之后,其他所有得分也随之确定了. 实现: #include <iostream> #include <cstdio> #include < ...
- 给网站添加运行时间的JavaScript完整代码
function secondToDate(second) { if (!second) { return 0; } var time = new Array(0, 0, 0, 0, 0); if ( ...
- zblog插件增加后台导航栏的方法
有时我们经常需要对插件进行设置,但是又不能让用户去做这些,那么下面的方法将会给插件增加在后台导航栏显示的功能 首先打开对应插件的文件夹,找到对应插件的 include.php 文件 将下面的代码粘 ...
- linux shell & bash
shell & bash shell指允许用户通过文本操作计算机的程序. interactive shell:从是否通过标准输入输出与用户进行交互的角度分为交互式shell(interacti ...
- Ajax——异步基础知识(一)
基础概念 1.异步请求可以做到偷偷向服务器发送请求,而页面却不刷新 2.get异步请求传递参数是通过url追加键值对的方式 3.post异步请求比较特殊,需要设置请求的类型 User-Agent:浏览 ...
- xamarin.forms模拟rem动态大小值,实现屏幕适配
开发app的时候,比较麻烦的地方,就是处理屏幕适配,比如文字设为12的大小,测试的时候,看得文字挺正常,可是,放到高分辨率设备一看,文字就变得特别小, 怎样实现随着分辨率变大或者变小,所有的size数 ...
- 如何用windbg查看_eprocess结构
打开菜单: File->Symbol File Path... 输入: C:/MyCodesSymbols; SRV*C:/MyLocalSymbols*http://msdl.microsof ...
- CAD动态绘制带面积周长的圆(com接口)
CAD绘制图像的过程中,画圆的情况是非常常见的,用户可以在控件视区点取任意一点做为圆心,再动态点取半径绘制圆. 主要用到函数说明: _DMxDrawX::DrawCircle 绘制一个圆.详细说明如下 ...
- 转:LINQ教程一:LINQ简介
原文地址:https://www.cnblogs.com/dotnet261010/p/8278793.html 一.为什么要使用LINQ 要理解为什么使用LINQ,先来看下面一个例子.假设有一个整数 ...