四. QuartzInitializerServlet 可谓救命草
Quartz 框架包括一个叫做 org.quartz.ee.servlet.QuartzInitializerServlet 的 Java 类,它继承自标准的 HttpServlet。你可应用这个 servlet 于你的 Web 应用中,它将会创建一个 StdSchedulerFactory 实例并在你的程序后续中一直可用。通常的,它就是做了命令行版本的 Quartz 程序的 main() 方法所做的事性。
QuartzInitializerServlet 在 Quartz 1.5 中有所改变在 Quartz 的 1.5 发布版中,QuartzInitializerServlet 被修改为会存储 StdSchedulerFactory 实例到 Web 应用的 ServletContext 中。这就允许你的程序在任何地方都能访问到 Scheduler 实例,只要获取到了 HttpServletRequest 或 HttpSession 对象,调用工厂的 getScheduler() 就访问到了 Scheduler 实例。 还新增了一个 start-scheduler-on-load 的 Servlet 初始化参数。这一参数指定 Scheduler 是否随 QuartzInitializerServlet 启动或是别处启动。假如未设置时默认为 True,Sheduler 将随 QuartzInitializerServlet 起来。否则,你的应用将不得不自己去获得 Scheduler 实例然后调用 start() 方法。 |
当容器加载 QuartzInitializerServlet,该 Servlet 的 init() 方法将被调用。这个 Servlet 读取几个初始化参数,创建 StdSchedulerFactory 类的实例,并使用指定(或默认) 的 Quartz 属性文件来初始化 Scheduler。
工厂创建之后,init() 方法就会决定 Scheduler 是否立即启动,或是让程序来决定何时启动它。代码 3.1 列出了 QuartzInitializerServlet 的 init() 方法。
代码 13.1. QuartzIniializerServlet 类的 init() 方法
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 |
public void init(ServletConfig cfg) throws ServletException { super.init(cfg); log("Quartz Initializer Servlet loaded, initializing Scheduler..."); StdSchedulerFactory factory; try { String configFile = cfg.getInitParameter("config-file"); String shutdownPref = cfg.getInitParameter("shutdown-on-unload"); if (shutdownPref != null) performShutdown = Boolean.valueOf(shutdownPref).booleanValue(); // get Properties if (configFile != null) { factory = new StdSchedulerFactory(configFile); } else { factory = new StdSchedulerFactory(); } // Should the Scheduler being started now or later String startOnLoad = cfg.getInitParameter("start-scheduler-on-load"); /* * If the "start-scheduler-on-load" init-parameter is not specified, * the * scheduler will be started. This is to maintain backwards * compatability. */ if (startOnLoad == null || (Boolean.valueOf(startOnLoad).booleanValue())) { // Start now scheduler = factory.getScheduler(); scheduler.start(); log("Scheduler has been started..."); } else { log("Scheduler has not been started. Use scheduler.start()"); } log( "Storing the Quartz Scheduler Factory in the servlet context at key: " + QUARTZ_FACTORY_KEY); cfg.getServletContext().setAttribute(QUARTZ_FACTORY_KEY, factory); } catch (Exception e) { log("Quartz Scheduler failed to initialize: " + e.toString()); throw new ServletException(e); } } |
QuartzInitializerServlet 是 Quartz JAR 文件的一部分。只要你 Web 应用的 WEB-INF/lib 中有了 quartz.jar,这个 Servlet 在你的应用中就是可用的了。
·配置 Web 部署描述文件
Java Servlet 规范规定了每个 Web 应用都必须包含一个 Web 部署描述文件。部署文件(web.xml) 中包含了以下类型的信息:
·初始化参数
·Session 配置
·Servlet/JSP 定义
·Servlet/JSP 映射
·MIME 类型映射
·欢迎文件
·错误页面
·安全性
因为 QuartzInitializerServlet 是一个 Java Servlet,它必须配置到部署描述文件中让容器来加载它。代码 13.2 描绘了怎样在 web.xml 文件中配置 QuartzInitializerServlet。
代码 13.2. QuartzInitializerServlet 需要对 web.xml 文件作相应的修改
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 |
<web-app> <servlet> <servlet-name>QuartzInitializer</servlet-name> <display-name>Quartz Initializer Servlet</display-name> <servlet-class> org.quartz.ee.servlet.QuartzInitializerServlet </servlet-class> <load-on-startup>1</load-on-startup> <init-param> <param-name>config-file</param-name> <param-value>/some/path/my_quartz.properties</param-value> </init-param> <init-param> <param-name>shutdown-on-unload</param-name> <param-value>true</param-value> </init-param> <init-param> <param-name>start-scheduler-on-load</param-name> <param-value>true</param-value> </init-param> </servlet> <! other web.xml items here > </web-app> |
QuartzInitializerServlet 支持三个 Quartz 规范的初始化参数
初始化参数 config-file
config-file 参数用来指定 Quartz 属性文件的路径和文件名。StdSchedulerFactory 使用这个文件配置 Scheduler 实例。这个参数是可选的;假如未指定,就会用默认的 quartz.properties 文件。使用此参数最简单的方式(假定你想提供自己的属性文件) 是把你的属性文件放到 WEB-INF/classes 目录中,然后如下方式指定 init-param:
1 2 3 4 |
<init-param> <param-name>config-file</param-name> <param-value>/my_quartz.properties</param-value> </init-param> |
初始化参数 shutdown-on-unload
shutdown-on-unload 参数用于在容器卸载本 Servlet 时引起 scheduler.shutdown() 方法的调用。一个容器在关闭,或某种条件时,在一个热部署环境中重新加载时就会卸载这个 Servlet。这个参数是可选的,默认值是 true。
初始化参数 start-scheduler-on-load
start-scheduler-on-load 参数用于告诉 Servlet 调用 Scheduler 实例的 start() 方法。假如它没有启动,Scheduler 就需要由程序在晚些时候来启动,在 start() 未被调用之前是不会有 Job 运行的。这一参数是可选的,如果未指定时默认为 true。这个参数是在 1.5 发行版中加载来,不存在于早期版本中。
·访问 SchedulerFactory 和 Scheduler
自 Quartz 1.5 开始,QuartzInitializerservlet 将自动将 StdSchedulerFactory 实例以某一预定义键存放于 ServletContext 中。
早期 Quartz 版本中的 QuartzInitializerServlet QuartzInitializerServlet 在早期版本的框架中就出现了。在以往版本中,StdSchedulerFactory 不会存放到 ServletContext 中。Sheduler 在 Servlet 的 init() 方法中初始化后即启动。欲从你的代码中获取 Scheduler 实例,你必须使用 StdSchedulerFactory 的某个 get 方法访问该 Servlet 创建的 Scheduler。从 ServletContext 中访问 Scheduler 的改变是在 1.5 版中加进来的。 |
你可在代码 13.1 的 init() 方法结束部分看出来。一旦工厂被存入 ServletContext,有多种方式可以获取访问到它。最简单的方式,尤其是你在用 Struts 框架的时候,是使用 request 对象。代码 13.3 展示了一个 Struts Action 类,叫做 StartSchedulerAction。当这个 Action 被调用(假定是通过 /startscheduler.do 这样的 URL 来访问),SchedulerFactory 就能获取取,接着可以调用 getScheduler() 方法。
代码 13.3. SchedulerFactory 和 Scheduler 能简单的被访问
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 |
import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.struts.action.Action; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; import org.cavaness.jobconsole.web.QuartzFactoryServlet; import org.cavaness.jobconsole.web.WebConstants; import org.quartz.Scheduler; import org.quartz.impl.StdSchedulerFactory; public class StartSchedulerAction extends Action { public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { // Retrieve the ServletContext ServletContext ctx = request.getSession().getServletContext(); // Retrieve the factory from the ServletContext StdSchedulerFactory factory = (StdSchedulerFactory) ctx.getAttribute( QuartzFactoryServlet.QUARTZ_FACTORY_KEY); // Retrieve the scheduler from the factory Scheduler scheduler = factory.getScheduler(); // Start the scheduler scheduler.start(); // Forward to success page return mapping.findForward(WebConstants.SUCCESS); } } |
当从 SchedulerFactory 获取到 Scheduler 之后,你就可以按正常方式般调用 Scheduler 实例的方法。在代码 13.3 中,Scheduler 是使用 start() 方法来启动的,这是你所习惯的。
把 StdSchedulerFactory 存于 ServletContext 中的优点是避免了你重复创建它。实际上,你可以使得访问 Scheduler 甚至更简单,做法是把所有访问 ServletContext 和创建 Scheduler 的逻辑放到一个工具类中。代码 13.4 展示了这样一个名为 ActionUtil 的类,它简化了获得一个 Scheduler 对象的引用。
代码 13.4. ActionUtil 类方便了访问 Scheduler
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; import org.quartz.Scheduler; import org.quartz.SchedulerException; import org.quartz.impl.StdSchedulerFactory; public class ActionUtil { public static Scheduler getScheduler(HttpServletRequest request) throws SchedulerException { ServletContext ctx = request.getSession().getServletContext(); StdSchedulerFactory factory = (StdSchedulerFactory) ctx.getAttribute( QuartzFactoryServlet.QUARTZ_FACTORY_KEY); return factory.getScheduler(); } } |
你能使用 ActionUtil.getScheduler() 方法很方便的获取到 Scheduler 实例。代码 13.3 中接下来的片断就是类 StartSchedulerAction 如何使用 Action.getScheduler() 方法了:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
public class StartSchedulerAction extends Action { public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { // Retrieve the scheduler from the factory Scheduler scheduler = ActionUtil.getScheduler(); // Start the scheduler scheduler.start(); // Forward to success page return mapping.findForward(WebConstants.SUCCESS); } } |
代码 13.4 中的 ActionUtil 并非 Quartz 框架的一部份,但它或许会被加入到将来的版本中。你可在你的应用中需要的时候加入相同的东西。
本文链接 https://yanbin.blog/quartz-job-scheduling-framework-13-3/, 来自 隔叶黄莺 Yanbin Blog
[版权声明] 本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。
org.cavaness.jobconsole.web.QuartzFactoryServlet
这只是说的一个虚拟的 Job Console 的项目中,假定为自己实现的一个 QuartzFactoryServlet 类,旨在启用 Web 应用时初始化一个 SchedulerFactory 放在 ServletContext 中。原文并未对它进它进行深入,所以你可以自己去实现它;或者不用去理会它,这里只用了 QuartzFactoryServlet.QUARTZ_FACTORY_KEY 这么一个常,为的是以此键把 ScehdulerFactory 放在 ServletContext 中,方便应用随时取用。
哦,这样呀,谢谢了,再研究研究