前言
Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目,它可以与J2EE与J2SE应用程序相结合也可以单独使用。Quartz可以用来创建简单或为运行十个,百个,甚至是好几万个Jobs这样复杂的程序。Jobs可以做成标准的Java组件或 EJBs
一、添加依赖
| 12
 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的配置
| 12
 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
 
 | @Configurationpublic 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
| 12
 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)控制器执行
| 12
 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
 
 | @Controllerpublic 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)新建多个任务
| 12
 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)控制器
通过下面的代码就可以实现两个任务交替执行,但是我们一般的应用场景是不确定的任务和执行时间,请看下一个解决方案
| 12
 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
 
 | @Controllerpublic 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:==
有时候我们有新建活动之类的场景,这种场景就是活动数目不确定,活动开始时间不确定,所以我们需要用其他的方案来解决!
| 12
 3
 4
 5
 
 | 思路:主要是通过逻辑代码实现任务开始时间的修改,但是必须要修改任务名称和触发器(trigger)名称的修改,确保多个任务之间名称不一致,否则会报错!
 
 根据任务我们也可以定制使用数据库轮询的方式,确保任务的开启!
 主要是为了解决服务器关起和其它因素导致任务终止!
 
 | 
1)任务类
| 12
 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)控制器类
| 12
 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
| 12
 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集合
 `
`