• 1. Quartz定时器综合软件开发三部 连勇
  • 2. 2Quartz是什么 Quartz能干什么 Easy example Quartz框架分析 项目开发
  • 3. 3Quartz是什么?Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目,它可以与J2EE与J2SE应用程序相结合也可以单独使用。Quartz可以用来创建简单或为运行十个,百个,甚至是好几万个Jobs这样复杂的日程序表。Jobs可以做成标准的Java组件或 EJBs。 Quartz是一个任务日程管理系统,一个在预先确定(被纳入日程)的时间到达时,负责执行(或者通知)其他软件组件的系统。 Quartz用一个小Java库发布文件(.jar文件),这个库文件包含了所有Quartz核心功能。这些功能的主要接口(API)是Scheduler接口。它提供了简单的操作,例如:将任务纳入日程或者从日程中取消,开始/停止/暂停日程进度。
  • 4. 4Quartz能干什么?场景 #1: 下载交易流水 从银行下载当日交易流水 场景 #2: 邮件提醒和告警 公司出于安全考虑,让每个员工三个月换一次邮箱密码。这种情况下,可以创建一个作业,让它每天午夜运行一次,并且向离过期时间不到三天的所有用户发邮件提醒。这里可以恰到好处的用到作业调度器。图 1.1 描绘了密码这个提醒作业。 图 1.1  密码过期的作业每晚发送邮件给密码很快会过期的用户
  • 5. 5Easy example// First we must get a reference to a scheduler SchedulerFactory sf = new StdSchedulerFactory(); Scheduler sched = sf.getScheduler(); // computer a time that is on the next round minute Date runTime = TriggerUtils.getEvenMinuteDate(new Date()); // define the job and tie it to our HelloJob class JobDetail job = new JobDetail("job1", "group1", HelloJob.class); // Trigger the job to run on the next round minute Trigger trigger = new SimpleTrigger("trigger1", "group1", runTime); // Tell quartz to schedule the job using our trigger sched.scheduleJob(job, trigger); // Start up the scheduler sched.start();
  • 6. 6下载=下载:http://www.quartz-scheduler.org/download/index.html docs/wikidocs Quartz 的帮助文件 docs/api Quartz 框架的JavaDoc Api 说明文档 Examples Quartz 的例子 Lib Quartz 使用到的第三方包 src 源码
  • 7. 7Quartz框架分析核心接口 Scheduler Job JobDetail Trigger JobDataMap
  • 8. 8Scheduler(调度器)A Scheduler maintains a registery of org.quartz.JobDetails and Triggers. Once registered, the Scheduler is responible for executing Job s when their associated Triggers fire (when their scheduled time arrives). void addJob(JobDetail jobDetail, boolean replace) throws SchedulerException; Date scheduleJob(Trigger trigger) throws SchedulerException; Date scheduleJob(JobDetail jobDetail, Trigger trigger) throws SchedulerException; Date rescheduleJob(String triggerName, String groupName, Trigger newTrigger) throws SchedulerException;
  • 9. 9Scheduler(调度器)客服端与调度器交互是通过 org.quartz.Scheduler 接口的。这个 Scheduler 的实现,实际上是一个代理,对其中方法调用会传递到 QuartzScheduler 实例上。QuartzScheduler 处在框架根的位置,它是一个引擎驱动着整个框架。Quartz相当灵活和可配置,许多重要的功能由分离的组件和子框架实现,所以并非所有的功能都直接内建到 QuartzScheduler。这就意味着用户可以用自己某个关键特征实现来替换原有默认实现。
  • 10. 10Scheduler实例化使用scheduler之前应首先实例化它。使用SchedulerFactory可以完成scheduler的实例化。 org.quartz.impl.DirectoSchedulerFactory org.quartz.impl.StdSchedulerFactory StdSchedulerFactory会加载类路径下的quartz.properties 文件。quartz.properties,允许你修改框架运行时环境。缺省是使用Quartz.jar里面的quartz.properties文件。当然,你应该创建一个quartz.properties文件的副本并且把它放入你工程的classes目录中以便类装载器找到它。
  • 11. 11Scheduler启动关闭一旦一个scheduler被实例化,它就可以被启动(start),并且处于驻留模式,直到被关闭(shutdown)。注意,一旦scheduler被关闭(shutdown),则它不能再重新启动,除非重新实例化它。除非scheduler 被启动并且不处于暂停状态,否则触发器不会被触发(任务也不能被执行)。 void start() throws SchedulerException; void startDelayed(int seconds) throws SchedulerException; void shutdown() throws SchedulerException; void shutdown(boolean waitForJobsToComplete) throws SchedulerException;
  • 12. 12Job作业是一个执行任务的简单java类。任务可以是任何java代码。只需你实现org.quartz.Job接口。当Quartz确定该是作业运行的时候,它将调用你的作业。Quartz提供了一个机制来建立具有不同粒度的、可重复的调度表,于是,你只需创建一个java类,这个类被调用而执行任务。 public interface Job { void execute(JobExecutionContext context) throws JobExecutionException; }
  • 13. 13JobDetailJobDetail对象由Quartz客户端在Job被加入到scheduler时创建。它包含了Job的各种设置属性以及一个JobDataMap对象,这个对象被用来存储给定Job类实例的状态信息。Scheduler并不保存真正的Job Class,而是通过JobDetail来保存。 注意,我们给scheduler传入了一个JobDetail实例,而且这个JobDetail实例只是简单提供了类名来引用被执行的Job。每次scheduler执行这个任务时,它就创建这个类的新实例,然后调用该实例的execute(..)方法。Job不必担心线程安全性,因为同一时刻仅有一个线程去执行给定Job类的实例,甚至是并发执行同一Job也是如此。 推断: Job类必须有一个无参数的构造函数 Job类中定义的成员数据失去意义,因为这些成员数据值在每次执行的时候被“清空”了。
  • 14. 14JobFactoryJobFactory控制job的实例化 Job newJob(TriggerFiredBundle bundle) throws SchedulerException; 默认的JobFactory是org.quartz.simpl.SimpleJobFactory,缺省的JobFactory只是简单地对Job类调用newInstance()方法。 设置JobFactory: Scheduler.setJobFactory(factory) 配置quartz.properties的org.quartz.scheduler.jobFactory.class属性设置jobFactory的类型
  • 15. 15JobDataMapJobDataMap被用来保存一系列的(序列化的)对象,这些对象在Job执行时可以得到。JobDataMap是Java Map接口的一个实现,而且还增加了一些存储和读取主类型数据的便捷方法。 JobDetail.getJobDataMap().put("jobSays", "Hello World!"); JobExecutionContext.getJobDetail().getJobDataMap(); Trigger.getJobDataMap(); JobExecutionContext.getMergedJobDataMap();
  • 16. 16StatefulJob有状态任务任务在执行任务过程中,任何对Job Data Map所作的更改都将丢失而且任务下次执行时也无法看到。 StatefulJob在任务的每次执行之后重新存储JobDataMap Job vs. StatefulJob JobDataMap 在每次执行之后重新持久化到 JobStore 中。 两个或多个有状态的 JobDetail 实例不能并发执行。
  • 17. 17TriggerTrigger对象被用来触发jobs的执行。你希望将任务纳入到进度,要实例化一个Trigger并且“调整”它的属性以满足你想要的进度安排。Triggers也有一个JobDataMap与之关联,这非常有利于向触发器所触发的Job传递参数。Quartz打包了很多不同类型的Trigger,但最常用的Trigger类是SimpleTrigger和CronTrigger。
  • 18. 18SimpleTriggerSimpleTrigger用来触发只需执行一次或者在给定时间触发并且重复N次且每次执行延迟一定时间的任务。 如果你想让触发器在2010年1月11日,上午11:23:54秒执行,然后每个隔10秒钟重复执行一次,并且这样重复5次。那么SimpleTrigger 就可以满足你的要求。 public SimpleTrigger(String name, String group, String jobName, String jobGroup, Date startTime, Date endTime, int repeatCount, long repeatInterval);
  • 19. 19CronTrigger如果你需要像日历那样按日程来触发任务,而不是像SimpleTrigger 那样每隔特定的间隔时间触发,CronTriggers通常比SimpleTrigger更有用。 使用CronTrigger,你可以指定诸如“每个周五中午”,或者“每个工作日的9:30”或者“从每个周一、周三、周五的上午9:00到上午10:00之间每隔五分钟”这样日程安排来触发。甚至,象SimpleTrigger一样,CronTrigger也有一个startTime以指定日程从什么时候开始,也有一个(可选的)endTime以指定何时日程不再继续。 public CronTrigger(String name, String group, String jobName, String jobGroup, Date startTime, Date endTime, String cronExpression, TimeZone timeZone) throws ParseException;
  • 20. 20Cron ExpressionsCron表达式被用来配置CronTrigger实例。Cron表达式是一个由7个子表达式组成的字符串。每个子表达式都描述了一个单独的日程细节。这些子表达式用空格分隔,分别表示: Seconds 秒 Minutes 分钟 Hours 小时 Day-of-Month 月中的天 Month 月 Day-of-Week 周中的天 Year (optional field) 年
  • 21. 21TriggerUtilsTriggerUtils 提供了许多便捷的方法简化了构造和配置 trigger。 public static Trigger makeSecondlyTrigger(int intervalInSeconds); public static Trigger makeDailyTrigger(int hour, int minute); public static Trigger makeWeeklyTrigger(int dayOfWeek, int hour, int minute); public static Trigger makeMonthlyTrigger(int dayOfMonth, int hour, int minute); public static Date getNextGivenMinuteDate(Date date, int minuteBase); public static Date getEvenMinuteDate(Date date);
  • 22. 22JobStore作业存储Quartz提供两种基本作业存储类型。 第一种类型叫做RAMJobStore,它利用通常的内存来持久化调度程序信息。这种作业存储类型最容易配置、构造和运行。对许多应用来说,这种作业存储已经足够了。然而,因为调度程序信息是存储在被分配给JVM的内存里面,所以,当应用程序停止运行时,所有调度信息将被丢失。如果你需要在重新启动之间持久化调度信息,则将需要第二种类型的作业存储。 第二种类型的作业存储实际上提供两种不同的实现,但两种实现一般都称为JDBC作业存储。两种JDBC作业存储都需要JDBC驱动程序和后台数据库来持久化调度程序信息。这两种类型的不同在于你是否想要控制数据库事务或这释放控制给应用服务器例如BEA’s WebLogic或Jboss。 org.quartz.impl.jdbcjobstore.JobStoreTX org.quartz.impl.jdbcjobstore.JobStoreCMT
  • 23. 23TriggerListeners和JobListeners 监听器是在scheduler事件发生时能够执行动作的对象。可以看出,TriggerListeners接收与triggers相关的事件,而JobListeners则接收与Job相关的事件。 创建监听器很简单,创建一个实现TriggerListener或JobListener的接口。监听器然后在执行的时候注册到scheduler中,而且必须给定一个名字(或者,它们必须通过他们的getName()方法来介绍自己)。监听器可以被注册为“全局”的或者“非全局”。“全局”监听器接收所有triggers/jobs产生的事件,而“非全局”监听器只接受那些显式指定监听器名的triggers/jobs所产生的事件。 SchedulerListeners只接收与特定trigger 或job无关的Scheduler自身事件通知
  • 24. 24SchedulerPluginQuartz提供了一个接口(org.quartz.spi.SchedulerPlugin)来插入附加的功能。 随Quartz打包儿来的插件有很多有用的功能,它们在org.quartz.plugins包中找到。他们提供了诸如自动安排任务的日程,将任务和触发器事件的历史记入日志以及JVM虚拟机退出时确保干净地关闭scheduler等的功能。 配置quartz.properties的org.quartz.plugin属性设置SchedulerPlugin public interface SchedulerPlugin { public void initialize(String name, Scheduler scheduler) throws SchedulerException; public void start(); public void shutdown(); }
  • 25. 25Quartz 和 Web 应用QuartzInitializerServlet QuartzInitializerListener config-file shutdown-on-unload start-scheduler-on-load start-delay-seconds servlet-context-factory-key
  • 26. 26 config-file /some/path/my_quartz.properties shutdown-on-unload true start-scheduler-on-load true org.quartz.ee.servlet.QuartzInitializerListener
  • 27. 27项目开发
  • 28. 28Thank you!
  • 29. 保密须知:本文件及其书面或其他任何形式的附件乃以保密形式提供,其著作权归属于本公司,仅供阁下内部使用。未经过本公司的审核、确认及书面授权,阁下不得以任何方式在任何媒体(包括互联网)上公开引用或在阁下的任何资料中引用本文件及其附件中的任何数据和信息,不得以任何方式将本文件及其附件中的任何内容提供、披露给其他单位或个人。敬希阁下与我们共同遵守法律。