Quartz Job Scheduling Framework[翻译]第八章. 使用 Quartz 插件 (第二部分)
二. 创建 Quartz 插件
创建一个新的插件很简单。你所有要做的就是创建一个 Java 类(或重用一个现有的类),让它实现 org.quartz.spi.SchedulerPlugin 接口。Scheduler 将会在启动期间创建这个插件的实例。这个插必须有一个无参的构造方法,很显然它不能是抽象的。
·JobInitializationPlugin
Quartz 框架有一个用来从 XML 文件中加载 Job 和 Trigger 信息的插件。这个插件就是 org.quartz.plugins.xml.JobInitializationPlugin,并且它在前面第三章 "Hello, Quartz" 中简略的讨论过。当你使用这个插件的时候,Quartz 框架就会搜寻一个叫做 quartz_jobs.xml 的文件并试图从中加载 Job 和 Trigger 信息。
如第三章所解释的,这个插件在你的应用需求不涉及到从数据库中加载 Job 信息时是很方便的。它在开发和测试期间也是很有用的,因为你可以快速的配置哪些 Job 和 Trigger 要被触发。就是说,无可争辩的,修改一个 XML 总比一系列的数据库表要简单。
对于从一个 XML 文件中加载 Job 和 Trigger 信息做法的一个很好的延展就是可以有一个目录来存储 Job XML 文件,然后过使用一个插件,Scheduler 就会加载任何存在的 Job 文件了。这允许你在 Scheduler 启动时简单从指定的目录中添加或移除 Job 文件来方便的增加或删除 Job。在本章剩下的部分,我们向你展示如何构建这个插件。
·创建 JobLoaderPlugin
我们把这个新插件命名为 JobLoaderPlugin。代码 8.2 中显示了这个 JobLoaderPlugin 类。
代码 8.2. 从一个目录中加载多个 Job 文件的 Quartz SchedulerPlugin
代码 8.2 中 JobLoaderPlugin 的实际工作仅是由两个方法:initialize() 和 start() 来完成的。它们是 SchedulerPlugin 接口所必须的。其他的方法只是 setXXX 和 getXXX 方法是用于实现 JavaBean 规范的,因为声明了私有属性。
·JobLoaderPlugin initialize() 方法
正如你看到的,由 Scheduler 调用的 initialize() 方法会调用 loadJobs() 方法。loadJobs() 方法使用从 quartz.properties 文件传入的 jobsDirectory 所指示的目录中获取所有的 XML 文件。这个插件还不会试图部署 Job,因为在插件的 initialize() 方法被调用的时候 Scheduler 还没有完全初始化好。JobLoaderPlugin 只简单的持有一个 File 对象的数组,直等 start() 方法被调用。我们还持有了一个 Scheduler 实例,以便我们在 start() 方法在调用时能访问它。
·JobLoaderPlugin start() 方法
当 Scheduler 调用 JobLoaderPlugin 的 start() 方法时,start() 方法就调用 processJobs()。processJobs() 方法遍历那个 Job 文件的数组并把每个都加载到 Scheduler 实例中。
对 Job 文件的处理是通过一个 org.quartz.xml.JobSchedulingDataProcessor 实例来完成的。调用 processFileAndScheduleJobs() 方法并传入文件名,Scheduler 实例和一个布尔值告诉它是否覆盖已有的 Job。
当 processJobs() 方法完成后,这个指定 jobsDirectory 下的所有 Job 文件就已经被加载并被部署了。 永久链接 https://yanbin.blog/quartz-job-scheduling-framework-8-2/, 来自 隔叶黄莺 Yanbin's Blog
[版权声明]
本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。
创建一个新的插件很简单。你所有要做的就是创建一个 Java 类(或重用一个现有的类),让它实现 org.quartz.spi.SchedulerPlugin 接口。Scheduler 将会在启动期间创建这个插件的实例。这个插必须有一个无参的构造方法,很显然它不能是抽象的。
·JobInitializationPlugin
Quartz 框架有一个用来从 XML 文件中加载 Job 和 Trigger 信息的插件。这个插件就是 org.quartz.plugins.xml.JobInitializationPlugin,并且它在前面第三章 "Hello, Quartz" 中简略的讨论过。当你使用这个插件的时候,Quartz 框架就会搜寻一个叫做 quartz_jobs.xml 的文件并试图从中加载 Job 和 Trigger 信息。
| 改变 JobInitializtionPlugin 加载的 XML 文件 插件允许你改变它要查找来加载 Job 和 Trigger 信息的文件的名字。你可以通过在 quartz.properties 文件中设置一个别的文件名。我们会在本章后续中讲到更多的关于设置插件参数的内容。 |
如第三章所解释的,这个插件在你的应用需求不涉及到从数据库中加载 Job 信息时是很方便的。它在开发和测试期间也是很有用的,因为你可以快速的配置哪些 Job 和 Trigger 要被触发。就是说,无可争辩的,修改一个 XML 总比一系列的数据库表要简单。
对于从一个 XML 文件中加载 Job 和 Trigger 信息做法的一个很好的延展就是可以有一个目录来存储 Job XML 文件,然后过使用一个插件,Scheduler 就会加载任何存在的 Job 文件了。这允许你在 Scheduler 启动时简单从指定的目录中添加或移除 Job 文件来方便的增加或删除 Job。在本章剩下的部分,我们向你展示如何构建这个插件。
·创建 JobLoaderPlugin
我们把这个新插件命名为 JobLoaderPlugin。代码 8.2 中显示了这个 JobLoaderPlugin 类。
代码 8.2. 从一个目录中加载多个 Job 文件的 Quartz SchedulerPlugin
1package org.cavaness.quartzbook.chapter8;
2
3import java.io.File;
4
5import org.apache.commons.logging.Log;
6import org.apache.commons.logging.LogFactory;
7import org.quartz.Scheduler;
8import org.quartz.SchedulerConfigException;
9import org.quartz.SchedulerException;
10import org.quartz.spi.SchedulerPlugin;
11import org.quartz.xml.JobSchedulingDataProcessor;
12
13public class JobLoaderPlugin implements SchedulerPlugin {
14
15 private static Log logger =
16 LogFactory.getLog(JobLoaderPlugin.class);
17
18 // The directory to load jobs from
19 private String jobsDirectory;
20
21 // An array of File objects
22 private File[] jobFiles = null;
23
24 private String pluginName;
25
26 private Scheduler scheduler;
27
28 private boolean validateXML = true;
29
30 private boolean validateSchema = true;
31
32 public JobLoaderPlugin() {
33 }
34
35 public File[] getJobFiles() {
36 return jobFiles;
37 }
38
39 public void setJobFiles(File[] jobFiles) {
40 this.jobFiles = jobFiles;
41 }
42
43 public boolean isValidateSchema() {
44 return validateSchema;
45 }
46
47 public void setValidateSchema(boolean validatingSchema) {
48 this.validateSchema = validatingSchema;
49 }
50
51 public void initialize(String name, final Scheduler scheduler)
52 throws SchedulerException {
53
54 this.pluginName = name;
55 this.scheduler = scheduler;
56
57 logger.debug("Registering Plugin " + pluginName);
58 // Load the job definitions from the specified directory
59 loadJobs();
60 }
61
62 private void loadJobs() throws SchedulerException {
63
64 File dir = null;
65
66 // Check directory
67 if (getJobsDirectory() == null
68 || !(dir =
69 new File(getJobsDirectory())).exists()) {
70 throw new SchedulerConfigException(
71 "The jobs directory was missing "
72 + jobsDirectory);
73
74 }
75 logger.info("Loading jobs from " + dir.getName());
76
77 // Only XML files, filtering out any directories
78 this.jobFiles = dir.listFiles(new XMLFileOnlyFilter());
79 }
80
81 public void start() {
82 processJobs();
83 }
84
85 public void shutdown() {
86 // nothing to clean up
87 }
88
89 public void processJobs() {
90 // There should be at least one job
91 if (getJobFiles() == null || getJobFiles().length == 0) {
92 return;
93 }
94
95 JobSchedulingDataProcessor processor =
96 new JobSchedulingDataProcessor(
97 true, isValidateXML(), isValidateSchema());
98
99 int size = getJobFiles().length;
100 for (int i = 0; i < size; i++) {
101 File jobFile = getJobFiles()[i];
102
103 String fileName = jobFile.getAbsolutePath();
104 logger.debug("Loading job file: " + fileName);
105
106 try {
107
108 processor.processFileAndScheduleJobs(
109 fileName, scheduler, true);
110
111 } catch (Exception ex) {
112 logger.error("Error loading jobs: " + fileName);
113 logger.error(ex);
114 }
115 }
116 }
117
118 public String getJobsDirectory() {
119 return jobsDirectory;
120 }
121
122 public void setJobsDirectory(String jobsDirectory) {
123 this.jobsDirectory = jobsDirectory;
124 }
125
126 public String getPluginName() {
127 return pluginName;
128 }
129
130 public void setPluginName(String pluginName) {
131 this.pluginName = pluginName;
132 }
133
134 public boolean isValidateXML() {
135 return validateXML;
136 }
137
138 public void setValidateXML(boolean validateXML) {
139 this.validateXML = validateXML;
140 }
141}代码 8.2 中 JobLoaderPlugin 的实际工作仅是由两个方法:initialize() 和 start() 来完成的。它们是 SchedulerPlugin 接口所必须的。其他的方法只是 setXXX 和 getXXX 方法是用于实现 JavaBean 规范的,因为声明了私有属性。
·JobLoaderPlugin initialize() 方法
正如你看到的,由 Scheduler 调用的 initialize() 方法会调用 loadJobs() 方法。loadJobs() 方法使用从 quartz.properties 文件传入的 jobsDirectory 所指示的目录中获取所有的 XML 文件。这个插件还不会试图部署 Job,因为在插件的 initialize() 方法被调用的时候 Scheduler 还没有完全初始化好。JobLoaderPlugin 只简单的持有一个 File 对象的数组,直等 start() 方法被调用。我们还持有了一个 Scheduler 实例,以便我们在 start() 方法在调用时能访问它。
·JobLoaderPlugin start() 方法
当 Scheduler 调用 JobLoaderPlugin 的 start() 方法时,start() 方法就调用 processJobs()。processJobs() 方法遍历那个 Job 文件的数组并把每个都加载到 Scheduler 实例中。
对 Job 文件的处理是通过一个 org.quartz.xml.JobSchedulingDataProcessor 实例来完成的。调用 processFileAndScheduleJobs() 方法并传入文件名,Scheduler 实例和一个布尔值告诉它是否覆盖已有的 Job。
当 processJobs() 方法完成后,这个指定 jobsDirectory 下的所有 Job 文件就已经被加载并被部署了。 永久链接 https://yanbin.blog/quartz-job-scheduling-framework-8-2/, 来自 隔叶黄莺 Yanbin's Blog
[版权声明]
本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。