Quartz学习笔记02

Quartz 学习笔记02
一、概要
    OpenSymphony提供强大的开源任务调度框架
    官网:http://www.quartz-scheduler.org

    纯Java开发

二、特点

1.强大的调度功能

Spring默认的调度框架,Quartz可以灵活的与Spring集成,实现灵活的可配置的调度功能,提供调度运行环境的持久化机制,可以保存调度线程,即使系统因故障关闭,任务调度数据并不会丢失,Timer不会做到。


2.灵活的运用方式

可灵活的定义触发器的调度事件表,并可以对触发器和任务关联映射,提供了组建式监听器,各种插件,线程池等功能,支持调度数据多种存储方式


3.分布式和集群能力



三、主要用到的设计模式
Builder模式
Factory模式
组建模式
链式写法


四、三个核心概念
调度器
任务
触发器

四、Quartz体系结构
JobDetail
任务的实现类和类的信息
trigger
触发器
SimpleTrigger
类似Timer的时间操作,例如固定频率的时间操作
CronTrigger
每周五执行任务
Scheduler调度器 (start stop pause resume)

五、重要组成

1.Job
一个接口,只有一个方法,类似TimerTask下的run方法
2.JobDetail
Quartz在每次执行Job的时候,都重新创建一个Job实例,所以不直接接受一个Job实例,相反接受一个Job实现类
3.JobBuilder
用来定义创建JobDetail的实例
4.JobStore
用来保存Job数据
5.Trigger
SimpleTrigger
CronTrigger
6.TriggerBuilder
定义或创建触发器实例
7.ThreadPool
Quartz有线程池来运行
8.Scheduler
独立运行容器
9.Calender
一个Trigger可以和多个Calender关联,以排除或包含某个时间点
10.监听器
JobListener 
TriggerListener 

schedulerListeger

六、Quartz使用

    1.准备工作

    建立Maven项目工程

    引入Quartz jar包

    2.编写一个Quartz项目

pom

    org.quartz-scheduler
    quartz
    2.2.3
public class HelloJob implements Job{
    @Override
    public void execute(JobExecutionContext arg0) throws JobExecutionException{
	//打印当前的执行时间,格式为2017-02-02 12:00:00
	SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
	System.out.println("Current Exec Time is " + sf.format(Calender.getTime()));
	//编写具体的业务逻辑
	System.out.println("Hello world");
						
	//这里可以获取到执行时候传递的参数
	}			
}
			
public class HelloScheduler{
    public static void main(String ... args){
        //创建一个JobDetail实例,将该实例与HelloJob Class绑定
        JobDetail jobDetail = JobBuilder.newJob(HelloJob.class)
        .withIdentity("myJob","group1").build();
								
        //创建一个Trigger实例,定义该Job立即执行,并且每隔两秒钟执行一次,知道永远
        Trigger trigger = TriggerBuilder.newTrigger().withIdentity("myTrigger","group1")
        .startNow().withSchedule(SimpleScheduleBuilder.simpleSchedule()
        .withIntervalInSeconds(2).repeatForever()).build();
					
        //创建Scheduler实例
        SchedulerFactory sfact = new StdSchedulerFactory();
        Scheduler scheduler = sfact.getScheduler();
        scheduler.start();
        //打印当前的执行时间,格式为2017-02-02 12:00:00
        SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        System.out.println("Current Exec Time is " + sf.format(Calender.getTime()));
        scheduler.scheduleJob(jobDetail,trigger);
    }
}

七、浅谈Job&JobDetail
    浅谈Job定义
实现业务逻辑的任务接口
    Job接口非常容易实现,只有一个execute方法,类似TimerTask的run()方法,在里面编写业务逻辑
Job接口源码
package org.quartz;
public interface Job{
public void execute(JobExecutionContext context) throws JobExecutionException;
}
Job实例在Quartz中的生命周期
每次调度器执行Job时候,它在调用execute方法前会创建一个新的Job实例,当调用完成后,关联Job对象实例会被释放,释放的实例会被垃圾回收机制回收

八、浅谈JobDetail

JobDetail为Job实例提供了许多设置属性,以及JobDataMap成员变量属性,它用来存储特定Job实例的状态信息,调度器需要借助JobDetail对象来添加Job实例。
System.out.println("jobDetail,s name:" + jobDetail.getKey().getName());
System.out.println("jobDetail,s group:" + jobDetail.getKey().getGroup());
System.out.println("jobDetail,s jobClass:" + jobDetail.getJobClass().getName());
九、重要属性
name 任务的名称
group 任务所在的组,默认值为DETAULT
jobClass 任务的实现类
jobDataMap 任务传参


十、浅谈JobExecutionContext
JobExecutionContext是什么?
当Scheduler调用一个Job,就会将JobExecutionContext传递给Job的execute()方法;
Job能通过JobExecutionContext对象访问到Quartz运行时候的环境以及Job本身的明细数据


十一、浅谈JobDataMap
JobDataMap是什么
在进行任务调度时JobDataMap存储在JobExecutionConext中,非常方便获取
JobDataMap可以用来装载任何可以序列化的数据对象,当Job实例对象被执行时这些参数对象会传递给它
JobDataMap实现了JDK的Map接口,并添加了一些非常方便的方法来存取基本数据类型
获取JobDataMap两种方式
1.从Map中直接获取
	//jobDetail中传递两个参数
	JobDetail jobDetail = JobBuilder.newJob(HelloJob.class).withIdentity("myJob")
	.usingJobData("message","hello myJob1").usingJobData("FloatJobValue",3.14F).builder();
	//Trigger中传递两个参数
	Trigger trigger = TriggerBuilder.newTrigger().withIdentity("myTrigger","group1")
			.usingJobData("message","hello myTrigger1").usingJobData("DoubleTriggerValue",2.0D).
			.startNow().withSchedule(SimpleScheduleBuilder.simpleSchedule()
			.withIntervalInSeconds(2).repeatForever()).build();
	//在HelloJob中获取JobDetail信息
	JobKey key = jobExecutionContext.getJobDetail().getKey();
	System.out.println("my job name and group are : " = key.getName() + ":" + key.getGroup());
	//在HelloJob中获取Trigger信息
	TriggerKey trkey = jobExecutionContext.getTrigger().getKey();
	System.out.println("my trigger name and group name are :" + trkey.getName() + ":" + trkey.getGroup());
	//在HelloJob中获取
	JobDataMap jobDataMap = jobExecutionContext.getJobDetail().getJobDataMap();
	JobDataMap tjobDataMap = jobExecutionContext.getTrigger().getJobDataMap();
	String jobMessage = jobDataMap.getString("mesage");
	String jobFloatValue=jobDataMap.getFloat("FloatJobValue");
	String jobDoubleValue=jobDataMap.getFloat("DoubleTriggerValue");	
其中	
    JobDataMap jobDataMap = jobExecutionContext.getJobDetail().getJobDataMap();
    JobDataMap tjobDataMap = jobExecutionContext.getTrigger().getJobDataMap();
可以修改为
    JobDataMap jobDataMap = jobExecutionContext.getMergedJobDataMap();
但是注意如果JobDetail和Trigger有同名的key,Trigger会覆盖JobDetail中同名的key

2.Job实现类中添加setter方法对应的JobDataMap的键值(Quartz框架默认的JobFactory实现类在初始化Job实例对象时会自动的调用这些setter方法)
在HelloJob类中添加
private String message;
private Float FloatJobValue;
private Double DoubleTriggerValue;
//省略getter\setter方法
十二、浅谈Trigger
Trigger是什么
Quartz中的触发器用来告诉调度程序作业什么时候粗发,即Trigger对象时用来触发执行Job的。
触发器通用属性
JobKey
表示Job实例的标识,触发器被触发时,该指定的Job实例会执行
StartTime
触发器的事件表首次被触发的时间。它的值类型是java.util.Date.
EndTime
指定触发器不再被触发的时间,他的类型是java.util.Date

public class HelloJob implements Job{
    @Override
    public void execute(JobExecutionContext arg0) throws JobExecutionException{
        //打印当前的执行时间,格式为2017-02-02 12:00:00
        SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        System.out.println("Current Exec Time is " + sf.format(Calender.getTime()));
					
        Trigger currentTrigger = arg0.getTrigger();
        System.out.println("startTime is " + currentTrigger.getStartTime());
        System.out.println("endTime is " + currentTrigger.getEndTime());
        JobKey jobKey = currentTrigger.getJobKey();
        System.out.println("job key info ---" + "jobName:"+jobKey.getName() +"jobGroup:" + jobKey.getGroup());
    }
				
}
			
public class HelloScheduler{
    public static void main(String ... args){
        //创建一个JobDetail实例,将该实例与HelloJob Class绑定
        JobDetail jobDetail = JobBuilder.newJob(HelloJob.class)
	.withIdentity("myJob","group1").build();
					
        Date date = new Date();
        SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
					
        date.setTime(date.getTime() + 3000);
					
        Date endDate = new Date();
        endDate.setTime(date.getTime() + 6000);
        //创建一个Trigger实例,获取距离当前时间3秒后的时间
        //距离当前时间6秒后停止执行
        Trigger trigger = TriggerBuilder.newTrigger().withIdentity("myTrigger","group1")
        .startAt(date).endAt(endDate).withSchedule(SimpleScheduleBuilder.simpleSchedule()
        .withIntervalInSeconds(2).repeatForever()).build();
					
        //创建Scheduler实例
        SchedulerFactory sfact = new StdSchedulerFactory();
        Scheduler scheduler = sfact.getScheduler();
        scheduler.start();
        //打印当前的执行时间,格式为2017-02-02 12:00:00
        SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        System.out.println("Current Exec Time is " + sf.format(Calender.getTime()));
        scheduler.scheduleJob(jobDetail,trigger);
	}
}
十三、SimpleTrigger
作用
在一个指定时间段内执行一次作业任务或是在执行的时间间隔内多次执行作业任务

public class HelloJob implements Job{
    @Override
    public void execute(JobExecutionContext arg0) throws JobExecutionException{
        //打印当前的执行时间,格式为2017-02-02 12:00:00
        SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        System.out.println("Current Exec Time is " + sf.format(Calender.getTime()));
        //编写具体的业务逻辑
        System.out.println("Hello world");
    }
}
			
public class HelloScheduler{
    public static void main(String ... args){
        //创建一个JobDetail实例,将该实例与HelloJob Class绑定
        JobDetail jobDetail = JobBuilder.newJob(HelloJob.class)
        .withIdentity("myJob","group1").build();
					
        //获取距离4秒钟之后的具体时间
        Date date = new Date();
        date.setTime(date.getTime()+4000L);
        //距离当前时间4秒钟执行,之后每隔两秒钟重复执行一次任务
        Date endDate = new Date();
        endDate.setTime(endDate.getTime() + 6000L);
        SimpleTrigger trigger = (SimpleTrigger)TriggerBuilder.newTrigger().withIdentity("myTrigger","group1")
        .startAt(date).withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(2).withRepeatCount(1))
        .endAt(endDate).withSchedule(SimpleScheduleBuilder.simpleSchedule().repeatForever()).build();
					
        //创建Scheduler实例
        SchedulerFactory sfact = new StdSchedulerFactory();
        Scheduler scheduler = sfact.getScheduler();
        scheduler.start();
        //打印当前的执行时间,格式为2017-02-02 12:00:00
        SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        System.out.println("Current Exec Time is " + sf.format(Calender.getTime()));
        scheduler.scheduleJob(jobDetail,trigger);
	    }
}
			
需要注意
    重复次数可以为0,正整数或是SimpleTrigger.REPEAT_INDEFINITELY常量值
    重复执行间隔必须为0或长整数
    一旦被指定了endTime参数,name他会覆盖重复次数参数效果

十四、CronTrigger
作用
基于日历的作业调度器
而不是像SimpleTrigger那样精确指定间隔时间,比SimpleTrigger更常用。
Cron表达式
用于配置CronTrigger实例
是由7个子表达式组成的字符串,描述了时间表的详细信息。
格式:[秒] [分] [小时] [日] [月] [周] [年]
public class HelloJob implements Job{
    @Override
    public void execute(JobExecutionContext arg0) throws JobExecutionException{
        //打印当前的执行时间,格式为2017-02-02 12:00:00
        SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        System.out.println("Current Exec Time is " + sf.format(Calender.getTime()));
        //编写具体的业务逻辑
        System.out.println("Hello world");
    }				
}
			
public class HelloScheduler{
    public static void main(String ... args){
        //创建一个JobDetail实例,将该实例与HelloJob Class绑定
        JobDetail jobDetail = JobBuilder.newJob(HelloJob.class)
        .withIdentity("myJob","group1").build();
					
        //每秒钟触发一次任务
					
        //创建一个Trigger实例,定义该Job立即执行,并且每隔两秒钟执行一次,知道永远
        CronTrigger trigger = (CronTrigger)TriggerBuilder.newTrigger().withIdentity("myTrigger","group1")
        .startNow().withSchedule(CronScheduleBuilder.cronSchedule(* * * * * ?*));
        .withIntervalInSeconds(2).repeatForever()).build();
					
        //创建Scheduler实例
        SchedulerFactory sfact = new StdSchedulerFactory();
        Scheduler scheduler = sfact.getScheduler();
        scheduler.start();
        //打印当前的执行时间,格式为2017-02-02 12:00:00
        SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        System.out.println("Current Exec Time is " + sf.format(Calender.getTime()));
        scheduler.scheduleJob(jobDetail,trigger);
    }
}	


Quartz学习笔记02_第1张图片,  表示 或 

- 表示 至

* 表示 每

/ 表示 每

?表示 不关心 也可以用*

      


0 0 10,14,16  *  *  ? 每天上午10点,下午2点,4点

0 0/30 9-17 * * ? 朝九晚五工作时间内每半小时

0 0 12 ? * WED  表示每个星期三中午12点

0 0 12 * * ? 每天12点触发 

0 15 10 ? * * 每天10点15分触发 
0 15 10 * * ? 每天10点15分触发 
0 15 10 * * ? * 每天10点15分触发 
0 15 10 * * ? 2005 2005年每天10点15分触发 
0 * 14 * * ? 每天下午的 2点到2点59分每分触发 
0 0/5 14 * * ? 每天下午的 2点到2点59分(整点开始,每隔5分触发) 
0 0/5 14,18 * * ? 每天下午的 2点到2点59分、18点到18点59分(整点开始,每隔5分触发) 
0 0-5 14 * * ? 每天下午的 2点到2点05分每分触发 
0 10,44 14 ? 3 WED 3月每周三下午的 2点10分和2点44分触发 
0 15 10 ? * MON-FRI 从周一到周五每天上午的10点15分触发 
0 15 10 15 * ? 每月15号上午10点15分触发 
0 15 10 L * ? 每月最后一天的10点15分触发 
0 15 10 ? * 6L 每月最后一周的星期五的10点15分触发 
0 15 10 ? * 6L 2002-2005 从2002年到2005年每月最后一周的星期五的10点15分触发 
0 15 10 ? * 6#3 每月的第三周的星期五开始触发 
0 0 12 1/5 * ? 每月的第一个中午开始每隔5天触发一次 
0 11 11 11 11 ? 每年的11月11号 11点11分触发(光棍节)

Quartz学习笔记02_第2张图片

十五、浅谈Scheduler
Scheduler-工厂模式
所有的Scheduler实例应该由SchedulerFactory来创建
SchedulerFactory
StdSchedulerFactory
DirectSchedulerFactory
回顾Quartz三个核心概念
调度器
任务
触发器
Scheduler创建方式
SchedulerFactory sfact = new StdSchedulerFactory();
Scheduler scheduler = sfact.getScheduler();

DirectSchedulerFactory factory = DirectSchedulerFactory.getInstance();
Scheduler scheduler = factory.getScheduler();
StdSchedulerFactory
使用一组参数(java.util.Properties)来创建和初始化Quartz调度器
配置参数一般存储在quartz.properties中
调用getScheduler方法就能创建和初始化调度器对象
Scheduler主要函数
Date scheduleJob(JobDetail jobDetail,Trigger trigger)
void start()
void standby() scheduler暂时挂起
void shutdown()
十六、quartz.properties
文档的位置和加载顺序
默认加载工程下的quartz.properties文件,如果工程中没有就去读quartz jar包里面的quartz.properties文件里面内容
组成部分
调度器属性
org.quartz.scheduler.instanceName属性用来去区分特定的调度器实例,可以按照功能用途来给调度器起名。
org.quartz.scheduler.instanceId属性和前者一样,也允许任何字符串,单这个值必须是在所有调度器实例中是唯一的,
尤其是在一个集群当中,作为集群的唯一key. 假如你想Quartz帮你生成这个值得话,可以设置为AUTO
线程池属性
threadCount 决定有多少个线程,至少为1,多数机器上值高于100就很不适用了。没有默认值,必须设置值
threadPriority 线程优先级,最大值10 最小值为1,正常值为5(默认值)
org.quartz.treadPool.class
作业存储设置
描述了在调度器实例的生命周期中,Job和Trigger信息是如何存储的
插件配置
满足特定需求用到的Quartz插件配置
十七、使用Quartz配置作业
两种方式
MethodInvokingJobDetailFactoryBean
调用myBean的printMessage方法
Quartz学习笔记02_第3张图片

                        MyBean

                        Quartz学习笔记02_第4张图片    

               

   JobDetailFactoryBean

  dispatcher-servlet.xml




	
	
	
	
	
	
	
	
		
			
				
					
						
							text/html;charset=UTF-8
						
					
				
			
		
	
	
	
	
	

	
	
	
	
		
		
		
		
		
	

	
		
		
	

	
		
		
			
				
			
		
						
	
	
	
	    
	    
	    
	
	
	
	
	    
	    
	
	
	
	    
	        
	            
	            
	        
	    
	    
	        
	            
	            
	        
	    
	
  
package com.imooc.springquartz.quartz;

import org.springframework.stereotype.Component;

@Component("anotherBean")
public class AnotherBean {
	public void printAnotherMessage() {
		System.out.println("AnotherMessage");
	}
}
package com.imooc.springquartz.quartz;

import java.text.SimpleDateFormat;
import java.util.Date;

import org.springframework.stereotype.Component;

@Component("myBean")
public class MyBean {
	public void printMessage() {
		// 打印当前的执行时间,格式为2017-01-01 00:00:00
		Date date = new Date();
		SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		System.out.println("MyBean Executes!" + sf.format(date));
	}
}
package com.imooc.springquartz.quartz;

import java.text.SimpleDateFormat;
import java.util.Date;

import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.scheduling.quartz.QuartzJobBean;

public class FirstScheduledJob extends QuartzJobBean{
     private AnotherBean anotherBean;
     
     public void setAnotherBean(AnotherBean anotherBean){
    	 this.anotherBean = anotherBean;
     }

	@Override
	protected void executeInternal(JobExecutionContext arg0)
			throws JobExecutionException {
		Date date = new Date();
		SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		System.out.println("FirstScheduledJob Executes!" + sf.format(date));
		this.anotherBean.printAnotherMessage();		
	}
}



你可能感兴趣的:(Quartz)