quartz针对web应用提供两种方式配置【servlet、listener】,两种方式均在org.quartz.ee.servlet包中实现。
<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>/conf/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>
对于servlet方式,初始化servlet代码:
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();
}
// Always want to get the scheduler, even if it isn't starting,
// to make sure it is both initialized and registered.
scheduler = factory.getScheduler(); // Should the Scheduler being started now or later
String startOnLoad = cfg
.getInitParameter("start-scheduler-on-load");
int startDelay = 0;
String startDelayS = cfg.getInitParameter("start-delay-seconds");
try {
if(startDelayS != null && startDelayS.trim().length() > 0)
startDelay = Integer.parseInt(startDelayS);
} catch(Exception e) {
log("Cannot parse value of 'start-delay-seconds' to an integer: " + startDelayS + ", defaulting to 5 seconds.", e);
startDelay = 5;
}
/*
* 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())) {
if(startDelay <= 0) {
// Start now
scheduler.start();
log("Scheduler has been started...");
}
else {
// Start delayed
scheduler.startDelayed(startDelay);
log("Scheduler will start in " + startDelay + " seconds.");
}
} else {
log("Scheduler has not been started. Use scheduler.start()");
}
String factoryKey = cfg.getInitParameter("servlet-context-factory-key");
if (factoryKey == null) {
factoryKey = QUARTZ_FACTORY_KEY;
}
log("Storing the Quartz Scheduler Factory in the servlet context at key: "
+ factoryKey);
cfg.getServletContext().setAttribute(factoryKey, factory);
} catch (Exception e) {
log("Quartz Scheduler failed to initialize: " + e.toString());
throw new ServletException(e);
}
由于该servlet不提供get、post请求,所以重点在init方法中。
初始化主要完成两件事:一、通过调度器工厂产生调度器对象;二、启动调度器。
一、工厂如何产生调度器对象?
public Scheduler getScheduler() throws SchedulerException {
if (cfg == null) {
initialize();
}
SchedulerRepository schedRep = SchedulerRepository.getInstance();
Scheduler sched = schedRep.lookup(getSchedulerName());
if (sched != null) {
if (sched.isShutdown()) {
schedRep.remove(getSchedulerName());
} else {
return sched;
}
}
sched = instantiate(); return sched;
}
首先在调度器仓库寻找是否存在未关闭的同名调度器(同名的意思为配置文件中的org.quartz.scheduler.instanceName属性值)【调度器仓库为单态模式】,存在则直接返回,否则实例化调度器,方法在instantiate中加以实现。
instantiate方法做的事情太多【rmi、jmx远程调度器代理、job存储、插件、监听器等等】,下面只对重要的片段进行简述
ThreadPool tp = null;
try {
tp = (ThreadPool) loadHelper.loadClass(tpClass).newInstance();
} catch (Exception e) {
initException = new SchedulerException("ThreadPool class '"
+ tpClass + "' could not be instantiated.", e);
initException
.setErrorCode(SchedulerException.ERR_BAD_CONFIGURATION);
throw initException;
}
tProps = cfg.getPropertyGroup(PROP_THREAD_POOL_PREFIX, true);
try {
setBeanProps(tp, tProps);
} catch (Exception e) {
initException = new SchedulerException("ThreadPool class '"
+ tpClass + "' props could not be configured.", e);
initException
.setErrorCode(SchedulerException.ERR_BAD_CONFIGURATION);
throw initException;
}
……………………
tp.initialize();
线程池SimpleThreadPool初始化(根据org.quartz.threadPool属性组设置,线程池所维护的线程为WorkerThread,是SimpleThreadPool的内部类,主要执行实现JobRunShellFactory的工厂类产生的JobRunShell)
JobRunShellFactory jrsf = null;
if (wrapJobInTx) {
jrsf = new JTAJobRunShellFactory();
} else {
jrsf = new StdJobRunShellFactory();
}
QuartzScheduler qs = null;
qs = new QuartzScheduler(rsrcs, schedCtxt, idleWaitTime, dbFailureRetry);
该对象的建立非常重要,因为在构造函数中新建QuartzSchedulerThread线程对象,此线程建立后,立刻启动。
this.schedThread = new QuartzSchedulerThread(this, resources, ctxt);
QuartzSchedulerThread主要扫描job存储机制,不过有个paused变量控制,即使调用start()方法,也实际上处于停止状态,需要等待QuartzScheduler的start方法触发执行命令:
schedThread.togglePause(false);
Scheduler scheduler = instantiate(rsrcs, qs);
protected Scheduler instantiate(QuartzSchedulerResources rsrcs, QuartzScheduler qs) {
SchedulingContext schedCtxt = new SchedulingContext();
schedCtxt.setInstanceId(rsrcs.getInstanceId());
Scheduler scheduler = new StdScheduler(qs, schedCtxt);
return scheduler;
}
至此,成功获得调度器实例。
二、启动调度器
Scheduler的所有任务都委托给QuartzScheduler执行,则启动调度器的操作在QuartzScheduler的实现为:
public void start() throws SchedulerException {
if (shuttingDown|| closed) {
throw new SchedulerException(
"The Scheduler cannot be restarted after shutdown() has been called.");
}
if (initialStart == null) {
initialStart = new Date();
this.resources.getJobStore().schedulerStarted();
//初始化插件。即初始化quartz.properties中的org.quartz.plugin属性组
startPlugins();
}
//此处代码为schedThread的线程开关 如果paused为true,则线程循环等待
//如果设置为false,且存在job任务则执行
schedThread.togglePause(false);
getLog().info(
"Scheduler " + resources.getUniqueIdentifier() + " started.");
notifySchedulerListenersStarted();
}
startPlugins()实际上是执行已配置插件的start方法。最常见的插件为:
//老版本的配置如v1.5
org.quartz.plugin.jobInitializer.class = org.quartz.plugins.xml.JobInitializationPlugin
org.quartz.plugin.jobInitializer.fileName = conf/quartz_jobs.xml
//新版本的配置如v1.8 可支持多个fileName,以,号分隔
org.quartz.plugin.jobInitializer.class = org.quartz.plugins.xml.XMLSchedulingDataProcessorPlugin
org.quartz.plugin.jobInitializer.fileName = conf/quartz_jobs.xml
以上所配置插件的初始化,实际上就是组装jobDetail和Trigger到JobStrore中,让QuartzSchedulerThread线程轮询
午休了,待续【quartz集群、监听器、远程方式等】……
分享到:
相关推荐
NULL 博文链接:https://smurfs.iteye.com/blog/1155965
Quartz 批量下载源码,Quartz 批量下载源码Quartz 批量下载源码Quartz 批量下载源码Quartz 批量下载源码Quartz 批量下载源码Quartz 批量下载源码Quartz 批量下载源码Quartz 批量下载源码Quartz 批量下载源码
QuartZ源码包
quartz源码包 。。。。。。。。。。。。。。。。。。。。。。。。。。
quartz1.6.0源码包 网上只此一家,不要犹豫了
本项目中包含实验过得一些例子,对于初学Quartz来说很有帮助.
quartz .net 源码,可以编译,对需要了解.net 版quartz的大有益处。
Quartz 开发指南(附源码)Quartz 开发指南(附源码)Quartz 开发指南(附源码)Quartz 开发指南(附源码)
Quartz是一个开源的作业调度框架,它完全由Java写成,并设计用于J2SE和J2EE应用中。它提供了巨大的灵 活性而不牺牲简单性。你能够用它来为执行一个作业而创建简单的或复杂的调度 What's New In Quartz Scheduler ...
Quartz.NET 官方源码
我在博客写了timer和quartz的笔记 附上了全部代码 有兴趣的可以去看博客参照这个代码
Quartz 是一种功能丰富的,开放源码的作业调度库,可以在几乎任何Java应用程序集成 - 从最小的独立的应用程序到规模最大电子商务系统。Quartz可以用来创建简单或复杂的日程安排执行几十,几百,甚至是十万的作业数 -...
quartz集群调度机制调研及源码分析,基于quartz 1.7版本
quartz-3.0.3.1_quartes_源码
Quartz.NET 官方源码及演示例子,官方下载地址:http://sourceforge.net/projects/quartznet/files/quartznet/
1,源码 2,API 3,示例 4,版本为1.6
.net 简单任务调度平台,用于.net dll,exe的任务的挂载,任务的隔离,调度执行,访问权限控制,监控,管理,日志,错误预警,性能分析等
C# quartz.net 定时任务源码,实现了远程操控.动态追加dll,可以安装到windows服务中.
Quartz,集群,配置,源码,多线程 已经打包成jar包,解压即用,十分方便。 有问题请联系QQ:9710846
官方Quartz.NET 2.3.1 源码(官方2015.1.15更新) 附带15个示例 全部可用