<!--StartFragment-->
一、 新建 quartz 工程
新建 java 工程 IsmpQuartz ,在 build path 中加入用户库 quartz15 (我们使用 quartz1.5 版本),其中有 commons-beanutils.jar 、 commons-collections-3.1.jar 、 commons-digester-1.7.jar 、 commons-logging.jar 、 quartz-1.5.0.jar 、 log4j-1.2.11.jar 六个 jar 包。
二、 配置 log4j
在 src 目录下新建 log4j.properties ,内容:
# Create stdout appender
log4j.rootLogger= error, stdout
# Configure the stdout appender to go to the Console
log4j.appender.stdout= org.apache.log4j.ConsoleAppender
# Configure stdout appender to use the PatternLayout
log4j.appender.stdout.layout= org.apache.log4j.PatternLayout
# Pattern output the caller's filename and line #
log4j.appender.stdout.layout.ConversionPattern= %5p [%t] (%F/ : %L) - %m%n
# Print messages of level INFO or above for examples
log4j.logger.ydtf.quartz=info,stdout
注意最后一句,我们定义一个名为 ydtf.quartz 的 logger (日志器),其日志级别定为 info (及以上), appender (输出方式)为 stdout (即控制台),这样以 ydtf.quartz 包下的类名来获取 logger (日志器)时,只有 info 以上级别(包括 error )才可以使用 log4j 。
对于根日志器,我们过滤了 error 以下级别的输出,因为 quartz 自己输出的 info 级别和 debug 级别的信息实在太多,我们不得不过滤掉。
此外,需要注意对于 stdout 这样的输出方式,我们专门为它设计了一个输出模板:
%5p 表示输出占 5 个字符的优先级,即 error 、 info 等字样
[%t] 表示输出线程名并用中括号括住 , 即 [xxxx.class] 等字样
(%F/:%L) 表示输出“类名:行号”信息,并用圆括号括住
%m%n 表示输出信息内容,最后以回车符结束
* 注,如果 log4j 出现重复输出的情况,比如下面,每次消息都打印两次:
<!--[if gte vml 1]><v:shapetype id="_x0000_t75" coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f"> <v:stroke joinstyle="miter" /> <v:formulas> <v:f eqn="if lineDrawn pixelLineWidth 0" /> <v:f eqn="sum @0 1 0" /> <v:f eqn="sum 0 0 @1" /> <v:f eqn="prod @2 1 2" /> <v:f eqn="prod @3 21600 pixelWidth" /> <v:f eqn="prod @3 21600 pixelHeight" /> <v:f eqn="sum @0 0 1" /> <v:f eqn="prod @6 1 2" /> <v:f eqn="prod @7 21600 pixelWidth" /> <v:f eqn="sum @8 21600 0" /> <v:f eqn="prod @7 21600 pixelHeight" /> <v:f eqn="sum @10 21600 0" /> </v:formulas> <v:path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect" /> <o:lock v:ext="edit" aspectratio="t" /> </v:shapetype><v:shape id="_x0000_i1025" type="#_x0000_t75" style='width:585pt; height:50pt'> <v:imagedata src="file://localhost/Users/kmyhy/Library/Caches/TemporaryItems/msoclip/0/clip_image001.png" mce_src="file://localhost/Users/kmyhy/Library/Caches/TemporaryItems/msoclip/0/clip_image001.png" o:title="" /> </v:shape><![endif]-->
这并不是工作线程被同时执行了两次,而是 log4j 对一条信息进行了重复输出。请在 log4j.properties 的最后加上此句:
log4j.additivity.ydtf.quartz=false
即可消除重复输出问题。
三、 书写工作线程
新建类 SyncServiceConsumeJob, 实现 Job 接口:
package ydtf.quartz;
import java.util.Date;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.quartz.Job;
import org.quartz.JobDataMap;
import org.quartz.JobDetail;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
public class SyncServiceConsumeJob implements Job{
static Log logger = LogFactory. getLog (SyncServiceConsumeJob. class );
public void execute(JobExecutionContext context)
throws JobExecutionException {
JobDetail jobDetail = context.getJobDetail();
// The name is defined in the job definition
String jobName = jobDetail.getName();
// The directory to scan is stored in the job map
JobDataMap dataMap = jobDetail.getJobDataMap();
String doSth = dataMap.getString( "DO_SOMETHING" );
// Log the time the job started
logger .info(jobName + " " +doSth+ " at " + new Date());
}
}
四、 书写调度器
调度器是一个主线程,由他来启动 Scheduler 实例(由 quartz 实现,它会启动指定的工作线程):
package ydtf.quartz;
import java.util.Date;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.impl.StdSchedulerFactory;
public class SimpleScheduler {
static Log logger = LogFactory. getLog (SimpleScheduler. class );
public static void main(String[] args) {
SimpleScheduler simple = new SimpleScheduler();
simple.startScheduler();
}
public void startScheduler() {
Scheduler scheduler = null ;
try {
// Get a Scheduler instance from the Factory
scheduler = StdSchedulerFactory. getDefaultScheduler ();
// Start the scheduler
scheduler.start();
logger .info( "Scheduler started at " + new Date());
} catch (SchedulerException ex) {
// deal with any exceptions
logger .error(ex);
}
}
}
五、 配置 quartz 的工作方式 quartz.properties
在 src 目录下新建 quartz.properties 文件如下:
#===============================================================
#Configure Main Scheduler Properties
#===============================================================
org.quartz.scheduler.instanceName = QuartzScheduler # 指定调度器实例名
org.quartz.scheduler.instanceId = AUTO # 指定实例 id 自动分配
#===============================================================
#Configure ThreadPool
#===============================================================
org.quartz.threadPool.threadCount = 1 # 线程的线程数 1 ,即单线程
org.quartz.threadPool.threadPriority = 5 # 线程优先级 1-10 之间
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool# 线程池实现类
#===============================================================
#Configure JobStore
#===============================================================
org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore#Job 存储在内存中
#===============================================================
#Configure Plugins
#===============================================================
org.quartz.plugin.jobInitializer.class = org.quartz.plugins.xml.JobInitializationPlugin# 该插件使用 quartz_jobs.xml
org.quartz.plugin.jobInitializer.overWriteExistingJobs = true
org.quartz.plugin.jobInitializer.failOnFileNotFound = true
org.quartz.plugin.jobInitializer.validating= false
六、 配置 job , quartz_jobs.xml
<? xml version = '1.0' encoding = 'gbk' ?>
< quartz >
< job >
< job-detail >
< name > SyncServiceConsumeJob </ name >
< group > DEFAULT </ group >
< description >
同步业务执行消息
</ description >
< job-class >
ydtf.quartz.SyncServiceConsumeJob
</ job-class >
< volatility > false </ volatility >
< durability > false </ durability >
< recover > false </ recover >
< job-data-map allows-transient-data = "true" >
< entry >
< key > DO_SOMETHING </ key >
< value > 同步业务执行消息 </ value >
</ entry >
</ job-data-map >
</ job-detail >
< trigger >
< simple >
< name > Trigger1 </ name >
< group > DEFAULT </ group >
< job-name > SyncServiceConsumeJob </ job-name >
< job-group > DEFAULT </ job-group >
< start-time > 2009-08-27T1:00:00 </ start-time >
<!-- 每 10 秒无限循环 -->
< repeat-count > -1 </ repeat-count >
< repeat-interval > 10000 </ repeat-interval >
</ simple >
</ trigger >
</ job >
</ quartz >
七、 以 run as java application 方式运行 SimpleScheduler 。
总结:
1、 导入 quartz 所需的包( 6 个)
2、 配置 log4j.properties
3、 编写 job 类
4、 编写 Scheduler 类
5、 配置 quartz.properties
6、 配置 quartz_jobs.xml
<!--EndFragment-->