4. 创建 Quartz RMI 服务端
你务必按几个步骤来配置 Quartz 来使用 RMI。其中的一些步骤会在创建 Quartz RMI 服务端用到,还有些步骤会在 Quartz 客户端连接服务端。我们先来阐述服务端的配置步骤。
·配置 Quartz RMI 服务端
第一步就是修改要部署到 Quartz RMI 服务端的 quartz.properties 文件。当在 Quartz 中使用 RMI,你还必须添加几个新的属性。表 9.1 包括了完整 RMI 属性列表。
属性 | 默认值 |
org.quartz.scheduler.rmi.export注:假如你要使 Quartz 调度作为一个可用的 RMI 对象,这个标记必须设置为 true | false |
org.quartz.scheduler.rmi.registryHost注:这是运行 RMI 注册表所在的主机 | localhost |
org.quartz.scheduler.rmi.registryPort注:这是 RMI 注册服务监听所用的端口号(通常是1099) | 1099 |
org.quartz.scheduler.rmi.createRegistry注:这项决定了 Quartz 是否会创建 RMI 注册服务。如果你不希望 Quartz 创建注册服务就设置为 false 或 never。如果是希望 Quartz 首先尝试去使用已存在的注册服务,如果失败的话自行创建一个就设置为 true 或 as_needed。假如注册服务创建好了,它会使用给定的 registryPort 绑定到所给的 registryHost 上。 | never |
org.quartz.scheduler.rmi.serverPort注:这是 Quartz 调度器服务所绑定的端口号,在其中监听到来的连接。默认,RMI 服务会随机选择一个端口号作为调度器绑定到 RMI 注册服务的端口。 | -1 |
表 9.1 中的所有属性都必须加到Quartz RMI 服务端所使用的 quartz.properties 文件中去。虽然这些属性都有默认值的,但最好还是显式的为它们指定值,以免产生混乱。代码 9.1 是一个 Quartz RMI 服务端所用的属性文件的样例。 |
代码 9.1. 用于 Quartz RMI 服务端的 quartz.properties 文件样例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
#============================================================== # Configure Main Scheduler Properties #============================================================== org.quartz.scheduler.instanceName = RMIScheduler #============================================================== # Configure RMI Properties #============================================================== org.quartz.scheduler.rmi.export = true org.quartz.scheduler.rmi.registryHost = localhost org.quartz.scheduler.rmi.registryPort = 1099 org.quartz.scheduler.rmi.serverPort = 0 org.quartz.scheduler.rmi.createRegistry = true #============================================================== # Configure ThreadPool #============================================================== org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool org.quartz.threadPool.threadCount = 10 org.quartz.threadPool.threadPriority = 5 #============================================================== # Configure JobStore #============================================================== org.quartz.jobStore.misfireThreshold = 60000 org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore |
你认得代码 9.1 的 quartz.properties 文件的大部分设置的,这些在前面章节中讲过。我们只是往期中加了表 9.1 所列的属性。
·创建 Quartz RMI 服务端启动类
为启动 Quartz RMI 服务端,你必须创建一个启动类,该类从工厂中获取到调度器实例,然后运行这个调度器。即使是不用 RMI 也需要这一步。因为我们要在这个例子中运用 RMI,所以还有一些新的步骤要做。
首先,为清晰起见,我们把 quartz.properties 文件更名为 server.properties,这时候要告诉 Quartz RMI 服务端去加载新命名的文件而不是默认的 quartz.properties 文件。更改文件名会让我们调试问题变得容易些。这样,我们可以确保 Quartz 加载的是正确的设置文件。
第二个改变是:我们加载了一个新的安全管理器(SecurityManager),以便能够赋予 RMI 服务端必须的权限。我们在本章的前面讨论过 RMI 安全管理器(RMISecurityManager)。
除了这些改变,代码 9.2 中的启动类看起还是很亲切的
代码 9.2. QuartzRMIServer 可用于启动 Quartz RMI 服务
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
package org.cavaness.quartzbook.chapter9; import java.io.BufferedReader; import java.io.InputStreamReader; import java.util.Date; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.quartz.Scheduler; import org.quartz.SchedulerFactory; import org.quartz.impl.StdSchedulerFactory; public class QuartzRMIServer { public void run() throws Exception { Log log = LogFactory.getLog(QuartzRMIServer.class); // Use this properties file instead of quartz.properties System.setProperty("org.quartz.properties", "server.properties"); // RMI with Quartz requires a special security manager if (System.getSecurityManager() == null) { System.setSecurityManager(new java.rmi.RMISecurityManager()); } // Get a reference to the Scheduler Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler(); /* * Due to the server.properties file, our Scheduler will * be exported to RMI Registry automatically. */ scheduler.start(); log.info("Quartz RMI Server started at " + new Date()); log.info("RMI Clients may now access it. "); System.out.println("\n"); System.out.println( "The scheduler will run until you type \"exit\""); BufferedReader rdr = new BufferedReader( new InputStreamReader(System.in)); while (true) { System.out.print("Type 'exit' to shutdown server: "); if ("exit".equals(rdr.readLine())) { break; } } log.info("Scheduler is shutting down..."); scheduler.shutdown(true); log.info("Scheduler has been stopped."); } public static void main(String[] args) throws Exception { QuartzRMIServer example = new QuartzRMIServer(); example.run(); } } |
在代码 9.2 中,安装了 RMISecurityManager 之后,通过工厂方法获得调度器实例,并调用它的 start() 方法。服务端是设计成在控制台运行的,因此一旦调度器启动之后,直至用户在控制台上键入 exit 。接着调度器被关闭也不再为远程的客户端提供服务了。
除了要使用 RMISecurityManager,我们注意到用不着在代码中做任何特别的事情,就能让 Quartz 调度器作为一个远程调度器来用。那些全是托 server.properties 文件的福所致。当调度器被创建后,假如属性文件告诉它这么做,调度器就会把自己导出并注册到 RMI 注册服务器上,并使之可被远程调用。
5. 使用 RMI 注册服务
需要运行一个 RMI 注册服务让客户端能访问到服务对象。你可以选择在命令行下使用 Java 的 rmiregistry 命令来运行注册服务,或者你可以允许 Quartz 自动启动注册服务。完全由你自己选择,但是,假如你没什么偏爱的话,让 Quartz 自已在需要的时候启动注册服务大概要简单些。
假如你要通过命令行启动注册服务,要确保你启动时所用的端口号要与属性文件所指定的一致。要从命令行启动,你应先进入到 <JAVA_HOME>/bin 目录下,然后键入如下命令:
rmiregistry <port>
假如你不指定端口号,会使用默认的 1099。这个默认值与 Quartz 所用的默认端口是一样的。
假如你不想从命令行中运行注册服务,在你为属性 org.quartz.scheduler.rmi.createRegistry 设置了正确值的情况下,Quartz 会自动启动注册服务。看表 9.1,这个属性可取以下几个值:
false (never)
true (as_needed)
always
如果你想要 Quartz 来启动注册服务,为这个属性设置 true 或者 always 即可。
[译者注] 在为“Registry”和“Registry Server” 用词选择上感觉不怎么贴切,如今都是用的“注册服务”与之对等,确也有译作注册表的,但总觉不妥,太容易与 Windows 系统注册表搞混。
本文链接 https://yanbin.blog/quartz-job-scheduling-framework-9-2/, 来自 隔叶黄莺 Yanbin Blog
[版权声明] 本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。