·使用MyEclipse开发Struts框架的Hello World!(录像1)
·linux下Tomcat 5.0.20 与 Apache 2 安装/集成/配置
·在win2003下整合了整合Tomcat5.5+ apache_2.0.53+ mod_jk_2.0.47.dll
·Jsp 连接 mySQL、Oracle 数据库备忘(Windows平台)
·ASP、JSP、PHP 三种技术比较
·AWT GUI 设计笔记(二)

第十一天 Spring的进步

作者:未知 来源:月光软件站 加入时间:2005-2-28 月光软件站






18.2. Using the OpenSymphony Quartz Scheduler

Quartz uses Triggers, Jobs and JobDetail ro realize scheduling of all kinds of jobs. For the basic concepts behind Quartz, have a look at For convenience purposes, Spring offers a couple of classes that simplify usage of Quartz within Spring-based applications.

18.2.1. Using the JobDetailBean

JobDetail objects contain all information needed to run a job. Spring provides a so-called JobDetailBean that makes the JobDetail more of an actual with sensible defaults. Let's have a look at an example:

<bean name="exampleJob" class="org.springframework.scheduling.quartz.JobDetailBean">
  <property name="jobClass">
  <property name="jobDataAsMap">
      <entry key="timeout"><value>5</value></entry>

The job detail bean has all information it needs to run the job (ExampleJob). The timeout is specified as the job data map. The job data map is available through the JobExecutionContext (passed to you at execution time), but the JobDetailBean also maps the properties from the job data map to properties of the actual job. So in this case, if the ExampleJob contains a property named timeout, the JobDetailBean will automatically apply it:

package example;

public class ExampleJob extends QuartzJobBean {

  private int timeout;
   * Setter called after the ExampleJob is instantiated
   * with the value from the JobDetailBean (5)
  public void setTimeout(int timeout) {
    this.timeout = timeout;
  protected void executeInternal(JobExecutionContext ctx)
  throws JobExecutionException {
      // do the actual work

All additional settings from the job detail bean are by the way available to you as well.

Note: Using the name and group properties, you can modify in which group the job runs and using what name. By default the name of the job equals the bean name of the job detail bean (in the example above this is exampleJob).

18.2.2. Using the MethodInvokingJobDetailFactoryBean

Often times, you just need to invoke a method on a specific object. Using the MethodInvokingJobDetailFactoryBean you can do exactly this:

<bean id="methodInvokingJobDetail" 
    <property name="targetObject"><ref bean="exampleBusinessObject"/></property>
    <property name="targetMethod"><value>doIt</value></property>

The above example will result in the doIt being called on the exampleBusinessObject (see below):

public class BusinessObject {
  // properties and collaborators
  public void doIt() {
    // do the actual work

<bean id="exampleBusinessObject" class="examples.ExampleBusinessObject"/>

Using the MethodInvokingJobDetailFactoryBean you don't need to create one-line jobs that just invoke a method, and you only need to create the actual business object and wire up the detail object.

By default, Quartz Jobs are stateless, resulting in the possibility of jobs interfering with eachother. If you specify two triggers for the same JobDetail, it might be possible that before the first job has finished, the second one will start. If JobDetail objects implement the Stateful interface, this won't happen. The second job will not start before the first one has finished. To make jobs resulting from the MethodInvokingJobDetailFactoryBEan non-concurrent set the concurrent flag to false.

<bean id="methodInvokingJobDetail" 
    <property name="targetObject"><ref bean="exampleBusinessObject"/></property>
    <property name="targetMethod"><value>doIt</value></property>

Note: By default, jobs will run in a concurrent fashion.

18.2.3. Wiring up jobs using triggers and the SchedulerFactoryBean

We've created job details, jobs and we've reviewed the convenience bean that allows to you invoke a method on a specific object. Of course we still need to schedule the jobs themselves. This is done using triggers and a SchedulerFactoryBean. Several triggers are available within Quartz. Spring offers two subclassed triggers, the CronTriggerBean and the SimpleTriggerBean.

Triggers need to be scheduled. Spring offers a SchedulerFactoryBean exposing properties to set te triggers. The SchedulerFactoryBean schedules the actual triggers.

A couple of examples:

<bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">
  <property name="jobDetail">
    <!-- see the example of method invoking job above -->    
    <ref bean="methodInvokingJobDetail"/>
  <property name="startDelay">
    <!-- 10 seconds -->
  <property name="repeatInterval">
    <!-- repeat every 50 seconds -->

<bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
  <property name="jobDetail">
    <ref bean="exampleJob"/>
  <property name="cronExpression">
    <!-- run every morning at 6 am -->
    <value>0 6 * * 1</value>

Ok, now we've set up two triggers, one running every 50 seconds with a starting delay of 10 seconds and one every morning at 6. To finalize everything we need to set up the SchedulerFactoryBean:

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

More properties are available for the SchedulerFactoryBean for you to set, such as the Calendars used by the job details, properties to customize Quartz with, etcetera. Have a look at the JavaDOC ( for more information.

Cron Expressions 如下:

CronTrigger Expressions


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









An example of a complete cron-expression is the string "0 0 12 ? * WED" - which means "every Wednesday at 12: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 replaces 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 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 vaules 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 15 minutes, starting at minute zero'. If you used '3/20' in the Minutes field, it would mean 'every 20 minutes during the hour, starting at minute three' - or in other words it is the same as specifying '3,23,43' in the Minutes field.


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". When using the 'L' option, it is important not to specify lists, or ranges of values, as you'll get confusing results.


Here are a few more examples of expressions and their meanings - you can find even more in the JavaDOC for CronTrigger


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.