Quartz Job Scheduling Framework第8章翻译初稿

 

Chapter 8. Using Quartz Plug-Ins

8章 使用Quartz插件

The Quartz framework offers several ways to extend the capabilities of the platform. By using various "hooks" (commonly referred to as extension points), Quartz becomes very easy to extend and customize to suit your needs. One of the easiest methods for extending the framework is to use Quartz plug-ins. This chapter looks at how to use the plug-in mechanism to make Quartz go where no Quartz user has gone before.

<o:p> </o:p>

Quartz框架提供多种方法拓展平台能力。通过使用不同的钩子(hooks)-俗称拓展点,Quartz可以非常简单的拓展定制以满足你的需求。拓展框架最简单的方法就是使用Quartz插件。这一章看一下如何使用插件机制使Quartz达到以前Quartz用户达不到的地方(原文:make Quartz go where no Quartz user has gone before.)。(译者注:此处的意思是使Quartz整合到其他框架中)

<o:p> </o:p>

What Is a Plug-In?<o:p></o:p>

什么是插件<o:p></o:p>

If you have used other open source frameworks such as Apache Struts, you're already familiar with concept of plug-ins and their use. Quite simply, a Quartz plug-in is a Java class that implements the org.quartz.spi.SchedulerPlugin interface and is registered as a plug-in with the Scheduler. The plug-in interface contains three methods and is shown in Listing 8.1.

如果你曾经使用其他开源框架如ApacheStruts,你应该已经熟悉插件这个概念并使用过它了。非常简单的,一个Quartz插件就是一个实现了org.quartz.spi.SchedulerPlugin接口的JAVA类,它在Scheduler中注册为插件。插件的接口包含列表8.1显示的3个方法。

Listing 8.1. A Quartz Plug-In Must Implement the SchedulerPlugin Interface<o:p></o:p>

列表8.1 一个Quartz插件必须实现SchedulerPlugin接口

java 代码
  1. public interface SchedulerPlugin {   
  2.   
  3.      public void initialize(String name, Scheduler scheduler)   
  4.                throws SchedulerException;   
  5.   
  6.      public void start();   
  7.      public void shutdown();   
  8.   
  9. }   
  10.   

 

The methods of the SchedulerPlugin are called during the initialization and startup of a Scheduler. The Scheduler calls these methods on every plug-in that is registered. The following sections describe when each method of the plug-in is called.

<o:p> </o:p>

SchedulerPlugin的方法在Scheduler被初始化和启动时被调用。Scheduler依次调用每个注册插件的这些方法。下一段描述了插件中的每个方法在什么时间被调用。

<o:p> </o:p>

The initialize() Method<o:p></o:p>

initialize()方法<o:p></o:p>

The initialize() method is called during the creation of the Scheduler. When the getScheduler() method is called on the StdSchedulerFactory, the factory calls the initialize() method on all the registered plug-ins.

<o:p> </o:p>

initialize()在创建Scheduler时被调用。在StdSchedulerFactorygetScheduler()方法被调用的时候,工厂调用所有注册插件的initialize()方法。

<o:p> </o:p>

Plug-Ins Don't Work with the DirectSchedulerFactory<o:p></o:p>

插件不工作在DirectSchedulerFactory模式下<o:p></o:p>

Plug-ins are designed to be used only with the StdSchedulerFactory. It's a limitation within the framework. If you want to use plug-ins, then you'll need to use the StdSchedulerFactory to retrieve your Scheduler instance.

<o:p> </o:p>

插件被设计为只在StdSchedulerFactory下使用。这是框架的限制。如果你使用插件那么你必须使用StdSchedulerFactory获取Scheduler的实例。

<o:p> </o:p>

<o:p> </o:p>

Each plug-in is registered with a unique name. This given name and Scheduler instance is included in the call to the initialize() method. You should take whatever action is necessary to initialize your plug-in. For example, your plug-in might need to read and parse data from a file or database.

<o:p> </o:p>

每个注册的插件都有一个唯一的名字。这个名字与Scheduler实例会包含在调用的initialize()方法中。你应该采取任何必要的操作初始化插件。例如你的插件需要读取并解析文件或数据库中的数据。

<o:p> </o:p>

Scheduler Is Not Fully Set Up at initialize() Time<o:p></o:p>

在initialize()中Scheduler并没有全部设置<o:p></o:p>

The Scheduler has not been fully initialized when this method is called, so interaction with the Scheduler should be kept to a minimum. For example, you should not attempt to schedule any jobs during the initialize() method.

当这个方法被调用的时候Scheduler并没有完全被初始化,所以与Scheduler的交互应该保持在最小。例如你不应该在initialize()方法中调度任何Job

<o:p> </o:p>

If there is a problem initializing your plug-in, you should throw an org.quartz.SchedulerConfigException, which is a subclass of SchedulerException. This prevents the plug-in from being loaded and stops any further interaction with the Scheduler.

<o:p> </o:p>

如果在初始化的过程中发生了问题,程序会抛出org.quartz.SchedulerConfigException异常,他是SchedulerException的子类。它防止插件被加载并停止与Scheduler的进一步交互。

<o:p> </o:p>

The start() Method<o:p></o:p>

Start()方法<o:p></o:p>

The Scheduler instance calls the start() method to let the plug-in know that it can perform any startup actions it needs. For example, if you have jobs to schedule, this is the time to schedule them.

<o:p> </o:p>

Scheduler的实例调用start()方法让插件知道它可以完成任何它需要的启动操作。例如如果你有Job需要调度,那么就在这个时候去调度它。

<o:p> </o:p>

The shutdown() Method<o:p></o:p>

<o:p> </o:p>

Shutdown()方法<o:p></o:p>

<o:p> </o:p>

The shutdown() method is called to inform the plug-in that the Scheduler is shutting down. This is an opportunity for the plug-in to clean up any open resources that are open. For example, database connections or open files should be closed.

<o:p> </o:p>

Shutdown()方法通知插件Scheduler已经停止了。这个时候插件可以清理任何开放的资源。例如,数据库连接或关闭打开的文件。

<o:p> </o:p>

Scheduler Instance Not Passed in start() or shutdown()<o:p></o:p>

不要将Scheduler实例传递给start()或shutdown()方法<o:p></o:p>

<o:p> </o:p>

Notice that the Scheduler instance is not passed as an argument to the start() or shutdown() methods. If your plug-in needs access to the Scheduler during start() or shutdown(), you need to store the Scheduler in an instance variable in the plug-in.

注意,Scheduler实例不能作为参数传递给start()shutdown()方法。如果你的插件需要在start()shutdown()方法中访问Scheduler,你需要将Scheduler存储到插件中的实例变量中。

<o:p> </o:p>

Creating a Quartz Plug-In<o:p></o:p>

创建一个Quartz插件<o:p></o:p>

Creating a new plug-in is very simple. All you have to do is create a Java class (or reuse an existing one) that implements the org.quartz.spi.SchedulerPlugin interface. The Scheduler will create an instance of the plug-in during startup. The plug-in must have a no-argument constructor and obviously not be abstract.

<o:p> </o:p>

创建一个插件非常简单。你仅仅需要创建一个JAVA类(或重用已经存在的类),该类需要实现org.quartz.spi.SchedulerPlugin接口。Scheduler将会在启动时创建一个插件的实例。插件必须含有一个无参数的构造函数并且不能是虚函数。

<o:p> </o:p>

The JobInitializationPlugin<o:p></o:p>

JobInitializationPlugin插件<o:p></o:p>

The Quartz framework includes a plug-in for loading job and trigger information from an XML file. The plug-in is org.quartz.plugins.xml.JobInitializationPlugin and was discussed briefly back in Chapter 3, "Hello, Quartz." When you use this plug-in, the Quartz framework searches for a file called quartz_jobs.xml and attempts to load job and trigger information from this file.

<o:p> </o:p>

Quartz包含一个从XML文件读取Job和触发器信息的插件。这个插件就是org.quartz.plugins.xml.JobInitializationPlugin并且在第3 HelloQuartz中临时讨论了一下。当你使用这个插件的时候,Quartz将查找quartz_jobs.xml文件并且尝试从该文件中读取job和触发器信息。

<o:p> </o:p>

Changing the XML File That the JobInitializationPlugin Loads From<o:p></o:p>

改变JobInitializationPlugin读取的XML文件<o:p></o:p>

The plug-in enables you to change the name of the jobs file that it looks for to load job and trigger information. You change it by setting a different filename in the quartz.properties file. We talk more about setting parameters for plug-ins later in this chapter.

插件允许你改变寻找job和触发器信息的文件名。你可以在quartz.properties文件中设置其他的名字。在这章中我们更多的讨论在插件中设置参数。

<o:p> </o:p>

As Chapter 3 explained, this plug-in is very convenient when your application requirements don't involve loading job information from a database. It's also very useful during development and testing because you can quickly configure which jobs and triggers are to be fired. That is, arguably, it's easier to modify an XML file than a set of database tables.

<o:p> </o:p>

正如第3章阐述的那样,如果你的应用程序不想从数据库读取job信息时,使用该插件就非常方便。当然,在开发和测试时候也是非常有用的,因为你可能想快速的配置那些job和触发器被执行。综上可知修改XML文件比设置数据库表要简单的多。

<o:p> </o:p>

A nice extension to this idea of loading job and trigger information from an XML file would be to have a directory where you can store job XML files, and, by using a plug-in, the Scheduler would load whatever job files were present. This would enable you to conveniently add or remove jobs at Scheduler startup by simply adding or removing them from the specified directory. In the rest of this chapter, we show you how to build this plug-in.

<o:p> </o:p>

XML文件加载Job和触发器信息的一个比较好的拓展思想时,你可以建立一个目录存储jobXML文件。通过使用一个插件Scheduler不管job文件是否存在都可以进行加载。这种方式使你方便地通过简单地从目录中添加移除Scheduler启动时加载的Job信息。本章剩下的部分将讲解如何建立这个插件。

<o:p> </o:p>

Creating the JobLoaderPlugin<o:p></o:p>

创建JobLoaderPlugin<o:p></o:p>

<o:p> </o:p>

We call this new plug-in the JobLoaderPlugin. Listing 8.2 shows the JobLoaderPlugin class.

<o:p> </o:p>

我们调用这个新插件(JobLoaderPlugin)列表8.2显示了这个类。

<o:p> </o:p>

Listing 8.2. A Quartz SchedulerPlugin that Loads Multiple Job Files from a Directory<o:p></o:p>

列表8.2一个Quartz 的SchedulerPlugin插件从一个目录中加载多任务文件<o:p></o:p>

java 代码
  1. package org.cavaness.quartzbook.chapter8;   
  2.   
  3. import java.io.File;   
  4.   
  5. import org.apache.commons.logging.Log;   
  6. import org.apache.commons.logging.LogFactory;   
  7. import org.quartz.Scheduler;   
  8. import org.quartz.SchedulerConfigException;   
  9. import org.quartz.SchedulerException;   
  10. import org.quartz.spi.SchedulerPlugin;   
  11. import org.quartz.xml.JobSchedulingDataProcessor;   
  12.   
  13. public 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. private void loadJobs() throws SchedulerException {   
  62.   
  63.      File dir = null;   
  64.   
  65.      // Check directory   
  66.      if (getJobsDirectory() == null  
  67.                || !(dir =   
  68.                new File(getJobsDirectory())).exists()) {   
  69.           throw new SchedulerConfigException(   
  70.                     "The jobs directory was missing "  
  71.                               + jobsDirectory);   
  72.   
  73.      }   
  74.      logger.info("Loading jobs from " + dir.getName());   
  75.   
  76.      // Only XML files, filtering out any directories   
  77.      this.jobFiles = dir.listFiles(new XMLFileOnlyFilter());   
  78. }   
  79.   
  80. public void start() {   
  81.      processJobs();   
  82. }   
  83.   
  84. public void shutdown() {   
  85.      // nothing to clean up   
  86. }   
  87.   
  88. public void processJobs() {   
  89.      // There should be at least one job   
  90.      if (getJobFiles() == null || getJobFiles().length == 0) {   
  91.           return;   
  92.      }   
  93.   
  94.      JobSchedulingDataProcessor processor =   
  95.           new JobSchedulingDataProcessor(   
  96.                true, isValidateXML(), isValidateSchema());   
  97.   
  98.      int size = getJobFiles().length;   
  99.      for (int i = 0; i < size; i++) {   
  100.           File jobFile = getJobFiles()[i];   
  101.   
  102.           String fileName = jobFile.getAbsolutePath();   
  103.           logger.debug("Loading job file: " + fileName);   
  104.   
  105.           try {   
  106.   
  107.               processor.processFileAndScheduleJobs(   
  108.                    fileName, scheduler, true);   
  109.   
  110.           } catch (Exception ex) {   
  111.                logger.error("Error loading jobs: " + fileName);   
  112.                logger.error(ex);   
  113.           }   
  114.       }   
  115.    }   
  116.   
  117.    public String getJobsDirectory() {   
  118.         return jobsDirectory;   
  119.    }   
  120.   
  121.    public void setJobsDirectory(String jobsDirectory) {   
  122.         this.jobsDirectory = jobsDirectory;   
  123.    }   
  124.   
  125.    public String getPluginName() {   
  126.         return pluginName;   
  127.    }   
  128.   
  129.    public void setPluginName(String pluginName) {   
  130.         this.pluginName = pluginName;   
  131.    }   
  132.   
  133.    public boolean isValidateXML() {   
  134.         return validateXML;   
  135.    }   
  136.   
  137.    public void setValidateXML(boolean validateXML) {   
  138.         this.validateXML = validateXML;   
  139.    }   
  140. }   
  141.   

 

The real work of the JobLoaderPlugin in Listing 8.2 is done in just two methods: initialize() and start(). Both are required by the SchedulerPlugin interface. The rest of the methods are just setXXX and getXXX methods to fulfill the JavaBean contract because private properties have been declared.

列表8.2JobLoaderPlugin插件真正工作的只有2个方法:initialize() start()2个方法都是SchedulerPlugin接口中定义的。剩下的方法都是JavaBeangetset方法操作私有属性。

<o:p> </o:p>

The JobLoaderPlugin initialize() Method<o:p></o:p>

JobLoaderPlugin的initialize()方法<o:p></o:p>

<o:p> </o:p>

As you can see, the initialize() method, which is called by the Scheduler, calls the private loadJobs() method. The loadJobs() method uses the jobsDirectory that was passed in from the quartz.properties file to retrieve all XML files stored in that directory. The plug-in doesn't try to schedule the jobs yet because the Scheduler isn't fully instantiated when the plug-in's initialize() method is called. The JobLoaderPlugin simply holds on to an array of File objects, waiting for the start() method to be called. We also hold on to the instance of the Scheduler so that we have access to it when the start() method is called.

<o:p> </o:p>

正如你所见Scheduler调用的initialize()方法调用了私有方法loadJobs()loadJobs()方法使用从quartz.properties中所有来的储存在Job文件夹中的所有XML文件。暂时插件并不会试图调度job因为在插件的initialize()方法被调用的时候Scheduler还没有完全被初始化。JobLoaderPlugin简单的保存文件对象的数组,等待start()方法被调用。我们也保存了Scheduler的实例这样当start()方法被调用的时候可以访问它。

<o:p> </o:p>

The JobLoaderPlugin start() Method<o:p></o:p>

JobLoaderPlugin的start()方法<o:p></o:p>

When the Scheduler calls the start() method in the JobLoaderPlugin, the start() method calls processJobs(). The processJobs() method loops through the array of job files and loads each one into the Scheduler instance.

<o:p> </o:p>

ShedulerJobLoaderPlugin插件中调用start()<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值