Spring與Quartz使用說明 job不一樣步執行(第一個job完成後纔開始第二個job)

 

轉自:http://blog.sina.com.cn/s/blog_675e9aeb0100qghp.htmlhtml

最 近由於項目後臺須要使用一個線程去定時跑一些任務,因此看了一下Spring和Quartz的使用與集成。例如發短信、郵件。根據實際使用,此集成使用比 本身去寫線程方便和靈活,能夠不用代碼實現複雜的計劃任務,如「1月份的每週3、週五的早上9點至10點每5鍾一次任務」。因此分享一下。spring

Quartz官方網址:http://www.quartz-scheduler.org/ express

集成方法併發

集成起來比較簡單,對線程無需任何理解,Spring手冊上也有清楚的說明。只需寫一個POJO,其他的都是配置,並且若使用CronTriggerBean,能夠配置很複雜的任務調度。fetch

1.編寫一個普通的JAVA類ui

根據業務,寫一個簡單的JAVA類,和普通的類沒有區別。並配置到Spring配置文件上中。例:this

 <bean id="vcSMSProcessService" class="com.sinoprof.vc.sms.service.impl.MessageProcessServiceImpl">spa

        <property name="vcSMSLocalDAO" ref="vcSMSLocalDAO"/>線程

        <property name="vcSMSOAService" ref="vcSMSOAService"/>rest

        <property name="vcSMSConfig" ref="vcSMSConfig"/>

        <property name="vcSMSGateWayService" ref="vcSMSGateWayService"/>

    </bean>

2.使用MethodInvokingJobDetailFactoryBean創建任務

只須要配置便可,配置信息示例以下:

<bean id="jobTask" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">

        <property name="targetObject">

            <ref bean="vcSMSProcessService"/>

        </property>

        <property name="targetMethod">

            <value>sendMessages</value>

        </property>

        <property name="concurrent">

            <value>false</value>

        </property>

</bean>

 

說明:

targetObject

目標對象,即須要定時執行的POJO

targetMethod

目標方法,即須要定時執行的POJO方法

concurrent

默認狀況下,Quartz Jobs 是無狀態的,可能致使jobs之間互相的影響,若是你爲相同的JobDetail指定兩個Trigger,極可能當第一個job完成以前,第二個job就 開始了。若是Jobdetail實現了Stateful接口,就不會發生這樣的事情。第二個job將不會在第一個job完成以前開始。爲了使得jobs不 併發運行,設置concurrent標記爲false

 

3.使用CronTriggerBean創建規則,調度任務

<bean id="jobTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">

        <property name="jobDetail">

            <ref bean="jobTask"/>

        </property>

        <property name="cronExpression">

            <value>0 0/5 8-18 ? * 2-6 *</value>

        </property>

    </bean>

 

說明:

jobDetail

任務詳情,即所須要調度的任務

cronExpression

調用規則,即何時調用。詳細說明見附錄1

 

4.使用SchedulerFactoryBean包裝任務

<bean id="startQuartz" lazy-init="false" 

          class="org.springframework.scheduling.quartz.SchedulerFactoryBean">

        <property name="triggers">

            <list>

                <ref bean="jobTrigger"/>

            </list>

        </property>

        <property name="autoStartup" value="true"/>

        <property name="schedulerName" value="cronScheduler"/>

    </bean>

 

說明:

triggers

觸發器,調用哪些任務

autoStartup

是否自動啓動,該Bean被初始化後是否自動啓動定時任務。

Set whether to automatically start the scheduler after initialization. 

schedulerName

給這個計劃設定一個名稱。

Set the name of the Scheduler to fetch from the SchedulerFactory. 

 

更多使用細節能夠參考Spring文檔和Quartz文檔

附錄1:CronTrigger說明

若是須要複雜的任務計劃調度,像日曆樣式的任務,而不是簡單的時間間隔調度,須要使用CronTrigger,SimpleTrigger知足不了需求。

用CronTrigger,你能夠定義任務計劃像「每週五的中午」,或「每一個工做日的早上9:30」,甚至能夠定義「1月份的每週1、周3、週五早上9:00至10:00,每5分鐘一次」。

雖然如此,像SimpleTrigger同樣,CronTrigger仍有startTime屬性定義計劃的開始時間,endTime(可選)屬性定義計劃的停止時間。

Cron Expressions

Cron-Expressions是用來配置CronTrigger實例。Cron-Expressions是由七段子表達式組成的字符串,描述各個細節計劃。這些子字符串由空格分開,每一個子字符串表示一個域,分別爲:

1 秒

2 分

3 時

4 幾號

5 月份

6 星期幾

7 年(可選域)

例如:"0 0 12 ? * WED"-表示每週三12:00:00pm"。

其中每一個獨立的子表達式均可以用範圍或者列表表示。例如:

前例的」WED「也能夠寫成:

"MON-FRI"(範圍表示)

"MON,WED,FRI"(列表表示)

"MON-WED,SAT"(範圍加列表)

通配符(*)能夠用來表示某個子表達式域的每個可能的值。所以,「*」號用在月份裏,表示每個月。用在星期幾裏,表示一週中的天天。

每一個子表達式域都有一組有效的值,這些值都是顯然意見的。例:用0-59表示秒和分,用0到23表示小時。幾號用0-31中的任何值,可是要當心每個月的天數。月份指定的值應該是0至11,也能夠用字符串 JAN,FEB,MAR,APR,MAY,JUN,JUL,AUG,SEP,OCT,NOV和DEC表示。星期幾用1到7表示(1=星期天),或用英文字符表示:SUN,MON,TUE,WED,THU,FRI和SAT。

字 符「/」用來表示增量的值。例如:若是用「0/15」表示分,就表示從一個小時的0分開始,在這小時內每隔15分鐘一次。若是用"3/20"表示分,則表 示從一個小時的3分開始,在這小時內每隔20分鐘一次。也能夠用「3,23,43」表示。注意"*/35"並非表示每35分鐘,而是表示從一個小時的0 分開始,每隔35分鐘一次,至關於"0,35"。

「?"號容許用在幾號和星期幾的子字符串域中,用來講明沒有指定值。

「L」字 符容許用在幾號和星期幾域中,是"last"的縮寫。「L」用在幾號裏意思是這個月的最後一天,若是是1月就指31號,若是是閏年的2月就是28號。若是 用在星期幾裏,他就是表示「7」或者「SAT」(星期六)。可是若是L用在一個值的後面聯合表示星期幾域,就表示「這個月最後一個星期幾」。例 如:「6L」或「FRIL」表示這個月的最後一個星期五。一樣也能夠用一個偏移變量表示距離某個月最後一天的天數。例如:「L-3」表示某月最後一天的倒 數第三天。但用「L「字符時,不要將「L」用在列表或範圍中,那樣你會混淆或者得到不是預期的結果。

「W」用來指定某一號最近的工做日(星期一至五),例如:「15W」放在幾號裏,表示這個月15號最近的一個工做日。

「#」號用指定某月第幾個工做日,例如:「6#3」或「FRI#3」放在星期幾域中,表示這個月第三個星期五。

下面是一些表達式的樣例,你能夠從JavaDoc中找到更多的例子。

Cron Expressions示例

例1-一個表達式表示每5分鐘。

"0 0/5 * * * ?"

例2——表示每分鐘的10秒後,每5鍾一次(如:10:00:10 am,10:05:10 am,等等)

"10 0/5 * * * ?"

例3——表示運行在每一個星期三,星期五的10:30,11:30,12:30 and 13:30

"0 30 10-13 ? * WED,FRI"

例4——表示每個月的5號和20號的早8點至早10點每30分鐘一次。

"0 0/30 8-10 5,20 * ?"

注意,有些計劃調度需求若是用一個觸發器會很複雜,例如:「早9:00至10:00每5分鐘,下午1:00至10:00每20分鐘」,這種狀況下能夠是單的建立兩個觸發器同時運行一個JOB

如下是附錄的原文,有興趣能夠本身去看。

Lesson 6: CronTrigger

CronTrigger is often more useful than SimpleTrigger, if you need a job-firing schedule that recurs based on calendar-like notions, rather than on the exactly specified intervals of SimpleTrigger.

With CronTrigger, you can specify firing-schedules such as "every Friday at noon", or "every weekday and 9:30 am", or even "every 5 minutes between 9:00 am and 10:00 am on every Monday, Wednesday and Friday during January".

Even so, like SimpleTrigger, CronTrigger has a startTime which specifies when the schedule is in force, and an (optional) endTime that specifies when the schedule should be discontinued.

Cron Expressions

Cron-Expressions are used to configure instances of CronTrigger. Cron-Expressions are strings that are actually made up of seven sub-expressions, that describe individual details of the schedule. These sub-expression are separated with white-space, and represent:

1 Seconds

2 Minutes

3 Hours

4 Day-of-Month

5 Month

6 Day-of-Week

7 Year (optional field)

An example of a complete cron-expression is the string "0 0 12 ? * WED" - which means "every Wednesday at 12:00:00 pm".

Individual sub-expressions can contain ranges and/or lists. For example, the day of week field in the previous (which reads "WED") example could be replaced with "MON-FRI", "MON,WED,FRI", or even "MON-WED,SAT".

Wild-cards (the '*' character) can be used to say "every" possible value of this field. Therefore the '*' character in the "Month" field of the previous example simply means "every month". A '*' in the Day-Of-Week field would therefore obviously mean "every day of the week".

All of the fields have a set of valid values that can be specified. These values should be fairly obvious - such as the numbers 0 to 59 for seconds and minutes, and the values 0 to 23 for hours. Day-of-Month can be any value 0-31, but you need to be careful about how many days are in a given month! Months can be specified as values between 0 and 11, or by using the strings JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV and DEC. Days-of-Week can be specified as values between 1 and 7 (1 = Sunday) or by using the strings SUN, MON, TUE, WED, THU, FRI and SAT.

The '/' character can be used to specify increments to values. For example, if you put '0/15' in the Minutes field, it means 'every 15th minute of the hour, starting at minute zero'. If you used '3/20' in the Minutes field, it would mean 'every 20th minute of the hour, starting at minute three' - or in other words it is the same as specifying '3,23,43' in the Minutes field. Note the subtlety that "*/35" does not mean "every 35 minutes" - it mean "every 35th minute of the hour, starting at minute zero" - or in other words the same as specifying '0,35'.

The '?' character is allowed for the day-of-month and day-of-week fields. It is used to specify "no specific value". This is useful when you need to specify something in one of the two fields, but not the other. See the examples below (and CronTrigger JavaDoc) for clarification.

The 'L' character is allowed for the day-of-month and day-of-week fields. This character is short-hand for "last", but it has different meaning in each of the two fields. For example, the value "L" in the day-of-month field means "the last day of the month" - day 31 for January, day 28 for February on non-leap years. If used in the day-of-week field by itself, it simply means "7" or "SAT". But if used in the day-of-week field after another value, it means "the last xxx day of the month" - for example "6L" or "FRIL" both mean "the last friday of the month". You can also specify an offset from the last day of the month, such as "L-3" which would mean the third-to-last day of the calendar month. When using the 'L' option, it is important not to specify lists, or ranges of values, as you'll get confusing/unexpected results.

The 'W' is used to specify the weekday (Monday-Friday) nearest the given day. As an example, if you were to specify "15W" as the value for the day-of-month field, the meaning is: "the nearest weekday to the 15th of the month".

The '#' is used to specify "the nth" XXX weekday of the month. For example, the value of "6#3" or "FRI#3" in the day-of-week field means "the third Friday of the month".

Here are a few more examples of expressions and their meanings - you can find even more in the JavaDoc for org.quartz.CronExpression

Example Cron Expressions

CronTrigger Example 1 - an expression to create a trigger that simply fires every 5 minutes

"0 0/5 * * * ?" 

CronTrigger Example 2 - an expression to create a trigger that fires every 5 minutes, at 10 seconds after the minute (i.e. 10:00:10 am, 10:05:10 am, etc.).

"10 0/5 * * * ?" 

CronTrigger Example 3 - an expression to create a trigger that fires at 10:30, 11:30, 12:30, and 13:30, on every Wednesday and Friday.

"0 30 10-13 ? * WED,FRI" 

CronTrigger Example 4 - an expression to create a trigger that fires every half hour between the hours of 8 am and 10 am on the 5th and 20th of every month. Note that the trigger will NOT fire at 10:00 am, just at 8:00, 8:30, 9:00 and 9:30

"0 0/30 8-9 5,20 * ?" 

Note that some scheduling requirements are too complicated to express with a single trigger - such as "every 5 minutes between 9:00 am and 10:00 am, and every 20 minutes between 1:00 pm and 10:00 pm". The solution in this scenario is to simply create two triggers, and register both of them to run the same job.

Building CronTriggers

CronTrigger instances are built using TriggerBuilder (for the trigger's main properties) and CronScheduleBuilder (for the CronTrigger-specific properties). To use these builders in a DSL-style, use static imports:

import static org.quartz.TriggerBuilder.*;

import static org.quartz.CronScheduleBuilder.*;

import static org.quartz.DateBuilder.*:

Build a trigger that will fire every other minute, between 8am and 5pm, every day:

  trigger = newTrigger()

    .withIdentity("trigger3", "group1")

    .withSchedule(cronSchedule("0 0/2 8-17 * * ?"))

    .forJob("myJob", "group1")

    .build();

Build a trigger that will fire daily at 10:42 am:

  trigger = newTrigger()

    .withIdentity("trigger3", "group1")

    .withSchedule(dailyAtHourAndMinute(10, 42))

    .forJob(myJobKey)

    .build();

- or -

  trigger = newTrigger()

    .withIdentity("trigger3", "group1")

    .withSchedule(cronSchedule("0 42 10 * * ?"))

    .forJob(myJobKey)

    .build();

Build a trigger that will fire on Wednesdays at 10:42 am, in a TimeZone other than the system's default:

  trigger = newTrigger()

    .withIdentity("trigger3", "group1")

    .withSchedule(weeklyOnDayAndHourAndMinute(DateBuilder.WEDNESDAY, 10, 42))

    .forJob(myJobKey)

    .inTimeZone(TimeZone.getTimeZone("America/Los_Angeles"))

    .build();

- or -

  trigger = newTrigger()

    .withIdentity("trigger3", "group1")

    .withSchedule(cronSchedule("0 42 10 ? * WED"))

    .inTimeZone(TimeZone.getTimeZone("America/Los_Angeles"))

    .forJob(myJobKey)

    .build();

CronTrigger Misfire Instructions

The following instructions can be used to inform Quartz what it should do when a misfire occurs for CronTrigger. (Misfire situations were introduced in the More About Triggers section of this tutorial). These instructions are defined as constants on CronTrigger itself (including JavaDoc describing their behavior). The instructions include:

Misfire Instruction Constants of CronTrigger

MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY

MISFIRE_INSTRUCTION_DO_NOTHING

MISFIRE_INSTRUCTION_FIRE_NOW

All triggers also have the Trigger.MISFIRE_INSTRUCTION_SMART_POLICY instruction available for use, and this instruction is also the default for all trigger types. The 'smart policy' instruction is interpreted by CronTrigger as MISFIRE_INSTRUCTION_FIRE_NOW. The JavaDoc for the CronTrigger.updateAfterMisfire() method explains the exact details of this behavior.

When building CronTriggers, you specify the misfire instruction as part of the simple schedule (via CronSchedulerBuilder):

  trigger = newTrigger()

    .withIdentity("trigger3", "group1")

    .withSchedule(cronSchedule("0 0/2 8-17 * * ?")

        ..withMisfireHandlingInstructionFireAndProceed())

    .forJob("myJob", "group1")

    .build();

相關文章
相關標籤/搜索