zoukankan      html  css  js  c++  java
  • 对quartz的总结

    Quartz 是一个强大的企业级 Schedule 工具,也是目前最好的开源 Schedule 工具。Spring中也集成了quartz的应用,下面就讲一下如何在spring中使用quartz。

    spring的配置:

    xml 代码
    1. <bean id="schedulerFactoryBean" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">  
    2.  <property name="triggers">  
    3.   <list>  
    4.    <ref bean="simpleTrigger"/>  
    5.    <ref bean="cornTrigger"/>  
    6.   </list>  
    7.  </property>  
    8. </bean>  
    9. <bean id="schedulerControl" class="com.pheh.scheduler.Schedule">  
    10.  <property name="scheduler">  
    11.   <ref bean="schedulerFactoryBean"/>  
    12.  </property>  
    13. </bean>  
    14.   
    15. <bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">  
    16.  <property name="jobDetail">  
    17.   <ref bean="methodInvokingJobDetail"/>  
    18.  </property>  
    19.  <property name="startDelay">  
    20.   <value>1000</value>  
    21.  </property>  
    22.  <property name="repeatInterval">  
    23.   <value>3000</value>  
    24.  </property>  
    25. </bean>  
    26. <bean id="cornTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">  
    27.  <property name="jobDetail">  
    28.   <ref bean="methodInvokingJobDetail"/>  
    29.  </property>  
    30.  <property name="cronExpression">  
    31.   <value>0 0 */1 * * ?</value>  
    32.  </property>  
    33. </bean>  
    34.   

     

    Job:
    org.quartz.Job是一个接口,只定义了void execute(JobExecutionContext context)throws JobExecutionException;一个方法。当定时任务被触发后,系统会自动调用实现了该接口的方法。在spring中,org.springframework.scheduling.quartz.QuartzJobBean对其进行了封装,使用了Template Method模式。主要是为了在使用jobDataMap时更加方便。QuartzJobBean有两个方法,
    public final void execute(JobExecutionContext context) throws JobExecutionException
    Job接口中定义的,spring在该方法里进行了些处理,将jobDataMap中的值注入到该Job的实现者中

    protected abstract void executeInternal(JobExecutionContext context) throws JobExecutionException
    这是一个抽象方法,用户在扩展了QuartzJobBean后,要自己实现该方法,在其中添加相应的业务逻辑

    JobDetail:
    JobDetail描述了一个任务具体的信息。在Spring中,JobDetailBean对JobDetail进行了封装(继承了JobDetail)。
    private String name;//名称
    private String group = Scheduler.DEFAULT_GROUP;//组
    private String description;//描述
    private Class jobClass;//定时任务触发时,回调的class,该class要实现Job接口或继承QuartzJobBean
    private JobDataMap jobDataMap;//该任务存储的数据,在回调的时候也可以使用
    private boolean volatility = false;//是否持久化到org.quartz.spi.JobStore中
    private boolean durability = false;//当该任务完成后,是否还在JobStore中继续保留该任务
    private boolean shouldRecover = false;//当系统重新启动后,是否再次执行该任务
    对于jobDataMap,它是是一个封装过的Map,使用方法同Map,如
    jobDetailBean.getJobDataMap().put(target,value);
    如果使用了QuartzJobBean,在使用jobDetailBean时,可将target的值设成QuartzJobBean的子类的属性名称,这样,在定时触发时,spring会自动将与target对应的value值注入到QuartzJobBean的子类中去。如。

    java 代码
    1. ...   
    2. public class ReminderManager extends QuartzJobBean{   
    3.  private String reminderStr = "";   
    4. }   
    5. ...   
    6. jobDetailBean.getJobDataMap().put(reminderStr,"abcdefg");   
    7. ...  


    这样当该任务被触发后,在ReminderManager中,reminderStr的值就会被注入为"abcdefg"。

    Trigger:
    trigger就是触发器。Quartz有个很好的想法就是分离了任务和任务执行的条件。Trigger就是控制任务执行条件的类,当Trigger认为执行条件满足的时刻,Trigger会通知相关的Job去执行。分离的好处是:
    1.你可以为某个Job关联多个Trigger,其中任何一个条件满足都可以触发job执行,这样可以完成一些组合的高级触发条件
    2.当Trigger失效后(比如:一个永远都不能满足的条件),你不必去声明一个新的job,代替的是你可以为job关联一个新的Trigger让job可以继续执行。
    目前的Quartz实现中,存在两种Trigger,SimpleTrigger和CronTrigger,在spring中分别用SimpleTriggerBean和CronTriggerBean对其进行封装。SimpleTrigger是简单触发器,如从某日到某日,每个一定时间进行一次提醒,在这段时间内进行多少次提醒;CronTrigger是复杂触发器,用来执行calendar-like的任务,可设定一些复杂的触发规则,如每年的x月的第y个星期五,或是每个星期天的几点进行提醒。后面附加一个日常语义与cronTrigger的转化

    Trigger
    private String name;//名称
    private String group = Scheduler.DEFAULT_GROUP;//组
    private String jobName;//所关联的jobDetail的名称
    private String jobGroup = Scheduler.DEFAULT_GROUP;//所关联的jobDetail的组
    private String description;//描述
    private JobDataMap jobDataMap;//该触发器存储的数据,在回调的时候也可以使用
    private boolean volatility = false;//是否持久化到org.quartz.spi.JobStore中

    SimpleTrigger
    private Date startTime = null;//开始日期
    private Date endTime = null;//结束日期
    private Date nextFireTime = null;//下次的触发时间
    private Date previousFireTime = null;//上次的触发时间
    private int repeatCount = 0;//重复次数
    private long repeatInterval = 0;//重复间隔
    private int timesTriggered = 0;/已触发的次数

    SimpleTriggerBean
    private JobDetail jobDetail;//所关联的JobDetail,方便在配置文件中使用

    CornTrigger
    private CronExpression cronEx = null;//触发条件表达式,它有一个String型的setter
    private Date startTime = null;//开始日期
    private Date endTime = null;//结束日期
    private Date nextFireTime = null;//下次的触发时间
    private Date previousFireTime = null;//上次的触发时间
    private transient TimeZone timeZone = null;//所在时区

    CronTriggerBean
    private JobDetail jobDetail;//所关联的JobDetail,方便在配置文件中使用

    Scheduler的常用方法
    添加一个定时任务:
    Date scheduleJob(JobDetail jobDetail,Trigger trigger)

    修改一个定时任务,主要是更改trigger:
    Date rescheduleJob(String triggerName, String groupName, Trigger newTrigger)

    删除一个定时任务,同时也会将于该jobDetail关联的trigger一并删除:
    boolean deleteJob(String jobName,String jobGroup)

    取得所有的jobDetail组
    String[] getJobGroupNames() 

    取得某个group下的所有的jobDetail
    String[] getJobNames(String groupName)

    取得指定的jobDetail
    JobDetail getJobDetail(String jobName, String jobGroup)

    取得指定的jobDetail的所有的Trigger
    Trigger[] getTriggersOfJob(String jobName, String groupName)

    取得指定的Trigger
    Trigger getTrigger(String triggerName, String triggerGroup)

    Quartz的存储:
    Quartz默认的是使用RAM存储所有的信息,但是这样的话,当我们重启服务器后,之前的所有的定时任务就全消失了。为了让服务器重启以后,我们的定时任务仍不丢失,我们可采用数据库持久化定时任务。
    首先要先建立数据库,在quartz-1.6.0\docs\dbTables下,选择自己使用的数据库的sql脚本,建立相应的数据库表。
    在WEB-INF下加一个quartz.properties。我们可以在 quartz-1.6.0\examples\example10 中找到该文件的样例

     

    org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX #表明使用JDBC进行持久化
    org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
    org.quartz.jobStore.useProperties = false
    org.quartz.jobStore.dataSource = myDS
    org.quartz.jobStore.tablePrefix = QRTZ_     #该值尽量不要改动,如改动,还要相应的修改sql脚本
    org.quartz.jobStore.isClustered = false

    org.quartz.dataSource.myDS.driver = net.sourceforge.jtds.jdbc.Driver
    org.quartz.dataSource.myDS.URL = jdbc:jtds:sqlserver://192.168.1.101:1433/Northwind;autoReconnect=true
    org.quartz.dataSource.myDS.user = sa
    org.quartz.dataSource.myDS.password =
    org.quartz.dataSource.myDS.maxConnections = 5


    日常语义与cronTrigger的转化,以下setter,getter省略

     

    java 代码
    1. public class TDateRange{   
    2.  private int startType = 2;//开始类型。默认的使用2表示使用开始日期   
    3.  private Date startDate = new Date();//开始日期   
    4.  private int endType = 0;//结束类型。0表示无结束时间;1表示重复n次后结束;2表示使用结束日期   
    5.  private Date endDate = new Date();//结束日期   
    6.  private int occurrences;//执行次数   
    7. }   
    8. public class TFrequency{   
    9.  //0:无重复提醒   
    10.  //1:每every   
    11.  //2:每个工作日detail=1,2,3,4,5   
    12.  //3:每every周后的星期detail日   
    13.  //4:每every月的detail日   
    14.  //5:每every月的第num1个星期num2   
    15.  //6:每年num1月num2日   
    16.  //7:每年every月的第num1个月的星期num2   
    17.  private int type = 0;//频率类型   
    18.  private int every = 0;   
    19.  private String detail = "";   
    20.  private String num1 = "";   
    21.  private String num2 = "";   
    22. }   
    23.   
    24. private String formatQuartzString(){   
    25.  String quartzStr = "";   
    26.  tiggernote="";   
    27.  //秒 分 时    
    28.  quartzStr = "0 "+this.dateRange.getStartDate().getMinutes()+" "+this.dateRange.getStartDate().getHours()+" ";   
    29.  switch(this.frequency.getType()){   
    30.  case 0://无重复提醒   
    31.   quartzStr += this.dateRange.getStartDate().getDate()+" "+(this.dateRange.getStartDate().getMonth()+1)+" ? "+(this.dateRange.getStartDate().getYear()+1900);   
    32.   tiggernote+="起始时间:"+quartzStr;   
    33.   break;   
    34.  case 1://每XX天提醒   
    35.   quartzStr += "*/"+this.frequency.getEvery()+" * ? ";   
    36.   tiggernote+="每"+this.frequency.getEvery()+"提醒";   
    37.   break;   
    38.  case 2://每个工作日detail=1,2,3,4,5   
    39.   //quartzStr += "? * 2-6";   
    40.   quartzStr ="0 */1 * * * ?"; //测试   
    41.   tiggernote+="每个工作日1,2,3,4,5提醒";   
    42.   break;   
    43.  case 3://每every周后的星期detail日   
    44.   quartzStr += "? * "+this.frequency.getDetail()+"/"+this.frequency.getEvery();   
    45.   tiggernote+="每"+this.frequency.getEvery()+"周星期"+this.frequency.getDetail()+"日";   
    46.   break;   
    47.  case 4://每every个月的detail日   
    48.   quartzStr += this.frequency.getDetail()+" */"+this.frequency.getEvery()+" ?";   
    49.   tiggernote+="每"+this.frequency.getEvery()+"月"+this.frequency.getDetail()+"日";   
    50.   break;   
    51.  case 5://每every个月的第num1个星期num2   
    52.   quartzStr += "? */"+this.frequency.getEvery()+" "+this.frequency.getNum2();   
    53.   //星期   
    54.   if(Integer.valueOf(this.frequency.getNum1()).intValue()>0){   
    55.    quartzStr += "#"+this.frequency.getNum1();   
    56.    tiggernote+="每"+this.frequency.getEvery()+"月第"+this.frequency.getNum1()+"个星期"+this.frequency.getNum2()+"日";   
    57.   }else{   
    58.    quartzStr += "L";   
    59.    tiggernote+="每"+this.frequency.getEvery()+"月星期"+this.frequency.getNum2();   
    60.   }   
    61.   break;   
    62.  case 6://每年num1月num2日   
    63.   quartzStr += this.frequency.getNum2()+" "+this.frequency.getNum1()+" ?";   
    64.   tiggernote+="每年"+this.frequency.getNum1()+"月"+this.frequency.getNum2()+"日";   
    65.   break;   
    66.  case 7://每年every月的第num1个星期num2   
    67.   quartzStr += "? "+this.getFrequency().getEvery()+" "+this.getFrequency().getNum2();   
    68.   //星期   
    69.   if(Integer.valueOf(this.frequency.getNum1()).intValue()>0){   
    70.    quartzStr += "#"+this.frequency.getNum1();   
    71.    tiggernote+="每年"+this.getFrequency().getEvery()+"月的第"+this.frequency.getNum1()+"个星期"+this.getFrequency().getNum2()+"日";   
    72.   }else{    
    73.    quartzStr += "L";   
    74.    tiggernote+="每年"+this.getFrequency().getEvery()+"月的"+this.getFrequency().getNum2()+"日";   
    75.   }    
    76.   break;   
    77.  default :   
    78.  }   
    79.  log.debug("quartzStr="+quartzStr);   
    80.  return quartzStr;   
    81. }   
    Scheduler:
    Scheduler 是一个计划集,其中可以包含多个 JobDetail 和 Trigger 组成的计划任务。
    在Quartz中,我们可以通过
    SchedulerFactory scheduleFactory = new StdSchedulerFactory();
    Scheduler scheduler = scheduleFactory.getScheduler();
    来取得scheduler,通过调用scheduler.start()来启动quartz。
    在spring中,org.springframework.scheduling.quartz.SchedulerFactoryBean是对Quartz的org.quartz.Scheduler的封装,通过上面的配置,在spring启动的时候,quartz就会跟随着启动,不需要再用scheduler.start()来启动。在spring中,如果要取得scheduler,可通过上面的配置文件那样,将SchedulerFactoryBean注入到schdeuler中。

     ------------------------------------------另一文章--------------------------------------------------------------

     

    org.quartz.Scheduler 来控制任务

    scheduler.start();     //开始任务
    scheduler.shutdown();  //终止任务

    你在SchedulerFactoryBean里面不配置触发器
    然后在你要触发的事件里配置一个scheduler不就可以了吗

    Scheduler sch = (Scheduler) context.getBean("...");
    sch.scheduleJob(newJob..., newTrigger...);

  • 相关阅读:
    JUnit测试框架使用
    Android开发环境搭建与SD card
    深入Java泛型(Java泛型擦除机制,使用泛型强转时机,擦除对复写影响,协变返回类型)
    DHTML5(控件动态效果综合应用与表单校验)
    DHTML4(select与checkbox应用)
    DHTML3(表格动态创建,删除行/列,表格行排序,行颜色交替高亮显示)
    DHTML2(window对象,下拉列表)
    DHTML1(节点操作)
    JavaScript_语法,语句,函数,对象
    Html/CSS2_了解CSS
  • 原文地址:https://www.cnblogs.com/chenying99/p/2798364.html
Copyright © 2011-2022 走看看