在我们的另一个专栏《深入浅出Quartz任务调度》详细的讲解了使用Quartz适用于从普通门户至网站企业级系统的任务调度实现方法。在下面我们结合实例来完整spring和quartz的整合工作,将我们对quartz的配置统一交给spring容器进行管理。quartz1与quartz2两个版本的差别较大,他们的具体差别可参考我的另一篇文章Quartz任务调度(1)概念例析快速入门 。鉴于我们的实际项目中很多依旧使用着quartz1版本,下面我们会针对quartz1和quartz2的配置分别进行分析。但是:
下面我们会先讲解spring与Quartz1.8.6的整合,不过讲完之后,我们会发现,Quartz1.8.6与Quartz2.2.2的配置区别是很小,因为Quartz2中将原来1.+中的JobDetail和Trigger都变成了接口。但只需将下面的XXXBean换成XXXFactoryBean,即可完美兼容1.+版本配置。
JobDetailBean
扩展自Quartz的JobDetail,当使用Bean声明JobDetail时,Bean的name/id极为任务名字,如果没有指定所属组,就使用默认组,它的常见属性有:
1. jobClass
指定我们自定义的Job接口实现类
2. name
默认为Bean的id名,通过此属性显示指定任务名
3. jobDataAsMap
类型为Map,通过设置此Map的值,对应设置到JobDetail的jobDataMap中
4. applicationContextJobDataKey
通过指定一个key,然后可以通过任务的JobDataMap来访问ApplicationContext,如果不设置此key,则JobDetailbean不会将ApplicationContext放入JobDataMap中
5. jobListenerNames:类型为String[],指定注册在Scheduler中的Joblistener名字,以便这些监听器对本任务进行监听。
6. group:设定组名
下面是一个配置实例:
<bean id="forumMaintainJob" class="tool.job.ForumMaintainJob" />
<bean class="org.springframework.scheduling.quartz.JobDetailBean" id="myJobDetail">
<property name="applicationContextJobDataKey" value="acKey" />
<property name="jobClass" value="tool.job.ForumMaintainJob" />
<property name="description" value="I'm desc" />
<property name="group" value="group1" />
<property name="name" value="testJob2" />
<property name="jobDataAsMap">
<map>
<entry key="key1" value="value1" />
<entry key="key2" value="value2" />
</map>
</property>
<property name="jobListenerNames">
<list>
<value>listener1</value>
<value>listener2</value>
</list>
</property>
</bean>
下面是我们的测试类
public class Test1 {
@Test
public void test1(){
ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:spring/spring-task.xml");
JobDetail jobDetail = (JobDetail) ac.getBean("myJobDetail");
System.out.println(jobDetail.getDescription());
System.out.println(jobDetail.getFullName());
System.out.println(jobDetail.getGroup());
System.out.println(jobDetail.getName());
System.out.println(jobDetail.getJobClass());
String[] listenerNames = jobDetail.getJobListenerNames();
for(String name : listenerNames){
System.out.println(name);
}
Map map = jobDetail.getJobDataMap();
for(Iterator it = map.keySet().iterator(); it.hasNext();){
Object key = it.next();
System.out.println( key + "——" + map.get(key));
}
}
}
运行方法后,打印信息:
I’m desc
group1.testJob2
group1
testJob2
class tool.job.ForumMaintainJob
listener1
listener2
acKey——org.springframework.context.support.ClassPathXmlApplicationContext@4d1d54a5: startup date [Sun Mar 27 00:09:10 CST 2016]; root of context hierarchy
key2——value2
key1——value1
MethodInvokingJobDetailFactoryBean
有的时候,我们的任务需要对操作数据库,完成特定的业务处理,如在Service定义了一个备份文章表的方法,要求在每天特定时刻将文章内容复制到一份备份表中,如果使用JobDetailBean,我们可能需要单独配置一个实现类,再完成相应的依赖配置工作来实现调用,但如果使用MethodInvokingJobDetailFactoryBean,我们可以把特定对象的某个方法封装成一个Job,就能直接在我们的Service类中完成任务调度了。
下面是我们的配置实例:
<bean class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean" id="myJobFactoryBean">
<property name="targetClass" value="com.yc.service.ArticleServiceImpl" /><!-- 指定目标类 -->
<property name="targetMethod" value="copyArticle" /><!-- 指定目标类中的方法 -->
<!-- <property name="staticMethod" value="com.yc.service.ArticleServiceImpl.copyArticle" /> 以上两句等同与这一句 -->
<property name="concurrent" value="false" /><!-- 指定最终封装出的任务类是否无状态,默认为true,表示无状态 -->
<property name="name" value="job1" />
<property name="group" value="group1" />
<property name="jobListenerNames">
<list>
<value>listener1</value>
<value>listener2</value>
</list>
</property>
</bean>
下面是我们的测试方法:
@Test
public void test2(){
ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:spring/spring-task.xml");
JobDetail jobDetail = (JobDetail) ac.getBean("myJobFactoryBean");
System.out.println(jobDetail.getDescription());
System.out.println(jobDetail.getFullName());
System.out.println(jobDetail.getGroup());
System.out.println(jobDetail.getName());
System.out.println(jobDetail.getJobClass());
String[] listenerNames = jobDetail.getJobListenerNames();
for(String name : listenerNames){
System.out.println(name);
}
Map map = jobDetail.getJobDataMap();
for(Iterator it = map.keySet().iterator(); it.hasNext();){
Object key = it.next();
System.out.println( key + "——" + map.get(key));
}
}
打印信息
null
group1.job1
group1
job1
class org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean StatefulMeth