.jpg)
开头还是那句话,懒人直接下源码,如果有疑问,请看帖子最后的总结。
本范例演示了JobInitializationPlugin类的用法。排程的初始化使用XML文件配置,由插件加载配置文件。
本例配置了2项任务。
如果你要自己亲自动手实现本范例,注意必须的jar包如下:
commons-digester-1.7.jar ----- 解析xml文档
commons-beanutils.jar
commons-collections-3.1.jar
commons-logging.jar
log4j-1.2.11.jar
quartz-1.6.0.jar
配置文件3个,分别是:
log4j.xml
quartz.properties
jobs.xml
1. log4j.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<appender name="default" class="org.apache.log4j.ConsoleAppender">
<param name="target" value="System.out"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="[%p] %d{dd MMM hh:mm:ss.SSS aa} %t [%c]%n%m%n%n"/>
</layout>
</appender>
<logger name="org.quartz">
<level value="debug" />
</logger>
<root>
<level value="debug" />
<appender-ref ref="default" />
</root>
</log4j:configuration>
2. quartz.properties
#============================================================================
# Configure Main Scheduler Properties
#============================================================================
org.quartz.scheduler.instanceName = TestScheduler
org.quartz.scheduler.instanceId = AUTO
#============================================================================
# Configure ThreadPool
#============================================================================
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 3
org.quartz.threadPool.threadPriority = 5
#============================================================================
# Configure JobStore
#============================================================================
org.quartz.jobStore.misfireThreshold = 60000
org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore
#org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
#org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.PostgreSQLDelegate
#org.quartz.jobStore.useProperties = false
#org.quartz.jobStore.dataSource = myDS
#org.quartz.jobStore.tablePrefix = QRTZ_
#org.quartz.jobStore.isClustered = false
#============================================================================
# Configure Datasources
#============================================================================
#org.quartz.dataSource.myDS.driver = org.postgresql.Driver
#org.quartz.dataSource.myDS.URL = jdbc:postgresql://localhost/dev
#org.quartz.dataSource.myDS.user = jhouse
#org.quartz.dataSource.myDS.password =
#org.quartz.dataSource.myDS.maxConnections = 5
#============================================================================
# Configure Plugins
#============================================================================
org.quartz.plugin.triggHistory.class = org.quartz.plugins.history.LoggingJobHistoryPlugin
org.quartz.plugin.jobInitializer.class = org.quartz.plugins.xml.JobInitializationPlugin
org.quartz.plugin.jobInitializer.fileNames = jobs.xml
org.quartz.plugin.jobInitializer.overWriteExistingJobs = true
org.quartz.plugin.jobInitializer.failOnFileNotFound = true
org.quartz.plugin.jobInitializer.scanInterval = 10
org.quartz.plugin.jobInitializer.wrapInUserTransaction = false
3. jobs.xml
<?xml version=’1.0’ encoding=’utf-8’?>
<quartz xmlns="http://www.opensymphony.com/quartz/JobSchedulingData"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.opensymphony.com/quartz/JobSchedulingData
http://www.opensymphony.com/quartz/xml/job_scheduling_data_1_5.xsd"
version="1.5">
<!-- 描述了日历,记得上次范例如何使用日历吗?先要把日历加入排程,后将日历与制定触发器关联 -->
<calendar class-name="org.quartz.impl.calendar.HolidayCalendar"
replace="true">
<name>holidayCalendar</name>
<description>HolidayCalendar</description>
<base-calendar
class-name="org.quartz.impl.calendar.WeeklyCalendar">
<name>weeklyCalendar</name>
<description>WeeklyCalendar</description>
<base-calendar
class-name="org.quartz.impl.calendar.AnnualCalendar">
<name>annualCalendar</name>
<description>AnnualCalendar</description>
</base-calendar>
</base-calendar>
</calendar>
<job>
<!-- 排程包含任务和触发器,且2者必须关联 -->
<!-- 描述任务 -->
<job-detail>
<name>testJob1</name>
<group>testJobs</group>
<description>Test Job Number 1</description>
<job-class>
com.zbaccp.quartz.cl.example10.SimpleJob
</job-class>
<volatility>false</volatility>
<durability>false</durability>
<recover>false</recover>
<!-- JobDatamap在执行间,保存持续的信息 -->
<job-data-map>
<entry>
<key>test1</key>
<value>test1</value>
</entry>
<entry>
<key>test2</key>
<value>test2</value>
</entry>
</job-data-map>
</job-detail>
<!-- 触发器和触发器与任务的关联 -->
<trigger>
<cron>
<name>testTrigger1</name>
<group>testJobs</group>
<description>Test Trigger Number 1</description>
<job-name>testJob1</job-name>
<job-group>testJobs</job-group>
<!--
<start-time>2003-12-17 2:15:00 pm</start-time>
<end-time>2013-12-17 2:15:00 pm</end-time>
-->
<cron-expression>0/15 * * ? * *</cron-expression>
<!-- every 15 seconds... -->
</cron>
</trigger>
</job>
<job>
<job-detail>
<name>testJob2</name>
<group>testJobs</group>
<description>Test Job Number 2</description>
<job-class>
com.zbaccp.quartz.cl.example10.SimpleJob
</job-class>
<volatility>false</volatility>
<durability>false</durability>
<recover>false</recover>
</job-detail>
<trigger>
<simple>
<name>testTrigger2</name>
<group>testJobs</group>
<description>Test Trigger Number 2</description>
<!-- 关联日历 -->
<calendar-name>holidayCalendar</calendar-name>
<job-name>testJob2</job-name>
<job-group>testJobs</job-group>
<start-time>2004-02-26T12:26:00</start-time>
<repeat-count>10</repeat-count>
<repeat-interval>5000</repeat-interval>
</simple>
</trigger>
</job>
</quartz>
4. SimpleJob.java
package com.zbaccp.quartz.cl.example10;
import java.util.Date;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
/**
* 简单任务,只是打印出任务名和执行时刻
*
* @author 常磊
*/
public class SimpleJob implements Job {
private static Log _log = LogFactory.getLog(SimpleJob.class);
public SimpleJob() {
}
// 任务体
public void execute(JobExecutionContext context)
throws JobExecutionException {
String jobName = context.getJobDetail().getFullName();
_log.info("======任务名称: " + jobName + " 运行时刻: " + new Date());
}
}
5. PlugInExample.java
package com.zbaccp.quartz.cl.example10;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.quartz.Scheduler;
import org.quartz.SchedulerFactory;
import org.quartz.SchedulerMetaData;
import org.quartz.impl.StdSchedulerFactory;
/**
* 本范例演示了JobInitializationPlugin类的用法,排程的初始化使用XML文件配置。
* 本例jobs.xml中共配置了2项任务,分别使用cron触发器和简单触发器。
*
* @author 常磊
*/
public class PlugInExample {
public void run() throws Exception {
Log log = LogFactory.getLog(PlugInExample.class);
//1 排程实例化
SchedulerFactory sf = new StdSchedulerFactory();
Scheduler sched = sf.getScheduler();
log.info("------- 初始化完毕 -----------");
log.info("------- (没有安排任何任务 - 根据XML文档的定义来运行 --");
log.info("------- 启动排程 ----------------");
//2 启动排程
sched.start();
log.info("------- 排程已启动 -----------------");
log.info("------- 等待5分钟... -----------");
try {
Thread.sleep(300L * 1000L);
} catch (Exception e) {
}
//3 关闭排程
log.info("------- 开始关闭 ---------------------");
sched.shutdown(true);
log.info("------- 关闭结束 -----------------");
SchedulerMetaData metaData = sched.getMetaData();
log.info("共执行任务 " + metaData.numJobsExecuted() + " 次。");
}
public static void main(String[] args) throws Exception {
PlugInExample example = new PlugInExample();
example.run();
}
}
6. 我们的结论
l 插件提供的是对Quartz框架的一种扩展机制。如果你用过Struts就知道插件的使用,比如使用tiles框架,struts集成spring,实在司空常见。
l 官方推荐使用插件,是因为把job写在xml文件里,可维护性更好。插件只是把本来要写成代码的内容,写到配置文件中,并没有改变排程的工作机制。
l 如果要使用插件,必须覆盖jar包原有的quartz.properties文件,覆盖的方法是类路径根下的用户定义quartz.properties文件。
l 本例中使用了2个框架内置plugin。
l 在jobs.xml中,<quartz >为根元素。
l <calendar>配置了日历, <trigger>的后代标签<calendar-name>使触发器与日历关联。
l <job>标签代表一个任务,任务包含了<job-detail>标签(任务明细) 和<trigger>标签(触发器),同处于<job>标签中让2者关联。
l <job-detail>标签最为关键配置了Job接口的实现类。
l <trigger>标签可以选用CronTrigger或者SimpleTrigger。
7. quartz.properties中插件配置的说明
fileNames:
包含了使用,间隔的文件名列表,注意必须包含路径。每个配置文件包含了任务和管理触发器的定义。
overWriteExistingJobs:
告诉插件当启动的时候是否覆盖已存的同名任务。
failOnFileNotFound:
如果xml定义文件没有找到,插件是否抛出异常,从而阻止插件初始化。
scanInterval:
如果检测到xml定义文件发生更改,可以重新加载配置文件。本参数定义检测的时间间隔(单位:秒)。设置为0取消检测。
wrapInUserTransaction:
如果插件使用了JobStoreCMT(容器管理事务的jobStore),确认本属性设置为true,否则有可能导致不可预知的行为。
quartzOfficial10.rar