网站关键词分隔,个体户年报网上申报,用网站还是阿里巴巴做soho,深圳it外包服务一、Quartz简介
Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目#xff0c;它可以与J2EE与J2SE应用程序相结合也可以单独使用。Quartz可以用来创建简单或为运行十个#xff0c;百个#xff0c;甚至是好几万个Jobs这样复杂的程序。Jobs可以做成标准的Java…一、Quartz简介
Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目它可以与J2EE与J2SE应用程序相结合也可以单独使用。Quartz可以用来创建简单或为运行十个百个甚至是好几万个Jobs这样复杂的程序。Jobs可以做成标准的Java组件或 EJBs。Quartz的最新版本为Quartz 2.3.2
1、组件简介
Job
Job是一个任务接口开发者定义自己的任务须实现该接口并重写execute(JobExecutionContext context)方法.Job中的任务有可能并发执行例如任务的执行时间过长而每次触发的时间间隔太短则会导致任务会被并发执行。为了避免出现上面的问题可以在Job实现类上使用DisallowConcurrentExecution,保证上一个任务执行完后再去执行下一个任务 JobDetailJobDetail是任务详情。 包含有任务名称任务组名称任务描述、具体任务Job的实现类、参数配置等等信息可以说JobDetail是任务的定义而Job是任务的执行逻辑。 Trigger Trigger是一个触发器,定义Job执行的时间规则。主要触发器:SimpleTrigger,CronTrigger,CalendarIntervalTrigger,DailyTimeIntervalTrigger。SimpleTrigger:从某一个时间开始以一定的时间间隔来执行任务,重复多少次。CronTrigger: 适合于复杂的任务使用cron表达式来定义执行规则。CalendarIntervalTrigger:指定从某一个时间开始以一定的时间间隔执行的任务,时间间隔比SimpleTrigger丰富DailyTimeIntervalTrigger:指定每天的某个时间段内以一定的时间间隔执行任务。并且它可以支持指定星期。所有的Trigger都包含了StartTime和endTime这两个属性用来指定Trigger被触发的时间区间。所有的Trigger都可以设置MisFire策略.MisFire策略是对于由于系统奔溃或者任务时间过长等原因导致Trigger在应该触发的时间点没有触发.并且超过了misfireThreshold设置的时间默认是一分钟没有超过就立即执行就算misfire(失火)了。这个时候就该设置如何应对这种变化了。激活失败指令Misfire Instructions是触发器的一个重要属性 发生Misfire 对于SimpleTrigger的处理策略
//将任务马上执行一次。对于不会重复执行的任务这是默认的处理策略。
MISFIRE_INSTRUCTION_FIRE_NOW 1;// 调度引擎重新调度该任务立即执行任务repeat count 保持不变
// 按照原有制定的执行方案执行repeat count次但是如果当前时间已经晚于end-time那么这个触发器将不会再被触发
// 简单的说就是错过了应该触发的时间没有按时执行但是最终它还是以原来的重复次数执行就是会比预计终止的时间晚。
MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_REPEAT_COUNT//和上面的类似区别就是不会立马执行而是在下一个激活点执行且超时期内错过的执行机会作废。
MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT// 这个也是重新调度任务但是它只按照剩余次数来触发
// 比如应该执行10次但是中间错过了3次没有执行那它最终只会执行剩余次数 7次。
MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_REMAINING_REPEAT_COUNT//在下一个激活点执行并重复到指定的次数。
MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_EXISTING_COUNT// 立即执行任务repeat count 保持不变就算到了endtime,也继续执行
MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY发生Misfire 对于其他的Trigger
//立刻执行一次然后就按照正常的计划执行。
MISFIRE_INSTRUCTION_FIRE_ONCE_NOW//目前不执行然后就按照正常的计划执行。这意味着如果下次执行时间超过了end time实际上就没有执行机会了。
MISFIRE_INSTRUCTION_DO_NOTHINGScheduler
调度器主要是用来管理Trigger、JobDetail的。Scheduler可以通过组名或者名称来对Trigger和JobDetail来进行管理一个Trigger只能对应一个Job但是一个Job可以对应多个Trigger.Scheduler 有两个实现类RemoteScheduler、StdScheduler。但它是由 SchdulerFactory创建的。SchdulerFactory是个接口它有两个实现类StdSchedulerFactory、DirectSchedulerFactory
2、相关Builder介绍
Quartz提供了相应的Builder方便我们进行构造。 JobBuilder 这个主要方便我们构建任务详情常用方法
withIdentity(String name, String group):配置Job名称与组名withDescription(String jobDescription): 任务描述requestRecovery(): 出现故障是否重新执行默认falsestoreDurably(): 作业完成后是否保留存储默认falseusingJobData(String dataKey, String value): 配置单个参数keyusingJobData(JobDataMap newJobDataMap): 配置多个参数放入一个mapsetJobData(JobDataMap newJobDataMap): 和上面类似但是这个参数直接指向newJobDataMap,直接设置的参数无效 TriggerBuilder 这个主要方便我们构建触发器常用方法withIdentity(String name, String group) 配置Trigger名称与组名withIdentity(TriggerKey triggerKey) 配置Trigger名称与组名withDescription(String triggerDescription) 描述withPriority(int triggerPriority) 设置优先级默认是5startAt(Date triggerStartTime) 设置开始时间startNow() 触发器立即生效endAt(Date triggerEndTime) 设置结束时间withSchedule(ScheduleBuilder schedBuilder) 设置调度builder,下面的builder就是
SimpleScheduleBuilder 几种触发器类型之一最简单常用的。常用方法
repeatForever()指定触发器将无限期重复withRepeatCount(int triggerRepeatCount)指定重复次数总触发的次数triggerRepeatCount1repeatSecondlyForever(int seconds)每隔seconds秒无限期重复repeatMinutelyForever(int minutes)每隔minutes分钟无限期重复repeatHourlyForever(int hours)每隔hours小时无限期重复repeatSecondlyForever()每隔1秒无限期重复repeatMinutelyForever()每隔1分钟无限期重复repeatHourlyForever()每隔1小时无限期重复withIntervalInSeconds(int intervalInSeconds)每隔intervalInSeconds秒执行withIntervalInMinutes(int intervalInMinutes)每隔intervalInMinutes分钟执行withIntervalInHours(int intervalInHours)每隔intervalInHours小时执行withMisfireHandlingInstructionFireNow()失火后的策略为MISFIRE_INSTRUCTION_FIRE_NOW CronScheduleBuilder 算是非常常用的了crontab 表达式常用方法cronSchedule(String cronExpression)使用cron表达式。 CalendarIntervalScheduleBuilder 常用方法inTimeZone(TimeZone timezone)设置时区withInterval(int timeInterval, IntervalUnit unit)相隔多少时间执行单位有毫秒、秒、分、时、天、周、月、年withIntervalInSeconds(int intervalInSeconds)相隔秒withIntervalInWeeks(int intervalInWeeks)相隔周withIntervalInMonths(int intervalInMonths)相隔月 等等方法 DailyTimeIntervalScheduleBuilderwithInterval(int timeInterval, IntervalUnit unit)相隔多少时间执行单位有秒、分、时其他单位的不支持会报错withIntervalInSeconds(int intervalInSeconds)相隔秒withIntervalInMinutes(int intervalInMinutes)相隔分withIntervalInHours(int intervalInHours)相隔时onDaysOfTheWeek(Set onDaysOfWeek)将触发器设置为在一周的指定日期触发。取值范围可以是1-71是星期天2是星期一…onDaysOfTheWeek(Integer … onDaysOfWeek)和上面一样3是星期二…7是星期六onMondayThroughFriday()每星期的周一导周五触发onSaturdayAndSunday()每星期的周六周日触发onEveryDay()每天触发withRepeatCount(int repeatCount)重复次数总的重复次数1 (at start time) repeatCountstartingDailyAt(TimeOfDay timeOfDay)触发的开始时间endingDailyAt(TimeOfDay timeOfDay)触发的结束时间
3、基本使用
引用依赖
dependencygroupIdorg.quartz-scheduler/groupIdartifactIdquartz/artifactIdversion2.3.2/version
/dependency在pom.xml文件中引入
简单例子
public class Demo {public static final String COUNT count;//这个属性如不是static,那么每次都要实例这个任务类,始终打印为: 1private static int num 1;public static void main(String[] args) throws SchedulerException {SchedulerFactory schedulerfactory new StdSchedulerFactory();
// Scheduler scheduler schedulerfactory.getScheduler();Scheduler scheduler StdSchedulerFactory.getDefaultScheduler();scheduler.start();JobDetail job JobBuilder.newJob(HelloJob.class).withIdentity(jobName, jobGroupName).usingJobData(COUNT,num).build();// 各种builder 的基本使用SimpleScheduleBuilder simpleScheduleBuilder SimpleScheduleBuilder.simpleSchedule().repeatForever().withIntervalInSeconds(3);CronScheduleBuilder cronScheduleBuilder CronScheduleBuilder.cronSchedule(*/3 * * * * ?);CalendarIntervalScheduleBuilder calendarIntervalScheduleBuilder CalendarIntervalScheduleBuilder.calendarIntervalSchedule().withInterval(3, DateBuilder.IntervalUnit.SECOND);DailyTimeIntervalScheduleBuilder dailyTimeIntervalScheduleBuilder DailyTimeIntervalScheduleBuilder.dailyTimeIntervalSchedule().withIntervalInSeconds(3);Trigger trigger TriggerBuilder.newTrigger().withIdentity(jobName, jobGroupName).withSchedule(dailyTimeIntervalScheduleBuilder).startNow().build();scheduler.scheduleJob(job, trigger);}// 保存在JobDataMap传递的参数PersistJobDataAfterExecutionDisallowConcurrentExecutionpublic static class HelloJob implements Job{Overridepublic void execute(JobExecutionContext context) throws JobExecutionException {JobDataMap jobDataMap context.getJobDetail().getJobDataMap();int count jobDataMap.getInt(COUNT);System.out.println( LocalDateTimeUtils.formatDateTimeNow(),countcount);jobDataMap.put(COUNT,num);}}
}是不是感觉很简单自己定义一个类然后实现Job接口重写execute(JobExecutionContext context) 方法然后使用调度器去调度一下即可。 简单玩完了和springboot整合一波。
二、与Springboot整合
这个才是重点Springboot基本是一个Java程序猿必备的技能了。什么框架都得和它整一下。
1、引入依赖
dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-quartz/artifactId
/dependencyspring官方自己都帮我们搞好了一些配置。
2、配置application.yml
如下
spring:datasource:url: jdbc:mysql://localhost:3306/quartz?serverTimezoneGMTcharacterEncodingutf8zeroDateTimeBehaviorconvertToNullallowMultiQueriestrueusername: rootpassword: rootdriver-class-name: com.mysql.cj.jdbc.Drivertype: com.alibaba.druid.pool.DruidDataSourcedruid:initialSize: 5minIdle: 5maxActive: 30max-wait: 6000pool-prepared-statements: truemax-pool-prepared-statement-per-connection-size: 20time-between-eviction-runs-millis: 60000min-evictable-idle-time-millis: 300000#validation-query: SELECT 1 FROM DUALtest-while-idle: truetest-on-borrow: falsetest-on-return: falsestat-view-servlet:enabled: trueurl-pattern: /druid/*#login-username: admin#login-password: adminfilter:stat:log-slow-sql: trueslow-sql-millis: 1000merge-sql: falsewall:config:multi-statement-allow: truequartz:job-store-type: jdbc #数据库方式#是否等待任务执行完毕后容器才会关闭wait-for-jobs-to-complete-on-shutdownfalse#配置的job是否覆盖已经存在的JOB信息overwrite-existing-jobs: falsejdbc:initialize-schema: ALWAYS #不初始化表结构properties:org:quartz:scheduler:instanceId: AUTO #默认主机名和时间戳生成实例ID,可以是任何字符串但对于所有调度程序来说必须是唯一的 对应qrtz_scheduler_state INSTANCE_NAME字段#instanceName: clusteredScheduler #quartzSchedulerjobStore:class: org.quartz.impl.jdbcjobstore.JobStoreTX #持久化配置driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate #我们仅为数据库制作了特定于数据库的代理useProperties: false #以指示JDBCJobStore将JobDataMaps中的所有值都作为字符串因此可以作为名称 - 值对存储而不是在BLOB列中以其序列化形式存储更多复杂的对象。从长远来看这是更安全的因为您避免了将非String类序列化为BLOB的类版本问题。tablePrefix: qrtz_ #数据库表前缀misfireThreshold: 60000 #在被认为“失火”之前调度程序将“容忍”一个Triggers将其下一个启动时间通过的毫秒数。默认值如果您在配置中未输入此属性为6000060秒。clusterCheckinInterval: 5000 #设置此实例“检入”*与群集的其他实例的频率以毫秒为单位。影响检测失败实例的速度。isClustered: true #打开群集功能threadPool: #连接池class: org.quartz.simpl.SimpleThreadPoolthreadCount: 10threadPriority: 5threadsInheritContextClassLoaderOfInitializingThread: true这里打算搞个集群版的就算你部署多台服务器定时任务会自己负载均衡不会每台服务器都执行。表的生成其实可以修改配置启动的时候自己在数据库生成表。操作方法修改:spring.quartz.jdbc.initialize-schema: ALWAYS、说明一下这里有3个值可选ALWAYS每次都生成、EMBEDDED仅初始化嵌入式数据源、NEVER不初始化数据源。表生成之后再改为never即可。注意一点就是我测试了下发现只有使用druid数据库连接池才会自动生成表。
3、表的说明
会自动生成的表如下
//以Blob 类型存储的触发器。
qrtz_blob_triggers//存放日历信息 quartz可配置一个日历来指定一个时间范围。
qrtz_calendars//存放cron类型的触发器。
qrtz_cron_triggers
//存储已经触发的trigger相关信息trigger随着时间的推移状态发生变化直到最后trigger执行完成从表中被删除。
qrtz_fired_triggers //存放一个jobDetail信息。
qrtz_job_details//job**监听器**。
qrtz_job_listeners//Quartz提供的锁表为多个节点调度提供分布式锁实现分布式调度默认有2个锁
qrtz_locks//存放暂停掉的触发器。
qrtz_paused_trigger_graps//存储所有节点的scheduler会定期检查scheduler是否失效
qrtz_scheduler_state//存储SimpleTrigger
qrtz_simple_triggers//触发器监听器。
qrtz_trigger_listeners//触发器的基本信息。
qrtz_triggers//存储CalendarIntervalTrigger和DailyTimeIntervalTrigger两种类型的触发器
qrtz_simprop_triggers重要表字段解析
CREATE TABLE qrtz_job_details (SCHED_NAME varchar(120) COLLATE utf8_bin NOT NULL COMMENT 调度器名,集群环境中使用,必须使用同一个名称——集群环境下”逻辑”相同的scheduler,默认为QuartzScheduler,JOB_NAME varchar(200) COLLATE utf8_bin NOT NULL COMMENT 集群中job的名字,JOB_GROUP varchar(200) COLLATE utf8_bin NOT NULL COMMENT 集群中job的所属组的名字,DESCRIPTION varchar(250) COLLATE utf8_bin DEFAULT NULL COMMENT 描述,JOB_CLASS_NAME varchar(250) COLLATE utf8_bin NOT NULL COMMENT 集群中个note job实现类的完全包名,quartz就是根据这个路径到classpath找到该job类,IS_DURABLE varchar(1) COLLATE utf8_bin NOT NULL COMMENT 是否持久化,把该属性设置为1quartz会把job持久化到数据库中,IS_NONCONCURRENT varchar(1) COLLATE utf8_bin NOT NULL COMMENT 是否并行该属性可以通过注解配置,IS_UPDATE_DATA varchar(1) COLLATE utf8_bin NOT NULL,REQUESTS_RECOVERY varchar(1) COLLATE utf8_bin NOT NULL COMMENT 当一个scheduler失败后其他实例可以发现那些执行失败的Jobs若是1那么该Job会被其他实例重新执行否则对应的Job只能释放等待下次触发,JOB_DATA blob COMMENT 一个blob字段存放持久化job对象,PRIMARY KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)
) ENGINEInnoDB DEFAULT CHARSETutf8 COLLATEutf8_bin COMMENT存储每一个已配置的 Job 的详细信息;CREATE TABLE qrtz_triggers (SCHED_NAME varchar(120) COLLATE utf8_bin NOT NULL COMMENT 调度器名和配置文件org.quartz.scheduler.instanceName保持一致,TRIGGER_NAME varchar(200) COLLATE utf8_bin NOT NULL COMMENT 触发器的名字,TRIGGER_GROUP varchar(200) COLLATE utf8_bin NOT NULL COMMENT 触发器所属组的名字,JOB_NAME varchar(200) COLLATE utf8_bin NOT NULL COMMENT qrtz_job_details表job_name的外键,JOB_GROUP varchar(200) COLLATE utf8_bin NOT NULL COMMENT qrtz_job_details表job_group的外键,DESCRIPTION varchar(250) COLLATE utf8_bin DEFAULT NULL COMMENT 描述,NEXT_FIRE_TIME bigint(13) DEFAULT NULL COMMENT 下一次触发时间,PREV_FIRE_TIME bigint(13) DEFAULT NULL COMMENT 上一次触发时间,PRIORITY int(11) DEFAULT NULL COMMENT 线程优先级,TRIGGER_STATE varchar(16) COLLATE utf8_bin NOT NULL COMMENT 当前trigger状态,TRIGGER_TYPE varchar(8) COLLATE utf8_bin NOT NULL COMMENT 触发器类型,START_TIME bigint(13) NOT NULL COMMENT 开始时间,END_TIME bigint(13) DEFAULT NULL COMMENT 结束时间,CALENDAR_NAME varchar(200) COLLATE utf8_bin DEFAULT NULL COMMENT 日历名称,MISFIRE_INSTR smallint(2) DEFAULT NULL COMMENT misfire处理规则,1代表【以当前时间为触发频率立刻触发一次然后按照Cron频率依次执行】,2代表【不触发立即执行,等待下次Cron触发频率到达时刻开始按照Cron频率依次执行】,-1代表【以错过的第一个频率时间立刻开始执行,重做错过的所有频率周期后当下一次触发频率发生时间大于当前时间后再按照正常的Cron频率依次执行】,JOB_DATA blob COMMENT JOB存储对象,PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),KEY SCHED_NAME (SCHED_NAME,JOB_NAME,JOB_GROUP),CONSTRAINT qrtz_triggers_ibfk_1 FOREIGN KEY (SCHED_NAME, JOB_NAME, JOB_GROUP) REFERENCES qrtz_job_details (SCHED_NAME, JOB_NAME, JOB_GROUP)
) ENGINEInnoDB DEFAULT CHARSETutf8 COLLATEutf8_bin COMMENT存储已配置的 Trigger 的信息;CREATE TABLE qrtz_cron_triggers (SCHED_NAME varchar(120) COLLATE utf8_bin NOT NULL COMMENT 集群名,TRIGGER_NAME varchar(200) COLLATE utf8_bin NOT NULL COMMENT 调度器名,qrtz_triggers表trigger_name的外键,TRIGGER_GROUP varchar(200) COLLATE utf8_bin NOT NULL COMMENT qrtz_triggers表trigger_group的外键,CRON_EXPRESSION varchar(200) COLLATE utf8_bin NOT NULL COMMENT cron表达式,TIME_ZONE_ID varchar(80) COLLATE utf8_bin DEFAULT NULL COMMENT 时区ID,PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),CONSTRAINT qrtz_cron_triggers_ibfk_1 FOREIGN KEY (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP) REFERENCES qrtz_triggers (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP)
) ENGINEInnoDB DEFAULT CHARSETutf8 COLLATEutf8_bin COMMENT存放cron类型的触发器;CREATE TABLE qrtz_scheduler_state (SCHED_NAME varchar(120) COLLATE utf8_bin NOT NULL COMMENT 调度器名称集群名,INSTANCE_NAME varchar(200) COLLATE utf8_bin NOT NULL COMMENT 集群中实例ID配置文件中org.quartz.scheduler.instanceId的配置,LAST_CHECKIN_TIME bigint(13) NOT NULL COMMENT 上次检查时间,CHECKIN_INTERVAL bigint(13) NOT NULL COMMENT 检查时间间隔,PRIMARY KEY (SCHED_NAME,INSTANCE_NAME)
) ENGINEInnoDB DEFAULT CHARSETutf8 COLLATEutf8_bin COMMENT调度器状态;CREATE TABLE qrtz_fired_triggers (SCHED_NAME varchar(120) COLLATE utf8_bin NOT NULL COMMENT 调度器名称集群名,ENTRY_ID varchar(95) COLLATE utf8_bin NOT NULL COMMENT 运行Id,TRIGGER_NAME varchar(200) COLLATE utf8_bin NOT NULL COMMENT 触发器名,TRIGGER_GROUP varchar(200) COLLATE utf8_bin NOT NULL COMMENT 触发器组,INSTANCE_NAME varchar(200) COLLATE utf8_bin NOT NULL COMMENT 集群中实例ID,FIRED_TIME bigint(13) NOT NULL COMMENT 触发时间,SCHED_TIME bigint(13) NOT NULL COMMENT 计划时间,PRIORITY int(11) NOT NULL COMMENT 线程优先级,STATE varchar(16) COLLATE utf8_bin NOT NULL COMMENT 状态,JOB_NAME varchar(200) COLLATE utf8_bin DEFAULT NULL COMMENT 任务名,JOB_GROUP varchar(200) COLLATE utf8_bin DEFAULT NULL COMMENT 任务组,IS_NONCONCURRENT varchar(1) COLLATE utf8_bin DEFAULT NULL COMMENT 是否并行,REQUESTS_RECOVERY varchar(1) COLLATE utf8_bin DEFAULT NULL COMMENT 是否恢复,PRIMARY KEY (SCHED_NAME,ENTRY_ID)
) ENGINEInnoDB DEFAULT CHARSETutf8 COLLATEutf8_bin COMMENT存储与已触发的 Trigger 相关的状态信息以及相联 Job 的执行信息;CREATE TABLE qrtz_simple_triggers (SCHED_NAME varchar(120) COLLATE utf8_bin NOT NULL COMMENT 调度器名集群名,TRIGGER_NAME varchar(200) COLLATE utf8_bin NOT NULL COMMENT 触发器名,TRIGGER_GROUP varchar(200) COLLATE utf8_bin NOT NULL COMMENT 触发器组,REPEAT_COUNT bigint(7) NOT NULL COMMENT 重复次数,REPEAT_INTERVAL bigint(12) NOT NULL COMMENT 重复间隔,TIMES_TRIGGERED bigint(10) NOT NULL COMMENT 已触发次数,PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),CONSTRAINT qrtz_simple_triggers_ibfk_1 FOREIGN KEY (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP) REFERENCES qrtz_triggers (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP)
) ENGINEInnoDB DEFAULT CHARSETutf8 COLLATEutf8_bin COMMENT存储简单的 Trigger包括重复次数间隔以及已触的次数;4、怎么使用
当我们引入spring-boot-starter-quartz的依赖后springboot在启动的时候会自动加载配置类org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration。 会帮我们初始化好调度器,源码SchedulerFactoryBean实现InitializingBean重写afterPropertiesSet() 里面就有了。而且Scheduler,Spring默认是帮我们启动的不需要手动启动。
使用如下
Autowired
private Scheduler scheduler;spring会自己注入通过工厂类SchedulerFactoryBean的getObject()方法。 搞个基本的增删改查,很简单代码也没怎么优化就这样吧。
Component
public class JobService {Autowiredprivate Scheduler scheduler;/*** 增加一个job** param jobClass* 任务实现类* param jobName* 任务名称(建议唯一)* param jobGroupName* 任务组名* param cron* 时间表达式 如0/5 * * * * ? * param jobData* 参数*/public void addJob(Class? extends Job jobClass, String jobName, String jobGroupName, String cron, Map jobData,Date endTime)throws SchedulerException {// 创建jobDetail实例绑定Job实现类// 指明job的名称所在组的名称以及绑定job类// 任务名称和组构成任务keyJobDetail jobDetail JobBuilder.newJob(jobClass).withIdentity(jobName, jobGroupName).build();// 设置job参数if (jobData ! null jobData.size() 0) {jobDetail.getJobDataMap().putAll(jobData);}// 定义调度触发规则// 使用cornTrigger规则// 触发器keyTrigger trigger TriggerBuilder.newTrigger().withIdentity(jobName, jobGroupName).startAt(DateBuilder.futureDate(1, DateBuilder.IntervalUnit.SECOND)).withSchedule(CronScheduleBuilder.cronSchedule(cron)).startNow().build();if(endTime!null){trigger.getTriggerBuilder().endAt(endTime);}// 把作业和触发器注册到任务调度中scheduler.scheduleJob(jobDetail, trigger);}public Trigger getTrigger(String jobName, String jobGroupName) throws SchedulerException {return scheduler.getTrigger(TriggerKey.triggerKey(jobName, jobGroupName));}/*** 删除任务一个job** param jobName* 任务名称* param jobGroupName* 任务组名*/public void deleteJob(String jobName, String jobGroupName) {try {scheduler.deleteJob(JobKey.jobKey(jobName, jobGroupName));} catch (Exception e) {e.printStackTrace();}}/*** 暂停一个job** param jobName* param jobGroupName*/public void pauseJob(String jobName, String jobGroupName) {try {JobKey jobKey JobKey.jobKey(jobName, jobGroupName);scheduler.pauseJob(jobKey);} catch (SchedulerException e) {e.printStackTrace();}}/*** 恢复一个job** param jobName* param jobGroupName*/public void resumeJob(String jobName, String jobGroupName) {try {JobKey jobKey JobKey.jobKey(jobName, jobGroupName);scheduler.resumeJob(jobKey);} catch (SchedulerException e) {e.printStackTrace();}}/*** 立即执行一个job** param jobName* param jobGroupName*/public void runJobNow(String jobName, String jobGroupName) {try {JobKey jobKey JobKey.jobKey(jobName, jobGroupName);scheduler.triggerJob(jobKey);} catch (SchedulerException e) {e.printStackTrace();}}/*** 修改 一个job的 时间表达式** param jobName* param jobGroupName* param cron*/public void updateJob(String jobName, String jobGroupName, String cron,Map jobData) {try {TriggerKey triggerKey TriggerKey.triggerKey(jobName, jobGroupName);Trigger trigger scheduler.getTrigger(triggerKey);if(trigger instanceof CronTrigger){CronTrigger cronTrigger (CronTrigger) trigger;cronTrigger cronTrigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(CronScheduleBuilder.cronSchedule(cron)).build();}else {// 这里其实可以删掉在添加即可懒得写了throw new RuntimeException(格式转换错误);}// 设置job参数if (jobData ! null jobData.size() 0) {trigger.getJobDataMap().putAll(jobData);}// 重启触发器scheduler.rescheduleJob(triggerKey, trigger);} catch (SchedulerException e) {e.printStackTrace();}}
}和上面得基本demo没什么两样就是scheduler 并不需要我们去创建了。当部署多个服务时也不会重复执行。且任务会负载均衡分配。
5、时间演练
Quartz 提供了下一次运行的时间我们可以通过下一次运行的时间比对是否符合我们的预期
public class Test {public static void main(String[] args) throws ParseException, SchedulerException {String cron 0/10 * * * * ?;CronExpression cronExpression new CronExpression(cron);Date nextValidTimeAfter cronExpression.getNextValidTimeAfter(new Date());System.out.println(nextValidTimeAfter nextValidTimeAfter);nextValidTimeAfter cronExpression.getNextValidTimeAfter(nextValidTimeAfter);System.out.println(nextValidTimeAfter nextValidTimeAfter);nextValidTimeAfter cronExpression.getNextValidTimeAfter(nextValidTimeAfter);System.out.println(nextValidTimeAfter nextValidTimeAfter);CalendarIntervalTrigger calendarIntervalTrigger newTrigger().withIdentity(trigger3, group1).withSchedule(calendarIntervalSchedule().withIntervalInWeeks(3)).build();Date nextFireTime calendarIntervalTrigger.getFireTimeAfter(new Date());System.out.println(nextFireTime DateUtils.formatTime(nextFireTime));nextFireTime calendarIntervalTrigger.getFireTimeAfter(nextFireTime);System.out.println(nextFireTime DateUtils.formatTime(nextFireTime));nextFireTime calendarIntervalTrigger.getFireTimeAfter(nextFireTime);System.out.println(nextFireTime DateUtils.formatTime(nextFireTime));nextFireTime calendarIntervalTrigger.getFireTimeAfter(nextFireTime);System.out.println(nextFireTime DateUtils.formatTime(nextFireTime));}
}每个 Tigger 都有一个Date getFireTimeAfter(Date afterTime) 的方法返回的就是下一次运行的时间。