今天学习了quartz的第4例子,实现StatefulJob或者QuartzJobBean的job均是无状态的,每次触发器调用job都是new一个新的job,所以为了存储job的状态需要利用 JobDataMap data = context.getJobDetail().getJobDataMap();来完成,例子如下:
ColorJob.java:
package quartz.example.example4;
import java.util.Date;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.StatefulJob;
public class ColorJob implements StatefulJob {
public static final String FAVORITE_COLOR = "favorite color";
public static final String EXECUTION_COUNT = "count";
private int _counter = 1;
public ColorJob() {
}
public void execute(JobExecutionContext context)
throws JobExecutionException {
String jobName = context.getJobDetail().getFullName();
JobDataMap data = context.getJobDetail().getJobDataMap();
String favoriteColor = data.getString(FAVORITE_COLOR);
int count = data.getInt(EXECUTION_COUNT);
System.out.println("ColorJob: " + jobName + " executing at " + new Date() + "\n" +
" favorite color is " + favoriteColor + "\n" +
" execution count (from job map) is " + count + "\n" +
" execution count (from job member variable) is " + _counter);
count++;
data.put(EXECUTION_COUNT, count);
_counter++;
}
}
JobStateExample.java:
package quartz.example.example4;
import java.util.Date;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SimpleTrigger;
import org.quartz.TriggerUtils;
public class JobStateExample {
public ApplicationContext app;
public Scheduler sched;
public void run() throws Exception {
System.out.println("------- Initializing -------------------");
System.out.println("------- Initialization Complete --------");
System.out.println("------- Scheduling Jobs ----------------");
long ts = TriggerUtils.getNextGivenSecondDate(null, 10).getTime();
JobDetail job1 = new JobDetail("job1", "group1", ColorJob.class);
SimpleTrigger trigger1 = new SimpleTrigger("trigger1", "group1", "job1", "group1",
new Date(ts), null, 4, 10000);
job1.getJobDataMap().put(ColorJob.FAVORITE_COLOR, "Green");
job1.getJobDataMap().put(ColorJob.EXECUTION_COUNT, 1);
Date scheduleTime1 = sched.scheduleJob(job1, trigger1);
System.out.println(job1.getFullName() +
" will run at: " + scheduleTime1 +
" and repeat: " + trigger1.getRepeatCount() +
" times, every " + trigger1.getRepeatInterval() / 1000 + " seconds");
JobDetail job2 = new JobDetail("job2", "group1", ColorJob.class);
SimpleTrigger trigger2 = new SimpleTrigger("trigger2", "group1", "job2", "group1",
new Date(ts + 1000), null, 4, 10000);
job2.getJobDataMap().put(ColorJob.FAVORITE_COLOR, "Red");
job2.getJobDataMap().put(ColorJob.EXECUTION_COUNT, 1);
Date scheduleTime2 = sched.scheduleJob(job2, trigger2);
System.out.println(job2.getFullName() +
" will run at: " + scheduleTime2 +
" and repeat: " + trigger2.getRepeatCount() +
" times, every " + trigger2.getRepeatInterval() / 1000 + " seconds");
System.out.println("------- Starting Scheduler ----------------");
sched.start();
System.out.println("------- Started Scheduler -----------------");
System.out.println("------- Waiting 60 seconds... -------------");
try {
Thread.sleep(60L * 1000L);
} catch (Exception e) {
}
System.out.println("------- Shutting Down ---------------------");
sched.shutdown(true);
System.out.println("------- Shutdown Complete -----------------");
}
public static void main(String[] args) throws Exception {
JobStateExample example = new JobStateExample();
example.app=new ClassPathXmlApplicationContext(new String[] {
"classpath:applicationContext.xml",
"classpath:applicationContext-quartz.xml" });
example.sched = (Scheduler) example.app.getBean("quartzScheduler");
example.run();
}
}
运行结果如下:
------- Initializing -------------------
------- Initialization Complete --------
------- Scheduling Jobs ----------------
group1.job1 will run at: Wed Sep 28 11:13:40 CST 2011 and repeat: 4 times, every 10 seconds
group1.job2 will run at: Wed Sep 28 11:13:41 CST 2011 and repeat: 4 times, every 10 seconds
------- Starting Scheduler ----------------
------- Started Scheduler -----------------
------- Waiting 60 seconds... -------------
ColorJob: group1.job1 executing at Wed Sep 28 11:13:40 CST 2011
favorite color is Green
execution count (from job map) is 1
execution count (from job member variable) is 1
ColorJob: group1.job2 executing at Wed Sep 28 11:13:41 CST 2011
favorite color is Red
execution count (from job map) is 1
execution count (from job member variable) is 1
ColorJob: group1.job1 executing at Wed Sep 28 11:13:50 CST 2011
favorite color is Green
execution count (from job map) is 2
execution count (from job member variable) is 1
ColorJob: group1.job2 executing at Wed Sep 28 11:13:51 CST 2011
favorite color is Red
execution count (from job map) is 2
execution count (from job member variable) is 1
ColorJob: group1.job1 executing at Wed Sep 28 11:14:00 CST 2011
favorite color is Green
execution count (from job map) is 3
execution count (from job member variable) is 1
ColorJob: group1.job2 executing at Wed Sep 28 11:14:01 CST 2011
favorite color is Red
execution count (from job map) is 3
execution count (from job member variable) is 1
ColorJob: group1.job1 executing at Wed Sep 28 11:14:10 CST 2011
favorite color is Green
execution count (from job map) is 4
execution count (from job member variable) is 1
ColorJob: group1.job2 executing at Wed Sep 28 11:14:11 CST 2011
favorite color is Red
execution count (from job map) is 4
execution count (from job member variable) is 1
ColorJob: group1.job1 executing at Wed Sep 28 11:14:20 CST 2011
favorite color is Green
execution count (from job map) is 5
execution count (from job member variable) is 1
ColorJob: group1.job2 executing at Wed Sep 28 11:14:21 CST 2011
favorite color is Red
execution count (from job map) is 5
execution count (from job member variable) is 1
------- Shutting Down ---------------------
------- Shutdown Complete -----------------
可见,job的私有变量_counter并没有在每次触发的时候增加,一直都是1,而通过JobDataMap得到的count可以在每次触发时增加。
可能也可以使用如下方法,将private int _counter = 1;改成private static int _counter = 1;这个方法会带来个问题,如果job同时被多个触发器用到,这会互相干扰,呵呵,这是static的特性,所以要慎用。
结果如下:
------- Initializing -------------------
------- Initialization Complete --------
------- Scheduling Jobs ----------------
group1.job1 will run at: Wed Sep 28 11:09:30 CST 2011 and repeat: 4 times, every 10 seconds
group1.job2 will run at: Wed Sep 28 11:09:31 CST 2011 and repeat: 4 times, every 10 seconds
------- Starting Scheduler ----------------
------- Started Scheduler -----------------
------- Waiting 60 seconds... -------------
ColorJob: group1.job1 executing at Wed Sep 28 11:09:30 CST 2011
favorite color is Green
execution count (from job map) is 1
execution count (from job member variable) is 1
ColorJob: group1.job2 executing at Wed Sep 28 11:09:31 CST 2011
favorite color is Red
execution count (from job map) is 1
execution count (from job member variable) is 2
ColorJob: group1.job1 executing at Wed Sep 28 11:09:40 CST 2011
favorite color is Green
execution count (from job map) is 2
execution count (from job member variable) is 3
ColorJob: group1.job2 executing at Wed Sep 28 11:09:41 CST 2011
favorite color is Red
execution count (from job map) is 2
execution count (from job member variable) is 4
ColorJob: group1.job1 executing at Wed Sep 28 11:09:50 CST 2011
favorite color is Green
execution count (from job map) is 3
execution count (from job member variable) is 5
ColorJob: group1.job2 executing at Wed Sep 28 11:09:51 CST 2011
favorite color is Red
execution count (from job map) is 3
execution count (from job member variable) is 6
ColorJob: group1.job1 executing at Wed Sep 28 11:10:00 CST 2011
favorite color is Green
execution count (from job map) is 4
execution count (from job member variable) is 7
ColorJob: group1.job2 executing at Wed Sep 28 11:10:01 CST 2011
favorite color is Red
execution count (from job map) is 4
execution count (from job member variable) is 8
ColorJob: group1.job1 executing at Wed Sep 28 11:10:10 CST 2011
favorite color is Green
execution count (from job map) is 5
execution count (from job member variable) is 9
ColorJob: group1.job2 executing at Wed Sep 28 11:10:11 CST 2011
favorite color is Red
execution count (from job map) is 5
execution count (from job member variable) is 10
------- Shutting Down ---------------------
------- Shutdown Complete -----------------
附:
applicationContext-quartz.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans>
<bean name="quartzScheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="dataSource">
<ref bean="dataSource"/>
</property>
<property name="applicationContextSchedulerContextKey" value="applicationContextKey"/>
<property name="configLocation" value="classpath:quartz.properties"/>
<!--
<property name="triggers">-->
<!--
<list>
-->
<!--
<ref bean="trigger1"/>-->
<!--
<ref bean="trigger2"/>
-->
<!--
</list>-->
<!--
</property>
-->
</bean>
<!-- <bean id="jobDetail1" class="frameworkx.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">-->
<!-- <property name="targetObject" ref="simpleService1"/>-->
<!-- <property name="targetMethod" value="testMethod1"/>-->
<!--
<property name="shouldRecover" value="true"/>-->
<!-- </bean>-->
<!-- <bean id="trigger1" class="org.springframework.scheduling.quartz.CronTriggerBean">-->
<!-- <property name="jobDetail" ref="jobDetail1"/>-->
<!-- <property name="cronExpression" value="0/5 * * ? * * *"/>-->
<!-- </bean> -->
<!-- <bean id="jobDetail2" class="frameworkx.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">-->
<!-- <property name="targetObject" ref="simpleService1"/>-->
<!-- <property name="targetMethod" value="testMethod2"/>-->
<!--
<property name="shouldRecover" value="true"/>-->
<!-- </bean>-->
<!-- <bean id="trigger2" class="org.springframework.scheduling.quartz.SimpleTriggerBean">-->
<!-- <property name="jobDetail" ref="jobDetail2"/>-->
<!-- <property name="startDelay" value="1"/>-->
<!-- <property name="repeatCount" value="10"/>-->
<!-- <property name="repeatInterval" value="1000"/>-->
<!-- </bean>-->
<!-- <bean id="jobDetail" class="org.springframework.scheduling.quartz.JobDetailBean">-->
<!-- <property name="jobClass">-->
<!-- <value>-->
<!-- quartz.example.example5.test1.MyQuartzJobBean-->
<!-- </value>-->
<!-- </property>-->
<!-- <property name="jobDataAsMap">-->
<!-- <map>-->
<!-- <entry key="simpleService">-->
<!-- <ref bean="simpleService"/>-->
<!-- </entry>-->
<!-- </map>-->
<!-- </property>-->
<!-- </bean>-->
</beans>
applicationContext.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/jee
http://www.springframework.org/schema/jee/spring-jee-2.5.xsd" >
<context:component-scan base-package="com.sundoctor"/>
<!-- 属性文件读入 -->
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:jdbc.properties</value>
</list>
</property>
</bean>
<!-- 数据源定义,使用c3p0 连接池 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass" value="${jdbc.driverClassName}" />
<property name="jdbcUrl" value="${jdbc.url}" />
<property name="user" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<property name="initialPoolSize" value="5" />
<property name="minPoolSize" value="5" />
<property name="maxPoolSize" value="20" />
<property name="acquireIncrement" value="2" />
<property name="maxIdleTime" value="3600" />
<property name="idleConnectionTestPeriod" value="180"/>
<property name="automaticTestTable" value="C3P0TESTTABLE"/>
</bean>
</beans>
quartz.properties:
#==============================================================
#Configure Main Scheduler Properties
#==============================================================
org.quartz.scheduler.instanceName = TestScheduler1
org.quartz.scheduler.instanceId = AUTO
#==============================================================
#Configure ThreadPool
#==============================================================
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 10
org.quartz.threadPool.threadPriority = 5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true
#==============================================================
#Configure JobStore
#==============================================================
org.quartz.jobStore.misfireThreshold = 50000
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate
org.quartz.jobStore.tablePrefix = QRTZ_
org.quartz.jobStore.maxMisfiresToHandleAtATime=10
org.quartz.jobStore.isClustered = true
org.quartz.jobStore.clusterCheckinInterval = 20000