前言
Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目,它可以与J2EE与J2SE应用程序相结合也可以单独使用。Quartz可以用来创建简单或为运行十个,百个,甚至是好几万个Jobs这样复杂的程序。Jobs可以做成标准的Java组件或 EJBs
一、添加依赖
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency>
<dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> <version>2.2.1</version> </dependency>
<dependency><!-- 该依赖必加,里面有sping对schedule的支持 --> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> </dependency>
<!--必须添加,要不然会出错,项目无法启动--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>4.3.16.RELEASE</version> </dependency>
</dependencies>
|
二、相关配置
由于springboot是无xml配置,所以此处我们采用bean注解的方式实现quartz的配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| @Configuration public class QuartzConfigration { @Bean(name = "jobDetail") public MethodInvokingJobDetailFactoryBean detailFactoryBean(SchedulerTask task) { MethodInvokingJobDetailFactoryBean jobDetail = new MethodInvokingJobDetailFactoryBean();
jobDetail.setConcurrent(true);
jobDetail.setName("scheduler"); jobDetail.setGroup("scheduler_group");
jobDetail.setTargetObject(task);
jobDetail.setTargetMethod("start"); return jobDetail; }
@Bean(name = "jobTrigger") public CronTriggerFactoryBean cronJobTrigger(MethodInvokingJobDetailFactoryBean jobDetail) { CronTriggerFactoryBean tigger = new CronTriggerFactoryBean(); tigger.setJobDetail(jobDetail.getObject()); tigger.setCronExpression("0/2 * * * * ?"); tigger.setName("myTigger"); return tigger;
}
@Bean(name = "scheduler") public SchedulerFactoryBean schedulerFactory(Trigger cronJobTrigger) { SchedulerFactoryBean bean = new SchedulerFactoryBean(); bean.setOverwriteExistingJobs(true); bean.setStartupDelay(5); bean.setTriggers(cronJobTrigger); return bean; } @Bean(name = "multitaskScheduler") public SchedulerFactoryBean schedulerFactoryBean(){ SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean(); return schedulerFactoryBean; } }
|
三、应用场景
1、单任务执行,并且通过控制器的接口实现时间间隔的动态修改
1)新建一个任务SchedulerTask.java
1 2 3 4 5 6 7 8 9 10 11
| <!--三个注释都要加上--> @Configuration @Component @EnableScheduling public class SchedulerTask {
public void start() throws InterruptedException { System.out.println("活动开始!!!"+new Date()); } }
|
2)控制器执行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| @Controller public class QuartzController {
@Resource(name = "jobDetail") private JobDetail jobDetail;
@Resource(name = "scheduler") private Scheduler scheduler;
@Resource(name = "jobTrigger") private CronTrigger cronTrigger;
@ResponseBody @GetMapping("/{second}/quart") public Object quartzTest(@PathVariable("second")Integer second) throws SchedulerException { CronTrigger cron = (CronTrigger) scheduler.getTrigger(cronTrigger.getKey()); String currentCron = cron.getCronExpression(); System.err.println("当前trigger使用的-"+currentCron);
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule("0/"+second+" * * * * ?");
cron = cron.getTriggerBuilder().withIdentity(cronTrigger.getKey()) .withSchedule(scheduleBuilder).build();
scheduler.rescheduleJob(cronTrigger.getKey(),cron);
return "-这是quartz测试!"; } }
|
2、多任务场景
==Part1==
:新建多个Tast.java,也就是一开始就设定好了任务,我们假设为 伪多任务
1)新建多个任务
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| public class SchedulerJob1 implements Job { @Override public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException { System.err.println("这是第一个任务"+new Date());
} }
public class SchedulerJob2 implements Job { @Override public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException { System.err.println("这是第二个任务"+new Date()); } }
|
2)控制器
通过下面的代码就可以实现两个任务交替执行,但是我们一般的应用场景是不确定的任务和执行时间,请看下一个解决方案
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| @Controller public class QuartzController2 { @Resource(name = "multitaskScheduler") private Scheduler scheduler;
@ResponseBody @RequestMapping("task1") public Object task1() throws SchedulerException { JobDetail jobDetail = JobBuilder.newJob(SchedulerJob1.class).withIdentity("job1", "group1").build(); CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule("0/3 * * * * ?"); CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1").withSchedule(scheduleBuilder).build(); scheduler.scheduleJob(jobDetail, cronTrigger);
return "任务1"; }
@ResponseBody @RequestMapping("task2") public Object task1() throws SchedulerException { JobDetail jobDetail = JobBuilder.newJob(SchedulerJob2.class).withIdentity("job2", "group1").build(); CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule("0/6 * * * * ?"); CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity("trigger2", "group1").withSchedule(scheduleBuilder).build(); scheduler.scheduleJob(jobDetail, cronTrigger);
return "任务1"; } }
|
==Part2:==
有时候我们有新建活动之类的场景,这种场景就是活动数目不确定,活动开始时间不确定,所以我们需要用其他的方案来解决!
1 2 3 4 5
| 思路: 主要是通过逻辑代码实现任务开始时间的修改,但是必须要修改任务名称和触发器(trigger)名称的修改,确保多个任务之间名称不一致,否则会报错!
根据任务我们也可以定制使用数据库轮询的方式,确保任务的开启! 主要是为了解决服务器关起和其它因素导致任务终止!
|
1)任务类
1 2 3 4 5 6 7 8 9 10
| public class SchedulerJob2 implements Job { @Override public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
Object jobName = jobExecutionContext.getJobDetail().getKey(); System.err.println("这是"+jobName+"任务"+new Date()); } }
|
2)控制器类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| @ResponseBody @RequestMapping("task2/{jobName}") public Object task2(@PathVariable(value = "jobName") String jobName) throws SchedulerException { JobDetail jobDetail = JobBuilder .newJob(SchedulerJob2.class) .usingJobData("jobName",jobName) .withIdentity(jobName, "group1") .build();
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule("0/2 * * * * ?"); CronTrigger cronTrigger = TriggerBuilder.newTrigger() .withIdentity("trigger2"+jobName, "group1") .withSchedule(scheduleBuilder) .build();
scheduler.scheduleJob(jobDetail,cronTrigger);
return jobName; }
|
3)获取所有的在线job
1 2 3 4 5 6 7 8 9 10 11 12 13
| @ResponseBody @RequestMapping("jobs") public Object Jobs() throws SchedulerException {
Set<TriggerKey> triggerKeys = scheduler.getTriggerKeys(GroupMatcher.anyTriggerGroup());
Set<JobKey> jobKeys = scheduler.getJobKeys(GroupMatcher.anyJobGroup());
return jobKeys; }
|
job集合
`