• Quartz


      Quartz是一个完全由Java编写的开源作业调度框架,为在Java应用程序中进行作业调度提供了简单却强大的机制。Quartz允许开发人员根据时间间隔来调度作业。它实现了作业和触发器的多对多的关系,还能把多个作业与不同的触发器关联。简单地创建一个org.quarz.Job接口的Java类,Job接口包含唯一的方法:
    1     public void execute(JobExecutionContext context) throws JobExecutionException;
      在Job接口实现类里面,添加需要的逻辑到execute()方法中。配置好Job实现类并设定好调度时间表,Quartz就会自动在设定的时间调度作业执行execute()。
      整合了Quartz的应用程序可以重用不同事件的作业,还可以为一个事件组合多个作业。Quartz通过属性文件来配置JDBC事务的数据源、全局作业、触发器侦听器、插件、线程池等等。
    • Hello,Quartz
      配置环境:
      1. 下载Quartz
      2. 阅读Readme.txt,了解每个jar包的作用,将quartz.jar包和lib/下的几个jar包、以及相关依赖的jar包放在工程的classpath中 
      先来看一个简单的Quartz应用,让它每隔5s打印"Hello, Quartz",打印10次。
      代码清单1:创建任务
     1 import java.util.Date;
     2 import org.quartz.Job;
     3 import org.quartz.JobExecutionContext;
     4 import org.quartz.JobExecutionException;
     5 
     6 public class HelloQuartzJob implements Job {
     7 
     8     public void execute(JobExecutionContext context) 
     9             throws JobExecutionException {
    10         System.out.println("Hello, Quartz! - executing its JOB at "+ 
    11             new Date() + " by " + context.getTrigger().getName());
    12     }
    13 }

      为了调度此任务执行,需要先得到一个Schedule实例,然后创建一个包含任务信息的JobDetail,最后创建一个Trigger管理任务的执行。

      代码清单2:调度任务

     1 import java.sql.Date; 
     2 import org.quartz.JobDetail;
     3 import org.quartz.Scheduler;
     4 import org.quartz.SchedulerException;
     5 import org.quartz.SchedulerFactory;
     6 import org.quartz.SimpleTrigger;
     7 import org.quartz.impl.StdSchedulerFactory;
     8 
     9 
    10 public class HelloQuartzScheduling {
    11 
    12     public static void main(String[] args)throws SchedulerException {
    13 
    14         SchedulerFactory schedulerFactory = new StdSchedulerFactory();
    15         Scheduler scheduler = schedulerFactory.getScheduler();
    16 
    17         JobDetail jobDetail = new JobDetail("helloQuartzJob", 
    18                 Scheduler.DEFAULT_GROUP, HelloQuartzJob.class);
    19 
    20         SimpleTrigger simpleTrigger = new SimpleTrigger("simpleTrigger", 
    21                 Scheduler.DEFAULT_GROUP);
    22 
    23         simpleTrigger.setStartTime(new Date(System.currentTimeMillis()));
    24         simpleTrigger.setRepeatInterval(5000);
    25         simpleTrigger.setRepeatCount(10);
    26 
    27         scheduler.scheduleJob(jobDetail, simpleTrigger);
    28 
    29         scheduler.start();
    30     }
    31 
    32 }
      Job接口包含唯一方法execute(),将任务逻辑添加到该方法中。StdSchedulerFactory.getScheduler()返回一个可运行的实例,然后创建调度任务的JobDetail实例,并传递3个参数给构造方法。第一个参数是任务名,用于引用该任务。第二个参数是任务组名,这里使用默认名,任务组名用于引用集合起来的一组任务,如可以使用Scheduler.pauseJobGroup()来暂停一组任务,每个组中的任务名是唯一的。第三个参数是实现特定任务的类。创建JobDetail实例后,需要创建一个Trigger,这里使用的是SimpleTrigger类,它提供了JDK Timer风格的触发器行为。传递给SimpleTrigger构造方法的两个参数分别是触发器名和任务组名,触发器名在它所在的任务组中必须是唯一的。接下来是设置触发器的一些属性,setStartTime()是设置启动时间,setRepeatInterval()是设置重复间隔,setRepeatCount()是设置重复次数。最后,scheduler.start()启动调度,终止调度可以用stop()方法。
    • CronTrigger类
      Quartz有两大触发器,除了上面使用的SimpleTrigger外,就是CronTrigger。CronTrigger能够提供复杂的触发器表达式的支持。CronTrigger是基于Unix Cron守护进程,它是一个调度程序,支持简单而强大的触发器语法。
      使用CronTrigger主要的是要掌握Cron表达式。Cron表达式包含6个必要组件和一个可选组件,如下表所示。

    位置

    含义

    允许的特殊字符

    1

    秒(0~59)

    , -  *  /

    2

    分(0~59)

    , -  *  /

    3

    小时(0~24)

    , -  *  /

    4

    日期(1~31)

    , -  *  /  ?  L  W  C

    5

    月(JAN~DEC或1~12)

    , -  *  /

    6

    星期(SUN~SAT或1~7)

    , -  *  /  ?  L  C  #

    7

    年(可选,1970~2099),若为空,表示全部时间范围

    , -  *  /

      特殊字符的含义,见下表。
     

    特殊字符

    说明

    *

    通配符,任意值

    ?

    无特定值。通常和其他指定的值一起使用,表示必须显示该值但不能检查

    -

    范围。e.g.小时部分10-12表示10:00,11:00, 12:00

    ,

    列分隔符。可以让你指定一系列的值。e.g.在星期域中指定MON、TUE和WED

    /

    增量。表示一个值的增量,e.g.分钟域中0/1表示从0开始,每次增加1min

    L

    表示Last。它在日期和星期域中表示有所不同。在日期域中,表示这个月的最后一天,而在星期域中,它永远是7(星期六)。当你希望使用星期中某一天时,L字符非常有用。e.g.星期域中6L表示每一个月的最后一个星期五

    W

    在本月内离当天最近的工作日触发,所谓的最近工作日,即当天到工作日的前后最短距离,如果当天即为工作日,则距离是0;所谓本月内指的是不能跨月取到最近工作日,即使前/后月份的最后一天/第一天确实满足最近工作日。e.g. LW表示本月的最后一个工作日触发,W强烈依赖月份。

    #

    表示该月的第几个星期,e.g. 1#2表示每一个月的第一个星期一

    C

    日历值。日期值是根据一个给定的日历计算出来的。在日期域中给定一个20C将在20日(日历包括20日)或20日后日历中包含的第一天(不包括20日)激活触发器。例如在一个星期域中使用6C表示日历中星期五(日历包括星期五)或者第一天(日历不包括星期五)

     
      Cron表达式举例:
    "30 * * * * ?" 每半分钟触发任务
    "30 10 * * * ?" 每小时的10分30秒触发任务
    "30 10 1 * * ?" 每天1点10分30秒触发任务
    "30 10 1 20 * ?" 每月20号1点10分30秒触发任务
    "30 10 1 20 10 ? *" 每年10月20号1点10分30秒触发任务
    "30 10 1 20 10 ? 2011" 2011年10月20号1点10分30秒触发任务
    "30 10 1 ? 10 * 2011" 2011年10月每天1点10分30秒触发任务
    "30 10 1 ? 10 SUN 2011" 2011年10月每周日1点10分30秒触发任务
    "15,30,45 * * * * ?" 每15秒,30秒,45秒时触发任务
    "15-45 * * * * ?" 15到45秒内,每秒都触发任务
    "15/5 * * * * ?" 每分钟的每15秒开始触发,每隔5秒触发一次
    "15-30/5 * * * * ?" 每分钟的15秒到30秒之间开始触发,每隔5秒触发一次
    "0 0/3 * * * ?" 每小时的第0分0秒开始,每三分钟触发一次
    "0 15 10 ? * MON-FRI" 星期一到星期五的10点15分0秒触发任务
    "0 15 10 L * ?" 每个月最后一天的10点15分0秒触发任务
    "0 15 10 LW * ?" 每个月最后一个工作日的10点15分0秒触发任务
    "0 15 10 ? * 5L" 每个月最后一个星期四的10点15分0秒触发任务
    "0 15 10 ? * 5#3" 每个月第三周的星期四的10点15分0秒触发任务
     
      将上面HelloQuartz例子中SimpleTrigger换成CronTrigger,代码如下。
      代码清单3:CronTrigger调度器
      将上面HelloQuartz例子中SimpleTrigger换成CronTrigger,代码如下。
     1 import java.text.ParseException;
     2 import org.quartz.CronTrigger;
     3 import org.quartz.JobDetail;
     4 import org.quartz.Scheduler;
     5 import org.quartz.SchedulerException;
     6 import org.quartz.SchedulerFactory;
     7 import org.quartz.impl.StdSchedulerFactory;
     8 
     9 public class HelloQuartzScheduling {
    10 
    11     public static void main(String[] args) 
    12         throws SchedulerException, ParseException {
    13 
    14         SchedulerFactory schedulerFactory = new StdSchedulerFactory();
    15         Scheduler scheduler = schedulerFactory.getScheduler();
    16 
    17         JobDetail jobDetail = new JobDetail("helloQuartzJob", 
    18                 Scheduler.DEFAULT_GROUP, HelloQuartzJob.class);
    19 
    20         String cronExpression = "30/5 * * * * ?"; // 每分钟的30s起,每5s触发任务        
    21         CronTrigger cronTrigger = new CronTrigger("cronTrigger", 
    22                 Scheduler.DEFAULT_GROUP, cronExpression);
    23 
    24         scheduler.scheduleJob(jobDetail, cronTrigger);
    25 
    26         scheduler.start();
    27     }
    28 
    29 }

      CronTrigger使用HolidayCalendar类可以排除某一段时间,比如说国庆节不执行调度任务,代码示例如下:

     1 import java.text.ParseException;
     2 import java.util.Calendar;
     3 import org.quartz.CronTrigger;
     4 import org.quartz.JobDetail;
     5 import org.quartz.Scheduler;
     6 import org.quartz.SchedulerException;
     7 import org.quartz.SchedulerFactory;
     8 import org.quartz.impl.StdSchedulerFactory;
     9 import org.quartz.impl.calendar.HolidayCalendar;
    10 
    11 
    12 public class HelloQuartzScheduling {
    13 
    14     public static void main(String[] args) 
    15         throws SchedulerException, ParseException {
    16 
    17         SchedulerFactory schedulerFactory = new StdSchedulerFactory();
    18         Scheduler scheduler = schedulerFactory.getScheduler();
    19 
    20         JobDetail jobDetail = new JobDetail("helloQuartzJob", 
    21                 Scheduler.DEFAULT_GROUP, HelloQuartzJob.class);
    22 
    23         Calendar cal = Calendar.getInstance();
    24         cal.set(2012, Calendar.OCTOBER, 1); // 国庆节
    25 
    26         HolidayCalendar holidayCal = new HolidayCalendar();
    27         holidayCal.addExcludedDate(cal.getTime()); // 排除该日期
    28 
    29         // addCalendar(String calName, Calendar calendar, 
    30         //             boolean replace, boolean updateTriggers)
    31         scheduler.addCalendar("calendar", holidayCal, true, false);
    32 
    33         String cronExpression = "30/5 * * * * ?"; // 每5s触发任务        
    34         CronTrigger cronTrigger = new CronTrigger("cronTrigger", 
    35                 Scheduler.DEFAULT_GROUP, cronExpression);
    36 
    37         cronTrigger.setCalendarName("calendar");
    38 
    39         scheduler.scheduleJob(jobDetail, cronTrigger);
    40 
    41         scheduler.start();
    42     }
    43 
    44 }  

      JobStore: 任务持久化

      Quartz支持任务持久化,这可以让你在运行时增加任务或者对现存的任务进行修改,并为后续任务的执行持久化这些变更和增加的部分。中心概念是JobStore接口。默认的是RAMJobStore。
     
      初窥Quartz - 紫龍劍 - 倚天万里须长剑
      配置文件
      上述没有用到任何的配置文件。Quartz支持配置文件,它的好处是比编写代码简单,且修改后不需要重新编译源码。
     
      配置quartz.properties特性文件
      quartz.properties文件定义了Quartz应用运行时行为,还包含了许多能控制Quartz运转的属性。它应放在工程的classpath中。
      代码清单5:quartz.properties
     1 #============================================================================  
     2 # Configure Main Scheduler Properties  
     3 #============================================================================
     4 
     5 # 实例名
     6 org.quartz.scheduler.instanceName = QuartzScheduler 
     7 # 实例ID
     8 org.quartz.scheduler.instanceId = AUTO
     9 
    10 #============================================================================
    11 # Configure ThreadPool  
    12 #============================================================================
    13 org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
    14 # 线程个数
    15 org.quartz.threadPool.threadCount = 3
    16 org.quartz.threadPool.threadPriority = 5
    17 
    18 #============================================================================
    19 # Configure JobStore  
    20 #============================================================================
    21 org.quartz.jobStore.misfireThreshold = 60000
    22 org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore
    23 
    24 #============================================================================
    25 # Configure Plugins 
    26 #============================================================================
    27 org.quartz.plugin.triggHistory.class = org.quartz.plugins.history.LoggingJobHistoryPlugin
    28 # org.quartz.plugins.xml.JobInitializationPlugin是Quartz自带的插件,
    29 # 默认时,这个插件会在 classpath 中搜索名为 quartz_jobs.xml 
    30 # 的文件并从中加载 Job 和 Trigger 信息
    31 # v1.8之前用JobInitializationPlugin
    32 #org.quartz.plugin.jobInitializer.class = org.quartz.plugins.xml.JobInitializationPlugin
    33 org.quartz.plugin.jobInitializer.class = org.quartz.plugins.xml.XMLSchedulingDataProcessorPlugin
    34 org.quartz.plugin.jobInitializer.fileNames = quartz_jobs.xml
    35 org.quartz.plugin.jobInitializer.failOnFileNotFound = true
    36 org.quartz.plugin.jobInitializer.scanInterval =10
    37 org.quartz.plugin.jobInitializer.wrapInUserTransaction = false
    38 
    39 # 关闭quartz新版本检测功能
    40 org.quartz.scheduler.skipUpdateCheck = true

      quartz从版本1.8开始,配置文件有所改动,以前quartz自带的插件是JobInitializationPlugin,而1.8中是XMLSchedulingDataProcessorPlugin. xml。

      代码清单6:quartz_jobs.xml格式 

      1 <?xmlversion="1.0"encoding="UTF-8"?> 
      2 <job-scheduling-dataxmlns="http://www.quartz-scheduler.org/xml/JobSchedulingData" 
      3    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
      4    xsi:schemaLocation="http://www.quartz-scheduler.org/xml/JobSchedulingData http://www.quartz-scheduler.ogr/xml/job_scheduling_data_1_8.xsd" 
      5    version="1.8"> 
      6    <pre-processing-commands> 
      7        <!--在执行作业和触犯器之前执行的命令--> 
      8        <delete-jobs-in-group>*</delete-jobs-in-group> 
      9        <!--删除标示组中的所有作业,如果是“*”,则删除所有组中的作业,同时也会删除与作业有关的触犯器 --> 
     10        <delete-triggers-in-group>*</delete-triggers-in-group> 
     11        <!--删除标示组中的所有触犯器,如果是“*”,则删除所有组中的触发器 --> 
     12        <delete-job> 
     13            <!--删除指定的作业,同时也会删除与它关联的触犯器 --> 
     14            <name></name> 
     15            <group></group> 
     16        </delete-job> 
     17        <delete-trigger> 
     18            <!--删除指定的触犯器 --> 
     19            <name></name> 
     20            <group></group> 
     21        </delete-trigger> 
     22    </pre-processing-commands> 
     23  
     24    <processing-directives> 
     25        <!--在计划作业和触发器是应遵循的命令和原则 --> 
     26        <overwrite-existing-data>true or false</overwrite-existing-data> 
     27        <!--是否复写已经存在的任务计划数据,如果为false并且ingore-duplicates非false,那么文件中同名的触发器或作业将会继续存在,则会产生错误--> 
     28        <ignore-duplicates>true or false</ignore-duplicates> 
     29        <!--如果为true,计划中的任何同名的作业/触发器将会被忽略,不会产生错误--> 
     30    </processing-directives> 
     31  
     32    <schedule> 
     33        <job> 
     34            <name>JobName</name> 
     35            <group>JobGroup</group> 
     36            <description></description> 
     37            <job-class></job-class> 
     38            <job-listener-ref></job-listener-ref> 
     39            <!-- volatility,durability,recover必须按顺序设定 --> 
     40            <volatility></volatility> 
     41            <durability></durability> 
     42            <recover></recover> 
     43            <job-data-map> 
     44                <!-- entry可以设定多个--> 
     45                <entry> 
     46                    <key></key> 
     47                    <value></value> 
     48                </entry> 
     49            </job-data-map> 
     50        </job> 
     51        <trigger> 
     52            <!-- Trigger分为simple,cron,date-interval三种类型,一个trigger中只能指定一种类型--> 
     53            <simple> 
     54                <name></name> 
     55                <group></group> 
     56                <description></description> 
     57                <job-name></job-name> 
     58                <job-group></job-group> 
     59                <calendar-name></calendar-name> 
     60                <volatility></volatility> 
     61                <job-data-map> 
     62                    <entry> 
     63                        <key></key> 
     64                        <value></value> 
     65                    </entry> 
     66                </job-data-map> 
     67                <start-time></start-time> 
     68                <end-time></end-time> 
     69                <misfire-instruction></misfire-instruction> 
     70                <repeat-count></repeat-count> 
     71                <repeat-interval></repeat-interval> 
     72            </simple> 
     73            <cron> 
     74                <name></name> 
     75                <group></group> 
     76                <description></description> 
     77                <job-name></job-name> 
     78                <job-group></job-group> 
     79                <calendar-name></calendar-name> 
     80                <volatility></volatility> 
     81                <job-data-map> 
     82                    <entry> 
     83                        <key></key> 
     84                        <value></value> 
     85                    </entry> 
     86                </job-data-map> 
     87                <start-time></start-time> 
     88                <end-time></end-time> 
     89                <misfire-instruction></misfire-instruction> 
     90                <cron-expression></cron-expression> 
     91                <time-zone></time-zone> 
     92            </cron> 
     93            <date-interval> 
     94                <name></name> 
     95                <group></group> 
     96                <description></description> 
     97                <job-name></job-name> 
     98                <job-group></job-group> 
     99                <calendar-name></calendar-name> 
    100                <volatility></volatility> 
    101                <job-data-map> 
    102                    <entry> 
    103                        <key></key> 
    104                        <value></value> 
    105                    </entry> 
    106                </job-data-map> 
    107                <start-time></start-time> 
    108                <end-time></end-time> 
    109                <misfire-instruction></misfire-instruction> 
    110                <repeat-interval></repeat-interval> 
    111                <repeat-interval-unit></repeat-interval-unit> 
    112            </date-interval> 
    113        </trigger> 
    114    </schedule> 
    115 </job-scheduling-data>

      代码清单7:quartz_jobs.xml示例

     1 <?xmlversion="1.0"encoding="UTF-8"?>  
     2 <job-scheduling-dataxmlns="http://www.quartz-scheduler.org/xml/JobSchedulingData" 
     3    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     4    xsi:schemaLocation="http://www.quartz-scheduler.org/xml/JobSchedulingData http://www.quartz-scheduler.org/xml/job_scheduling_data_1_8.xsd" 
     5    version="1.8">  
     6       
     7    <pre-processing-commands>  
     8        <delete-jobs-in-group>*</delete-jobs-in-group> <!-- clear all jobs in scheduler -->  
     9        <delete-triggers-in-group>*</delete-triggers-in-group><!-- clear all triggers in scheduler -->  
    10    </pre-processing-commands>  
    11       
    12    <processing-directives>  
    13        <overwrite-existing-data>true</overwrite-existing-data>  
    14        <ignore-duplicates>false</ignore-duplicates>   
    15    </processing-directives>  
    16       
    17    <schedule>  
    18        <job>  
    19            <name>helloQuartzJob</name>  
    20            <group>DEFAULT</group>  
    21            <description>简单的quartz使用</description>  
    22            <job-class>HelloQuartzJob</job-class>  
    23            <volatility>false</volatility>  
    24            <durability>true</durability>  
    25            <recover>false</recover>  
    26        </job>  
    27        <trigger>  
    28        <cron>
    29                 <name>trigger</name>     
    30               <group>DEFAULT</group>     
    31               <job-name>helloQuartzJob</job-name>     
    32               <job-group>DEFAULT</job-group> 
    33              <cron-expression>30/5 * * * * ?</cron-expression>
    34        </cron>   
    35        </trigger>
    36    </schedule>      
    37 </job-scheduling-data>

      代码清单8:Quartz任务调度

     1 public class HelloQuartzScheduling {
     2     
     3     public static void main(String[] args) 
     4        throws SchedulerException, ParseException {
     5        
     6        SchedulerFactory schedulerFactory = new StdSchedulerFactory();
     7        Scheduler scheduler = schedulerFactory.getScheduler();
     8        
     9        scheduler.start();              
    10     }   
    11 }

      spring中的?的特殊用处:

      1、如官方文档解释的那样,问号(?)的作用是指明该字段‘没有特定的值’;

      2、星号(*)和其它值,比如数字,都是给该字段指明特定的值,只不过用星号(*)代表所有可能值;

      3、cronExpression对日期和星期字段的处理规则是它们必须互斥,即只能且必须有一个字段有特定的值,另一个字段必须是‘没有特定的值’;

      4、问号(?)就是用来对日期和星期字段做互斥的。

  • 相关阅读:
    监听浏览器使用不同版本js并且处理ie兼容getElementByClassName
    超出字数部分省略(主要解决不兼容;display: -webkit-box;的浏览器)
    highcharts图表
    整理前端css/js/jq常见问题及解决方法(1)
    [转载]移动页面所需meta元素和Viewport窗口知识点
    在ie和chrome浏览器中滚动条样式的设置
    关于:before :after
    mysql备份与还原
    使用xkbeancomparator对比javabean,生成操作记录
    SSO单点登录和CAS
  • 原文地址:https://www.cnblogs.com/lcngu/p/6126355.html
Copyright © 2020-2023  润新知