ScanDirectoryJob.java
package org.hzy.quartz; import java.io.File; import java.io.FileFilter; import java.text.ParseException; import java.util.Date; import org.quartz.CronTrigger; import org.quartz.Job; import org.quartz.JobDataMap; import org.quartz.JobDetail; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.quartz.Scheduler; import org.quartz.SchedulerException; import org.quartz.SchedulerFactory; import org.quartz.impl.StdSchedulerFactory; public class ScanDirectoryJob implements Job { @Override public void execute(JobExecutionContext arg0) throws JobExecutionException { // TODO Auto-generated method stub JobDetail jdetail = arg0.getJobDetail(); if(jdetail ==null){ throw new RuntimeException("请检查当前作业配置是否完整!"); } String jobName = jdetail.getName(); System.out.println(jobName + " " + new Date()); JobDataMap jmp = jdetail.getJobDataMap(); String dirName = jmp.getString("SCAN_DIR"); if (dirName == null) { throw new JobExecutionException("Directory not configured"); } System.out.println(dirName); File dir = new File(dirName); if (!dir.exists()) { throw new JobExecutionException("Invalid Dir " + dirName); } String matchName=jmp.getString("MATCH_NAME"); FileFilter filter = new FileExtensionFileFilter(matchName); File[] files = dir.listFiles(filter); int size = files.length; for (int i = 0; i < size; i++) { File file = files[i]; File aFile = file.getAbsoluteFile(); long fileSize = file.length(); String msg = aFile + " - Size: " + fileSize; System.out.println(msg); } } }
当 Quartz调用execute()方法,会传递一个org.quartz.JobExecutionContext上下文变量,里面封装有 Quartz 的运行时环境和当前正执行的 Job。通过JobexecutionContext,你可以访问到调度器的信息,作业和作业上的触发器的信息,还有更多更多的信息。在代码 3.1 中,JobExecutionContext被用来访问org.quartz.JobDetail类,JobDetail类持有 Job 的详细信息,包括为 Job 实例指定的名称,Job 所属组,Job 是否被持久化(易失性),和许多其他感兴趣的属性。
JobDetail又持有一个指向org.quartz.JobDataMap的引用。JobDataMap中有为指定 Job 配置的自定义属性。例如,在代码 3.1中,我们从JobDataMap中获得欲扫描的目录名,我们可以在ScanDirectoryJob中硬编码这个目录名,但是这样的话我们难以重用这个 Job 来扫描别的目录了。在后面有一节“编程方式调度一个 Quartz Job”,你将会看到目录是如何配置到JobDataMap的。
execute()方法中剩下的就是标准 Java 代码了:获得目录名并创建一个java.io.File对象。它还对目录名作为简单的校验,确保是一个有效且存在的目录。接着调用 File 对象的listFiles()方法得到目录下的文件。还创建了一个java.io.FileFilter对象作为参数传递给listFiles()方法。org.quartzbook.cavaness.FileExtensionFileFilter实现了java.io.FileFilter接口,它的作用是过滤掉目录仅返回 XML 文件。默认情况下,listFiles() 方法是返回目录中所有内容,不管是文件还是子目录,所以我们必须过滤一下,因为我们只对 XML 文件感兴趣。
注: FileExtensionFileFilter并非 Quartz 框架的一部分;它是java.io.FileFilter的子类,而是 Java 核心的一部分。FileExtensionFileFilter被创建为我们例子的一部分,用来滤除其他内容而只保留 XML 文件。它相当有用,你可以考虑为你的应用建一系列的文件过滤器,然后在你的 Quartz Job 中重用。 |
FileExtensionFileFilter.java
package org.hzy.quartz; import java.io.File; import java.io.FileFilter; public class FileExtensionFileFilter implements FileFilter { private String extension; public FileExtensionFileFilter(String extension) { this.extension = extension; } @Override public boolean accept(File file) { // TODO Auto-generated method stub String lCaseFilename = file.getName().toLowerCase(); return (file.isFile() && (lCaseFilename.indexOf(extension) > 0)) ? true : false; } }
FileExtensionFileFilter被用来屏蔽名称中不含字符串 “.xml” 的文件。它还屏蔽了子目录--这些子目录原本会让listFiles()方法正常返回。过滤器提供了一种很便利的方式选择性的向你的 Quartz 作业提供它能接受的作为输入的文件。
声明式之于编程式配置 在 Quartz 中,我们有两种途径配置应用程序的运行时属性:声明式和编程式。有一些框架是使用外部配置文件的方式;我们都知道,在软件中硬编码设置有它的局限性。 从其他方面来讲,你将要根据具体的需求和功能来选择用哪一种方式。下一节强调了何时用声明式何时选择编程式。因为多数的 Java 行业应用都偏向于声明的方式,这也是我们所推荐的。 |
测试1:
package org.hzy.quartz; import java.util.Date; import org.hzy.test.QuartzReport; import org.quartz.JobDataMap; import org.quartz.JobDetail; import org.quartz.Scheduler; import org.quartz.SchedulerException; import org.quartz.Trigger; import org.quartz.TriggerUtils; import org.quartz.impl.StdSchedulerFactory; public class Listing_3_6 { public static void main(String[] args) throws SchedulerException { Listing_3_6 example = new Listing_3_6(); Scheduler sched = example.createScheduler(); // example.scheduleJob(sched); sched.start(); example.scheduleJob1(sched, "ScanDirectory1", ScanDirectoryJob.class, "/home/hzy", 10); example.scheduleJob1(sched, "ScanDirectory2", ScanDirectoryJob.class, "/home/hzy/下载", 15); // sched.shutdown(); // System.out.println("Scheduler started at " + new Date()); } public Scheduler createScheduler() throws SchedulerException { return StdSchedulerFactory.getDefaultScheduler(); } private void scheduleJob(Scheduler scheduler) throws SchedulerException { JobDetail jobDetail = new JobDetail("ScanDirectory", Scheduler.DEFAULT_GROUP, ScanDirectoryJob.class); jobDetail.getJobDataMap().put("SCAN_DIR", "/home/hzy"); Trigger trigger = TriggerUtils.makeSecondlyTrigger(1); trigger.setName("scanTrigger"); trigger.setStartTime(new Date()); scheduler.scheduleJob(jobDetail, trigger); } private void scheduleJob1(Scheduler scheduler, String jobName, Class jobClass, String scanDir, int scanInterval) throws SchedulerException { JobDetail jobDetail = new JobDetail(jobName, Scheduler.DEFAULT_GROUP, jobClass); // jobDetail.getJobDataMap().put("SCAN_DIR", scanDir); JobDataMap jmp=new JobDataMap(); jmp.put("SCAN_DIR", scanDir); jmp.put("MATCH_NAME",".xml"); jobDetail.setJobDataMap(jmp); Trigger trigger = TriggerUtils.makeSecondlyTrigger(scanInterval); trigger.setName(jobName + "-Trigger"); trigger.setStartTime(new Date()); scheduler.scheduleJob(jobDetail, trigger); } }
<?xml version="1.0" encoding="UTF-8"?> <job-scheduling-data xmlns="http://www.quartz-scheduler.org/xml/JobSchedulingData" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.quartz-scheduler.org/xml/JobSchedulingData http://www.quartz-scheduler.org/xml/job_scheduling_data_1_8.xsd" version="1.8"> <schedule> <job> <name>ScanDirectory</name> <group>DEFAULT</group> <description> A job that scans a directory for files </description> <job-class> org.hzy.quartz.ScanDirectoryJob </job-class> <volatility>false</volatility> <durability>false</durability> <recover>false</recover> <job-data-map> <entry> <key>SCAN_DIR</key> <value>/home/hzy</value> </entry> <entry> <key>MATCH_NAME</key> <value>.xml</value> </entry> </job-data-map> </job> <trigger> <!-- <simple> <name>scanTrigger</name> <group>DEFAULT</group> <job-name>ScanDirectory</job-name> <job-group>DEFAULT</job-group> <start-time>2012-07-07T14:42:00</start-time> <repeat-count>-1</repeat-count> <repeat-interval>1000</repeat-interval> </simple>--> <cron> <name>scanTrigger</name> <group>DEFAULT</group> <job-name>ScanDirectory</job-name> <job-group>DEFAULT</job-group> <cron-expression>0/1 * * * * ?</cron-expression> </cron> </trigger> </schedule> </job-scheduling-data>