八. 为 JobStroreTX 创建数据源
当使用持久性 JobStore 时,Quartz 需要一个数据源。数据源扮演着产生数据库连接工厂的角色。在 Java 中,所有的数据源要实现 java.sql.Datasource 接口。Quartz 自身并不提供 Datasource 的所有功能;它只代表了那一职责。默认的,Quartz 能使用另一开源的框架,叫做 Commons DBCP,或者可以通过 JNDI 查找应用服务器中定义的 DataSource。
DBCP 是一个 Jakarta Commons 项目,网址是 http://jakarta.apache.org/commons/dbcp。这个框架的二进制版包含在 Quartz 的发行版中,你应该把它加到你的 Quartz 应用中来。你还需要加入 Commons Pool 库,它也包含中 Quartz 发行版中,是 DBCP 要用到的。
使用 JobStoreTX 时,你必须在 quartz.properties 文件中指定 Datasource 属性。这允许 Quartz 为你创建并管理 Datasource。表 6.4 列示了使用 JobStoreTX 时需要的 Datasource 配置属性。
表 6.4. 配置 Quartz Datasource 的可用属性
属性
必须
org.quartz.dataSource.NAME.driver
是
描述:JDBC 驱动类的全限名
org.quartz.dataSource.NAME.URL
是
描述:连接到你的数据库的 URL(主机,端口等)
org.quartz.dataSource.NAME.user
否
描述:用于连接你的数据库的用户名
org.quartz.dataSource.NAME.password
否
描述:用于连接你的数据库的密码
org.quartz.dataSource.NAME.maxConnections
否
描述:DataSource 在连接接中创建的最大连接数
org.quartz.dataSource.NAME.validationQuary
否
描述:一个可选的 SQL 查询字串,DataSource 用它来侦测并替换失败/断开的连接。例如,Oracle 用户可选用 select table_name from user_tables,这个查询应当永远不会失败,除非直的就是连接不上了。
表 6.4 中列出的每一个属性,你需要用你选择的名字替换掉属性的 NAME 部分。只要保证 Datasource 的所有属性的 NAME 部分相同就行了。这个名字用于唯一的标识 Datasource。假如你需要配置多个 Datasource (在使用 JobStoreCMT 时你将会这么做),每一个 Datasource 应该有一个唯一的 NAME 值。
代码 6.2 展示了一个为 JobStoreTX 配置 Datasource 的例子,它需要加到 quartz.properties 文件中
代码 6.2. 一个用于非 CMT 环境的 Quartz Datasource 的例子
- org.quartz.dataSource.myDS.driver = net.sourceforge.jtds.jdbc.Driver
- org.quartz.dataSource.myDS.URL = jdbc:jtds:sqlserver://localhost:1433/quartz
- org.quartz.dataSource.myDS.user = admin
- org.quartz.dataSource.myDS.password = myPassword
- org.quartz.dataSource.myDS.maxConnections = 10
org.quartz.dataSource.myDS.driver = net.sourceforge.jtds.jdbc.Driverorg.quartz.dataSource.myDS.URL = jdbc:jtds:sqlserver://localhost:1433/quartzorg.quartz.dataSource.myDS.user = adminorg.quartz.dataSource.myDS.password = myPasswordorg.quartz.dataSource.myDS.maxConnections = 10
像上面代码 6.2 那样加入了 Datasource 部分到 quartz.properties 文件后,你仍然需要使之对于已配置的 Quartz JobStoreTX 是可用的。你可以通过把下面的属性加到属性文件中来做到这一点:
org.quartz.jobStore.DataSource = <DS_NAME>
这个 <DS_NAME> 应该与指定给个 Datasource 配置的名字相匹配。对于代码 6.2 中的例子来使用 Datasource,你应当在 quartz.properties 文件中加入下面这行:
org.quartz.jobStore.dataSource = myDS
这个值然后会传递给 JobStoreSupport 并且对于你的 JobStoreTX 就可用了,这样连接就可以被获取并传递到 DriverDelegate 实例。
九. 应用 JobStoreTX 运行 Quartz
当你已完成前面的配置步骤时,你的程序就可以准备启动了。正如前面所有的例子那样,你仍然需要一个启动类来从工厂创建一个 Scheduler 实例,并调用它的 start() 方法。一个如代码 6.3 中的类就足够了。
代码 6.3. 简单的启动类,从命令行调用来启动 Scheduler
- public class SchedulerMain {
- static Log logger = LogFactory.getLog(SchedulerMain.class);
- public static void main(String[] args) {
- SchedulerMain app = new SchedulerMain();
- app.startScheduler();
- }
- public void startScheduler() {
- try {
- // Create an instance of the Scheduler
- Scheduler scheduler =
- StdSchedulerFactory.getDefaultScheduler();
- logger.info("Scheduler starting up...");
- scheduler.start();
- } catch (SchedulerException ex) {
- logger.error(ex);
- }
- }
- }
public class SchedulerMain { static Log logger = LogFactory.getLog(SchedulerMain.class); public static void main(String[] args) { SchedulerMain app = new SchedulerMain(); app.startScheduler(); } public void startScheduler() { try { // Create an instance of the Scheduler Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler(); logger.info("Scheduler starting up..."); scheduler.start(); } catch (SchedulerException ex) { logger.error(ex); } }}
当你使用代码 6.3 中的 SchedulerMain 类来测试 JobStoreTX 配置,你将得到类似于如下那样的输出:
INFO [main] - Quartz Scheduler v.1.5.0 created.
INFO [main] - Using thread monitor-based data access locking (synchronization).
INFO [main] - Removed 0 Volatile Trigger(s).
INFO [main] - Removed 0 Volatile Job(s).
INFO [main] - JobStoreTX initialized.
INFO [main] - Quartz scheduler 'QuartzScheduler' initialized from default resource
file in Quartz package: 'quartz.properties'
INFO [main] - Quartz scheduler version: 1.5.0
INFO [main] - Scheduler starting up...
INFO [main] - Freed 0 triggers from 'acquired' / 'blocked' state.
INFO [main] - Recovering 0 jobs that were in-progress at the time of the last
shut-down.
INFO [main] - Recovery complete.
INFO [main] - Removed 0 'complete' triggers.
INFO [main] - Removed 0 stale fired job entries.
INFO [main] - Scheduler QuartzScheduler_$_NON_CLUSTERED started.
日志信息是用 Log4J 显示的,因而它们可能和你实际的输出略有差别。一些事情从输出来看是很明显的。首先,在数据库中没有发现 Trigger 或 Job。这是很重要的,有些时候也是使人困惑之处。用了数据库却未给你加载任何的 Job 或 Trigger:是这样的,因为它无法知道谁来为你加载。这是你自己不得不做的事情,你可以几种方式把 Scheduler 信息存入到数据库中。