<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    posts - 75,comments - 83,trackbacks - 0

    Spring 中正確使用 Quartz CronExpression

    ???? Quartz 作為企業級任務調度框架以其靈活的使用方式、強大的功能已經得到廣泛應用,作為一向喜歡將業內流行的工具納入支持的 Spring 自然已經內置 了對 Quartz 的支持,使得 Quartz 中最常使用的 SimpleTrigger CronTrigger 的使用得到了最大簡化,分別對應 Spring org.springframework.scheduling.quartz.SimpleTriggerBean org.springframework.scheduling.quartz.CronTriggerBean ,這兩個類用起來非常方便,其中 SimpleTrigger 更類似于 JDK 中的 Timer ,它只是簡單的以某個時間間隔來執行某個任務而已,比較簡陋,而 CronTrigger 功能則十 分強大,可以設定制定任務在任意指定時刻內調用,其使用 Unix 中的 Cron Expression 來制定調度策略,十分靈活,不過 Cron Expression 可能需要用點時間來學習,不過一旦掌握會覺得真的很不錯,掌握了這兩種 Trigger 基本上就可以應付實現大多數 J2EE 應用中的時 間任務調度服務了。

    ???? 下面舉一個簡單例子說明一下在 Spring1.2.5 中使用 Quartz1.5 的方式(所需要的包在 Spring1.2.5 的發行版中的 lib 目錄下可以找到,將其拷貝到工程的類路徑中)。

    ???? 首先建立兩個要調度的任務,他們都必須繼承自 org.springframework.scheduling.quartz.QuartzJobBean ,而業務邏輯都是放在 executeInternal 方法中,指定的任務邏輯實現之后,需要將其注入到一個 JobDetailBean 中, JobDetailBean 可以看作 為一個具體任務的設置它指定了要執行的任務和執行任務的時間策略, JobDetailBean 不用實現,只需要在 Spring 的配置文件中設置便可:

    package com.peuo.albumSys.scheduling;

    import java.util.Iterator;
    import java.util.List;
    import java.util.Set;

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

    import org.apache.log4j.Logger;

    import com.peuo.albumSys.business.IAlbumSysService;
    import com.peuo.albumSys.domainobj.User;
    import com.peuo.albumSys.domainobj.Album;

    /**
    *
    在指定的時刻查詢當前所有的用戶,并顯示其姓名。
    * @author Shippo Field
    */
    public class ScheduledQueryUsers extends QuartzJobBean {
    ???? private static Logger log = Logger.getLogger(ScheduledQueryUsers.class);
    ????
    ???? private IAlbumSysService service = null;

    ???? /**
    ????? * @param service
    要設置的業務邏輯 Bean 實例,可以是已被納入事務管理的某個 Bean ,這樣以來 QuartzJobBean 內部邏輯也可以納入事務管理。
    ????? */
    ???? public void setService(IAlbumSysService service) {
    ???????? this.service = service;
    ???? }
    ????
    ???? /*
    (非 Javadoc
    ????? * @see org.springframework.scheduling.quartz.QuartzJobBean#executeInternal(org.quartz.JobExecutionContext)
    ????? */
    ???? protected void executeInternal(JobExecutionContext ctx)
    ???????????? throws JobExecutionException {
    ???????? log.debug("Now entering method executeInternal()...");
    ???????? List users = service.findAllUser();
    ???????? StringBuffer str = new StringBuffer();
    ???????? for(int i = 0; i < users.size(); i++){
    ???????????? User user = (User)users.get(i);
    ???????????? str.append("\nUser[" + i + "] = " + user.getUserName());
    ???????????? Set albums = user.getAlbumSet();
    ???????????? Iterator it = albums.iterator();
    ???????????? str.append("(Albums:");
    ???????????? while(it.hasNext()){
    ???????????????? str.append(((Album)it.next()).getAlbumName()).append(";");
    ???????????? }
    ???????? }
    ???????? log.debug(str.toString());
    ???? }

    }

    ??

    package com.peuo.albumSys.scheduling;

    import java.util.Date;

    import org.quartz.JobExecutionContext;
    import org.quartz.JobExecutionException;

    import org.springframework.scheduling.quartz.QuartzJobBean;

    import org.apache.log4j.Logger;

    import com.peuo.albumSys.business.IAlbumSysService;
    import com.peuo.albumSys.domainobj.Album;
    import com.peuo.albumSys.domainobj.Photo;

    /**
    *
    本程序會在指定的時刻插入照片
    * @author Field
    */
    public class ScheduledAddPhoto extends QuartzJobBean {
    ???? private static Logger log = Logger.getLogger(ScheduledAddPhoto.class);
    ????
    ???? private IAlbumSysService service = null;
    ???? private static int count = 0;
    ???? /*
    (非 Javadoc
    ????? * @see org.springframework.scheduling.quartz.QuartzJobBean#executeInternal(org.quartz.JobExecutionContext)
    ????? */
    ???? protected void executeInternal(JobExecutionContext arg0)
    ???????????? throws JobExecutionException {
    ???????? Date now = new Date(System.currentTimeMillis());
    ???????? Photo newPhoto = new Photo();
    ???????? newPhoto.setAlbum(new Album(new Integer(1)));
    ???????? newPhoto.setPhotoName( now.toString());
    ???????? newPhoto.setPhotoUrl("Photo url" + ++count);
    ???????? service.addPhoto(newPhoto);
    ???????? log.debug("New photo added : name =" + newPhoto.getPhotoName() +"; url = " + newPhoto.getPhotoUrl());
    ???? }

    ???? /**
    ????? * @return
    當前業務邏輯實例。
    ????? */
    ???? public IAlbumSysService getService() {
    ???????? return service;
    ???? }
    ???? /**
    ????? * @param service
    要設置的業務邏輯實例。
    ????? */
    ???? public void setService(IAlbumSysService service) {
    ???????? this.service = service;
    ???? }
    }
    然后在Spring的配置文件中分別設置一個SimpleTriggerBeanCronTriggerBean來調用上面兩個任務,配置如下:

    ?

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "
    http://www.springframework.org/dtd/spring-beans.dtd ">

    <beans>

    ……………………………………………………………………………………………………

    ??? <bean id="queryUserJob" class="org.springframework.scheduling.quartz.JobDetailBean">
    ???? <property name="jobClass">
    ????? <value>com.peuo.albumSys.scheduling.ScheduledQueryUsers</value>
    ???? </property>
    ???? <property name="jobDataAsMap">
    ????? <map>
    ?????? <entry key="service">
    ??????? <ref local="albumSysService"/>
    ???? </entry>
    ????? </map>
    ???? </property>

    ??? </bean>
    ???
    ??? <bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">
    ???? <property name="jobDetail">
    ????? <ref local="queryUserJob"/>
    ???? </property>
    ???? <property name="startDelay">
    ????? <value>15000</value>
    ???? </property>
    ???? <property name="repeatInterval">
    ????? <value>60000</value>
    ???? </property>
    ???? <property name="repeatCount">
    ????? <value>-1</value>
    ???? </property>
    ??? </bean>
    ???
    <bean id="addPhotoJob" class="org.springframework.scheduling.quartz.JobDetailBean">
    ?? <property name="jobClass">
    ??? <value>com.peuo.albumSys.scheduling.ScheduledAddPhoto</value>
    ?? </property>
    <property name="jobDataAsMap">
    ??? <map>
    ???? <entry key="service">
    ????? <ref local="albumSysService" />
    ???? </entry>
    ??? </map>
    ?? </property>
    </bean>

    <bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
    ?? <property name="jobDetail">
    ??? <ref local="addPhotoJob"/>
    ?? </property>
    ?? <property name="cronExpression">
    ??? <value>0 20 19 * * ?</value>
    ?? </property>
    </bean>

    ??? <bean id="sfb" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
    ???? <property name="triggers">
    ????? <list>
    ?????? <ref local="simpleTrigger"/>
    ???? <ref local="cronTrigger"/>
    ????? </list>
    ???? </property>
    ??? </bean>

    ??

    上面紅色標出的部分可以看出, Spring 對于將 QuartzJob 注入 JobDetailBean 的方式有點特殊,你需要將要注入給 QuartzJob 的某個屬性注入到 JobDetailBean jobDataAsMap 中, 這不同于 Spring 平時直接對某個 Bean 的屬性直接注入的方式,這主要是因為 Quartz 執行一個任務( JOB 或者叫作業)的時候會提供給任務一個 JobExecutionContext 的任務執行上下文,從這個上下文中可以獲得 Job 的環境設置,具體的可以看一下 Quartz API 文檔就明白 了,反正只要記住這里的注入方式比較特殊就行了。

    以上配置文件分別設置了一個 SimpleTriggerBean CronTriggerBean ,前者將會在程序執行 15 秒之后開始不斷以間隔一 分鐘的方式不斷查詢當前用戶信息并顯示出來,后者則指定每天的 19 20 分執行向 ID 1 的用戶的相冊內添加一張照片的任務,其 Cron Expression 0 20 19 * * ?

    從以上可以看出, Spring 大大簡化了對 Quartz 任務時間調度框架的使用,將其完美的融合入了 Spring 提供的 IoC 容器,只是其注入方式需要注意,還有就是 Cron Expression 一定要掌握,這個是 Quartz 真正的強大之處。

    ??

    網上似乎對 Cron 表達式的中文介紹相當少,我干脆就把 Quartz 中的 doc 翻譯一下,各位需要的朋友可以快速了解一下大致用法:

    一個 Cron- 表達式是一個由六至七個字段組成由空格分隔的字符串,其中 6 個字段是必須的而一個是可選的,如下:

    字段名

    ??

    允許的值

    ??

    允許的特殊字符

    ??

    0-59

    ??

    , - * /

    ??

    0-59

    ??

    , - * /

    小時

    ??

    0-23

    ??

    , - * /

    ??

    1-31

    ??

    , - * ? / L W C

    ??

    1-12 or JAN-DEC

    ??

    , - * /

    周幾

    ??

    1-7 or SUN-SAT

    ??

    , - * ? / L C #

    ( 可選字段 )

    ??

    empty, 1970-2099

    ??

    , - * /

    '*' 字符可以用于所有字段,在 字段中設為 "*" 表示 " 每一分鐘 " 的含義。

    '?' 字符可以用在 周幾 字段 . 它用來指定 ' 不明確的值 '. 這在你需要指定這兩個字段中的某一個值而不是另外一個的時候會被用到。在后面的例子中可以看到其含義。

    '-' 字符被用來指定一個值的范圍,比如在 小時 字段中設為 "10-12" 表示 "10 點到 12 ".

    ',' 字符指定數個值。比如在 周幾 字段中設為 "MON,WED,FRI" 表示 "the days Monday, Wednesday, and Friday".

    '/' 字符用來指定一個值的的增加幅度 . 比如在 字段中設置為 "0/15" 表示 " 0, 15, 30, 45 " 。而 "5/15" 則表示 " 5, 20, 35, 50". '/' 前加 "*" 字符相當于指定從 0 秒開始 . 每個字段都有一系列可以開始或結束的數值。對于 字段來說,其數值范圍為 0 59 ,對于 小時 字段來說其為 0 23, 對于 字段來說為 0 31, 而對于 字段來說為 1 12 "/" 字段僅僅只是幫助你在允許的數值范圍內從開始 " n" 的值。 因此 對于 字段來說 "7/6" 只是表示 7 月被開啟而不是 每六個月 ”, 請注意其中微妙的差別。

    'L' 字符可用在 周幾 這兩個字段。它是 "last" 的縮寫 , 但是在這兩個字段中有不同的含義。例如 ,“ 字段中的 "L" 表示 " 一個月中的最后一天 " —— 對于一月就是 31 號對于二月來說就是 28 號(非閏年)。而在 周幾 字段中 , 它簡單的表示 "7" or "SAT" ,但是如果在 周幾 字段中使用時跟在某個數字之后 , 它表示 " 該月最后一個星期 ×" —— 比如 "6L" 表示 " 該月最后一個周五 " 。當使用 'L' 選項時 , 指定確定的列表或者范圍非常重要,否則你會被結果搞糊涂的。

    'W' 可用于 字段。用來指定歷給定日期最近的工作日 ( 周一到周五 ) 。比如你將 字段設為 "15W" ,意為 : " 離該月 15 號最近的工作日 " 。因此如果 15 號為周六,觸發器會在 14 號即周五調用。如果 15 號為周日 , 觸發器會在 16 號也就是周一觸發。如果 15 號為周二 , 那么當天就會觸發。然而如果你將 字段設為 "1W", 而一號又是周六 , 觸發器會于下周一也就是當月的 3 號觸發 , 因為它不會越過當月的值的范圍邊界。 'W' 字符只能用于 字段的值為單獨的一天而不是一系列值的時候。

    'L' 'W' 可以組合用于 字段表示為 'LW' ,意為 " 該月最后一個工作日 "

    '#' 字符可用于 周幾 字段。該字符表示 該月第幾個周 ×” ,比如 "6#3" 表示該月第三個周五 ( 6 表示周五而 "#3" 該月第三個 ) 。再比如 : "2#1" = 表示該月第一個周一而 "4#5" = 該月第五個周三。注意如果你指定 "#5" 該月沒有第五個 ×” ,該月是不會觸發的。

    'C' 字符可用于 周幾 字段,它是 "calendar" 的縮寫。 它表示為基于相關的日歷所計算出的值(如果有的話)。如果沒有關聯的日歷 , 那它等同于包含全部日歷。 字段值為 "5C" 表示 " 日歷中的第一天或者 5 號以后 " 周幾 字段值為 "1C" 則表示 " 日歷中的第一天或者周日以后 "

    對于 月份 字段和 周幾 字段來說合法的字符都不是大小寫敏感的。

    下面是一些完整的例子 :

    表達式

    ??

    含義

    "0 0 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 55 分結束每 5 分鐘一次觸發

    "0 0/5 14,18 * * ?"

    ??

    每天的下午 2 點至 2 55 6 點至 6 55 分兩個時間段內每 5 分鐘一次觸發

    "0 0-5 14 * * ?"

    ??

    每天 14:00 14:05 每分鐘一次觸發

    "0 10,44 14 ? 3 WED"

    ??

    三月的每周三的 14 10 14 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"

    ??

    每月最后一個周五的 10 15 觸發

    "0 15 10 ? * 6L 2002-2005"

    ??

    2002 年至 2005 年的每月最后一個周五的 10 15 觸發

    "0 15 10 ? * 6#3"

    ??

    每月的第三個周五的 10 15 觸發

    請注意 '?' '*' 周幾 字段中的用法 !
    posted on 2009-12-24 13:12 梓楓 閱讀(2993) 評論(0)  編輯  收藏 所屬分類: spring

    只有注冊用戶登錄后才能發表評論。


    網站導航:
     
    主站蜘蛛池模板: 青青青视频免费观看| 亚洲人成网77777色在线播放| jjizz全部免费看片| 18女人水真多免费高清毛片| 日韩精品无码一区二区三区免费| 日本免费中文字幕| 鲁大师在线影院免费观看 | 久久久久亚洲Av片无码v| 在线精品亚洲一区二区三区| 亚洲色偷拍另类无码专区| 亚洲日韩欧洲乱码AV夜夜摸| 亚洲精品狼友在线播放| 亚洲欧洲日韩不卡| 亚洲噜噜噜噜噜影院在线播放| 亚洲AV无码精品蜜桃| 亚洲熟妇成人精品一区| 精品韩国亚洲av无码不卡区| av成人免费电影| 最近免费中文字幕MV在线视频3| 国产精品区免费视频| 亚洲视频在线观看免费视频| 国产成人免费高清激情视频| 国产成人啪精品视频免费网| 亚洲一级特黄大片在线观看| 亚洲国产另类久久久精品黑人| 久久久久久久亚洲Av无码| jlzzjlzz亚洲jzjzjz| 最新亚洲人成无码网站| 久久精品成人免费观看97| 无码av免费一区二区三区试看| 国产成人免费在线| 无码国模国产在线观看免费 | 99免费观看视频| 好先生在线观看免费播放| 亚洲av再在线观看| 亚洲乱码中文字幕久久孕妇黑人| 亚洲综合色一区二区三区小说| 亚洲AV无码一区二区三区牲色| 国产特黄一级一片免费| 免费观看激色视频网站bd| 免费真实播放国产乱子伦|