Quarz入门讲解(不错的例子)
- 格式:docx
- 大小:27.93 KB
- 文档页数:7
Quartz学习--quartz基本介绍和Cron表达式表名称说明qrtz_blob_triggers Trigger作为Blob类型存储(⽤于Quartz⽤户⽤JDBC创建他们⾃⼰定制的Trigger类型,JobStore 并不知道如何存储实例的时候)qrtz_calendars以Blob类型存储Quartz的Calendar⽇历信息, quartz可配置⼀个⽇历来指定⼀个时间范围负责执⾏向QuartzScheduler注册的触发Trigger的⼯作线程ThreadPool :Scheduler使⽤⼀个线程作为任务运⾏的基础设施,任务通过共享线程池中的线程提⾼运⾏效率QuartzSchedulerResources :包含穿件QuartzScheduler实例所需的所有资源(JobStore,ThreadPool等)JobStore :通过类实现的接⼝,这些类要为org.quartz.core.QuartzScheduler的使⽤提供⼀个org.quartz.Job和org.quartz.Trigger存储机制.作业和触发器的存储应该以其名称和组的组合为唯⼀性QuartzScheduler :Quartz的核⼼,他是org.quartz.Scheduler接⼝的间接实现,包含调度org.quartz.Jobs ,注册org.quartz.JobListener实例等的⽅法Scheduler :这是Quartz Scheduler的主要接⼝,代表⼀个独⽴运⾏容器. 调度程序维护JobDetails和触发器的注册表.⼀旦注册,调度程序负责执⾏作业,当她们的相关连的触发器触发(当她们的预定时间到达时 )Trigger:具有所有触发器通⽤属性的基本接⼝,描述了job执⾏的时间触发规则,使⽤TriggerBuilder实例化实际触发器JobDetail :传递给定作业实例的详细信息属性.JobDetails将使⽤JobBuilder创建/定义Job :表⽰要执⾏的"作业"的类的实现接⼝.只有⼀个⽅法:void execute(JobExecutionContext context);(JobExecutionContext 提供调度上下⽂各种信息,运⾏时数据保存在jobDataMap中 )Job 有个⼦接⼝StatefulJob,代表没有状态任务有状态任务不可并发,前次任务没有执⾏完,后⾯任务则⼀直处于阻塞等待状态2. ⼀个job可以被多个Trigger 绑定,但是⼀个Trigger只能绑定⼀个job!7. quartz.properties Quartz可更改配置//调度标识名集群中每⼀个实例都必须使⽤相同的名称(区分特定的调度器实例)org.quartz.scheduler.instanceName:DefaultQuartzScheduler//ID设置为⾃动获取每⼀个必须不同(所有调度器实例中是唯⼀的)org.quartz.scheduler.instanceId :AUTO//数据保存⽅式为持久化org.quartz.jobStore.class :org.quartz.impl.jdbcjobstore.JobStoreTX//表的前缀org.quartz.jobStore.tablePrefix : QRTZ_//设置为TRUE不会出现序列化⾮字符串类到 BLOB 时产⽣的类版本问题//eProperties : true//加⼊集群 true 为集群 false不是集群org.quartz.jobStore.isClustered : false//调度实例失效的检查时间间隔org.quartz.jobStore.clusterCheckinInterval:20000//容许的最⼤作业延长时间org.quartz.jobStore.misfireThreshold :60000//ThreadPool 实现的类名org.quartz.threadPool.class:org.quartz.simpl.SimpleThreadPool//线程数量org.quartz.threadPool.threadCount : 10//线程优先级org.quartz.threadPool.threadPriority : 5(threadPriority 属性的最⼤值是常量 ng.Thread.MAX_PRIORITY,等于10。
详细讲解Quartz如何从入门到精通Quartz是一个开源的作业调度框架它完全由Java写成并设计用于J SE和J EE应用中它提供了巨大的灵活性而不牺牲简单性你能够用它来为执行一个作业而创建简单的或复杂的调度它有很多特征如数据库支持集群插件EJB作业预构建JavaMail及其它支持cron like 表达式等等你曾经需要应用执行一个任务吗?这个任务每天或每周星期二晚上或许仅仅每个月的最后一天执行一个自动执行而无须干预的任务在执行过程中如果发生一个严重错误应用能够知到其执行失败并尝试重新执行吗?你和你的团队是用Java编程吗?如果这些问题中任何一个你回答是那么你应该使用Quartz调度器旁注 Matrix目前就大量使用到了Quartz 比如排名统计功能的实现在Jmatrix里通过Quartz定义了一个定时调度作业在每天凌晨一点作业开始工作重新统计大家的Karma和排名等还有 RSS文件的生成也是通过Quartz定义作业每隔半个小时生成一次RSS XML文件Quartz让作业调度简单Quartz是一个完全由Java编写的开源作业调度框架不要让作业调度这个术语吓着你尽管Quartz框架整合了许多额外功能但就其简易形式看你会发现它易用得简直让人受不了!简单地创建一个实现quartz Job接口的Java类 Job接口包含唯一的方法在你的Job接口实现类里面添加一些逻辑到execute()方法一旦你配置好Job实现类并设定好调度时间表 Quartz将密切注意剩余时间当调度程序确定该是通知你的作业的时候 Quartz框架将调用你Job实现类(作业类)上的execute()方法并允许做它该做的事情无需报告任何东西给调度器或调用任何特定的东西仅仅执行任务和结束任务即可如果配置你的作业在随后再次被调用 Quartz框架将在恰当的时间再次调用它如果你使用了其它流行的开源框架象struts 你会对Quartz的设计和部件感到舒适虽然两个开源工程是解决完全不同的问题还是有很多相似的之处就是开源软件用户每天感觉很舒适Quartz能用在单机J SE应用中作为一个RMI服务器也可以用在web应用中甚至也可以用在J EE应用服务器中Quartz的发展史尽管Quartz今年开始受到人们注意但还是暂时流行Quartz由James House创建并最初于年春天被加入sourcefe工程接下来的几年里有许多新特征和版本出现但是直到项目迁移到新的站点并成为OpenSymphony项目家族的一员才开始真正启动并受到应有的关注James House仍然和几个协助他的业余开发者参与大量开发工作Quartz开发团队今年能发布几个新版本包括当前正处在候选发布阶段的版上手QuartzQuartz工程驻留在OpenSymphony站点上在Quartz站点上可以找到许多有用的资源 JavaDocs 包含指南的文档 CVS访问用户和开发者论坛的连接当然也有下载从下载连接取得Quartz的发布版本并且解压到到本地目录这个下载文件包含了一个预先构建好的Quartz二进制文件(quartz jar)你可以将它放进自己的应用中Quartz框架只需要少数的第三方库并且这些三方库是必需的你很可能已经在使用这些库了你要把Quartz的安装目录的/lib/core 和 /lib/optional目录中的第三方库加进你自己的工程中大多数第三方库是我们所熟知和喜欢的标准Jakarta Commons库像Commons Logging Commons BeantUtils等等quartz properties文件Quartz有一个叫做quartz properties的配置文件它允许你修改框架运行时环境缺省是使用Quartz jar里面的quartz properties文件当然你应该创建一个quartz properties文件的副本并且把它放入你工程的classes目录中以便类装载器找到它一旦将Quartz jar文件和第三方库加到自己的工程里面并且quartz properties文件在工程的classes目录中就可以创建作业了然而在做这之前我们暂且回避一下先简短讨论一下Quartz架构Quartz内部架构在规模方面 Quartz跟大多数开源框架类似大约有个Java类和接口并被组织到个包中这可以和Apache Struts把大约个类和接口以及组织到个包中相比尽管规模几乎不会用来作为衡量框架质量的一个特性但这里的关键是quarts内含很多功能这些功能和特性集是否成为或者应该成为评判一个开源或非开源框架质量的因素Quartz调度器Quartz框架的核心是调度器调度器负责管理Quartz应用运行时环境调度器不是靠自己做所有的工作而是依赖框架内一些非常重要的部件 Quartz不仅仅是线程和线程管理为确保可伸缩性 Quartz采用了基于多线程的架构启动时框架初始化一套worker线程这套线程被调度器用来执行预定的作业这就是Quartz怎样能并发运行多个作业的原理 Quartz依赖一套松耦合的线程池管理部件来管理线程环境本文中我们会多次提到线程池管理但Quartz里面的每个对象是可配置的或者是可定制的所以例如如果你想要 *** 自己线程池管理设施我猜你一定能!作业用Quartz的行话讲作业是一个执行任务的简单Java类任务可以是任何Java代码只需你实现 quartz Job接口并且在出现严重错误情况下抛出JobExecutionException异常即可Job接口包含唯一的一个方法execute() 作业从这里开始执行一旦实现了Job接口和execute()方法当Quartz确定该是作业运行的时候它将调用你的作业Execute()方法内就完全是你要做的事情下面有一些你要在作业里面做事情的例子· 用JavaMail(或者用其他的像Commons Net一样的邮件框架)发送邮件· 创建远程接口并且调用在EJB上的方法· 获取Hibernate Session 查询和更新关系数据库里的数据· 使用OSWorkflow并且从作业调用一个工作流· 使用FTP和到处移动文件· 调用Ant构建脚本开始预定构建这种可能性是无穷的正事这种无限可能性使得框架功能如此强大Quartz给你提供了一个机制来建立具有不同粒度的可重复的调度表于是你只需创建一个Java类这个类被调用而执行任务作业管理和存储作业一旦被调度调度器需要记住并且跟踪作业和它们的执行次数如果你的作业是分钟后或每秒调用这不是很有用事实上作业执行需要非常准确和即时调用在被调度作业上的execute()方法Quartz通过一个称之为作业存储(JobStore)的概念来做作业存储和管理有效作业存储Quartz提供两种基本作业存储类型第一种类型叫做RAMJobStore 它利用通常的内存来持久化调度程序信息这种作业存储类型最容易配置构造和运行对许多应用来说这种作业存储已经足够了然而因为调度程序信息是存储在被分配给JVM的内存里面所以当应用程序停止运行时所有调度信息将被丢失如果你需要在重新启动之间持久化调度信息则将需要第二种类型的作业存储第二种类型的作业存储实际上提供两种不同的实现但两种实现一般都称为JDBC作业存储两种JDBC作业存储都需要JDBC驱动程序和后台数据库来持久化调度程序信息这两种类型的不同在于你是否想要控制数据库事务或这释放控制给应用服务器例如BEA s WebLogic 或Jboss (这类似于J EE领域中Bean管理的事务和和容器管理事务之间的区别)这两种JDBC作业存储是· JobStoreTX 当你想要控制事务或工作在非应用服务器环境中是使用· JobStoreCMT 当你工作在应用服务器环境中和想要容器控制事务时使用JDBC作业存储为需要调度程序维护调度信息的用户而设计作业和触发器Quartz设计者做了一个设计选择来从调度分离开作业Quartz中的触发器用来告诉调度程序作业什么时候触发框架提供了一把触发器类型但两个最常用的是SimpleTrigger和CronTrigger SimpleTrigger 为需要简单打火调度而设计典型地如果你需要在给定的时间和重复次数或者两次打火之间等待的秒数打火一个作业那么SimpleTrigger适合你另一方面如果你有许多复杂的作业调度那么或许需要CronTriggerCronTrigger是基于Calendar like调度的当你需要在除星期六和星期天外的每天上午点半执行作业时那么应该使用CronTrigger 正如它的名字所暗示的那样 CronTrigger是基于Unix克隆表达式的作为一个例子下面的Quartz克隆表达式将在星期一到星期五的每天上午点分执行一个作业* MON FRI下面的表达式* L将在年到年的每个月的最后一个星期五上午点分执行作业你不可能用SimpleTrigger来做这些事情你可以用两者之中的任何一个但哪个跟合适则取决于你的调度需要调度一个作业让我们通过看一个例子来进入实际讨论现假定你管理一个部门无论何时候客户在它的FTP服务器上存储一个文件都得用电子邮件通知它我们的作业将用FTP登陆到远程服务器并下载所有找到的文件然后它将发送一封含有找到和下载的文件数量的电子邮件这个作业很容易就帮助人们整天从手工执行这个任务中解脱出来甚至连晚上都无须考虑我们可以设置作业循环不断地每秒检查一次而且工作在× 模式下这就是Quartz框架完全的用途首先创建一个Job类将执行FTP和Email逻辑下例展示了Quartz 的Job类它实现了 quartz Job接口我们故意让ScanFTPSiteJob保持很简单我们为这个例子创建了一个叫做JobUtil的实用类它不是Quartz的组成部分但对构建各种作业能重用的实用程序库来说是有意义的我们可以轻易将那种代码组织进作业类中 quarts 调度器一样好用因为我们一直在使用quarts 所以那些代码可继续重用JobUtil checkForFiles() and JobUtil sendEmail()方法使用的参数是Quartz创建的JobDataMap的实例实例为每个作业的执行而创建它是向作业类传递配置参数的方法这里并没有展示JobUtil的实现但我们能用Jakarta上的Commons Net轻易地实现FTP和Email功能用调度器调用作业首先创建一个作业但为使作业能被调度器调用你得向调度程序说明你的作业的调用时间和频率这个事情由与作业相关的触发器来完成因为我们仅仅对大约每秒循环调用作业感兴趣所以打算使用SimpleTrigger作业和触发器通过Quartz调度器接口而被调度我们需要从调度器工厂类取得一个调度器的实例最容易的办法是调用StdSchedulerFactory这个类上的静态方法getDefaultScheduler() 使用Quartz框架你需要调用start()方法来启动调度器例的代码遵循了大多数Quartz应用的一般模式创建一个或多个作业创建和设置触发器用调度器调度作业和触发器启动调度器编程调度同声明性调度我们通过编程的方法调度我们的ScanFTPSiteJob作业就是说我们用Java代码来设置作业和触发器Quartz框架也支持在xml文件里面申明性的设置作业调度申明性方法允许我们更快速地修改哪个作业什么时候被执行Quartz框架有一个插件这个插件负责读取xml配置文件xml配置文件包含了关于启动Quartz应用的作业和触发器信息所有xml文件中的作业连同相关的触发器都被加进调度器你仍然需要编写作业类但配置那些作业类的调度器则非常动态化你可以将xml文件中的元素跟例代码作个比较它们从概念上来看是相同的使用申明性方法的好处是维护变得极其简单只需改变xml配置文件和重新启动Quartz应用即可无须修改代码无须重新编译无须重新部署有状态和无状态作业在本文中你所看到的作业到是无状态的这意味着在两次作业执行之间不会去维护作业执行时JobDataMap的状态改变如果你需要能增删改JobDataMap的值而且能让作业在下次执行时能看到这个状态改变则需要用Quartz有状态作业如果你是一个有经验的EJB开发者的话深信你会立即退缩因为有状态带有负面含义这主要是由于EJB带来的伸缩性问题Quartz有状态作业实现了 quartz StatefulJob接口无状态和有状态作业的关键不同是有状态作业在每次执行时只有一个实例大多数情况下有状态的作业不回带来大的问题然而如果你有一个需要频繁执行的作业或者需要很长时间才能完成的作业那么有状态作业可能给你带来伸缩性问题Quartz框架的其他特征Quartz框架有一个丰富的特征集事实上quarts有太多特性以致不能在一种情况中全部领会下面列出了一些有意思的特征但没时间在此详细讨论监听器和插件每个人都喜欢监听和插件今天几乎下载任何开源框架你必定会发现支持这两个概念监听是你创建的Java类当关键事件发生时会收到框架的回调例如当一个作业被调度没有调度或触发器终止和不再打火时这些都可以通过设置来来通知你的监听器Quartz框架包含了调度器监听作业和触发器监听你可以配置作业和触发器监听为全局监听或者是特定于作业和触发器的监听一旦你的一个具体监听被调用你就能使用这个技术来做一些你想要在监听类里面做的事情例如你如果想要在每次作业完成时发送一个电子邮件你可以将这个逻辑写进作业里面也可以JobListener里面写进JobListener的方式强制使用松耦合有利于设计上做到更好Quartz插件是一个新的功能特性无须修改Quartz源码便可被创建和添加进Quartz框架他为想要扩展Quartz框架又没有时间提交改变给Quartz开发团队和等待新版本的开发人员而设计如果你熟悉Struts插件的话那么完全可以理解Quartz插件的使用与其Quartz提供一个不能满足你需要的有限扩展点还不如通过使用插件来拥有可修整的扩展点集群Quartz应用Quartz应用能被集群是水平集群还是垂直集群取决于你自己的需要集群提供以下好处· 伸缩性· 搞可用性· 负载均衡目前Quartz只能借助关系数据库和JDBC作业存储支持集群将来的版本这个制约将消失并且用RAMJobStore集群将是可能的而且将不需要数据库的支持Quartz web应用使用框架几个星期或几个月后 Quartz用户所显示的需求之一是需要集成Quartz到图形用户界面中目前Quartz框架已经有一些工具允许你使用Java servlet来初始化和启动Quartz 一旦你可以访问调度器实例你就可以把它存储在web容器的servlet上下文中(ServletContext中)并且可以通过调度器接口管理调度环境幸运的是一些开发者已正影响着单机Quartz web应用它用来更好地管理调度器环境构建在若干个流行开源框架如Struts和Spring 之上的图形用户界面支持很多功能这些功能都被包装进一个简单接口Quartz的下一步计划Quartz是一个活动中的工程Quartz开发团队明确表示不会停留在已有的荣誉上Quartz下一个主要版本已经在启动中你可以在OpenSymphony的wiki上体验一下Quartz 的设计和特征总之Quartz用户每天都自由地添加特性建议和设计创意以便能被核心框架考虑(看重)了解更多Quartz特征lishixinzhi/Article/program/Java/ky/201311/27892。
quartz基本介绍和使⽤⼀、什么是quartz,有什么⽤。
Quartz是⼀个完全由java编写的开源作业调度框架,由OpenSymphony组织开源出来。
所谓作业调度其实就是按照程序的设定,某⼀时刻或者时间间隔去执⾏某个代码。
最常⽤的就是报表的制作了。
⼆、quartz的简单事例public class HelloJob implements Job {@Overridepublic void execute(JobExecutionContext context) throws JobExecutionException {Object tv1 = context.getTrigger().getJobDataMap().get("t1");Object tv2 = context.getTrigger().getJobDataMap().get("t2");Object jv1 = context.getJobDetail().getJobDataMap().get("j1");Object jv2 = context.getJobDetail().getJobDataMap().get("j2");Object sv = null;try {sv = context.getScheduler().getContext().get("skey");} catch (SchedulerException e) {e.printStackTrace();}System.out.println(tv1+":"+tv2);System.out.println(jv1+":"+jv2);System.out.println(sv);System.out.println("hello:"+LocalDateTime.now());}}public class Test {public static void main(String[] args) throws SchedulerException {//创建⼀个schedulerScheduler scheduler = StdSchedulerFactory.getDefaultScheduler();scheduler.getContext().put("skey", "svalue");//创建⼀个TriggerTrigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1").usingJobData("t1", "tv1").withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(3).repeatForever()).build();trigger.getJobDataMap().put("t2", "tv2");//创建⼀个jobJobDetail job = JobBuilder.newJob(HelloJob.class).usingJobData("j1", "jv1").withIdentity("myjob", "mygroup").build();job.getJobDataMap().put("j2", "jv2");//注册trigger并启动schedulerscheduler.scheduleJob(job,trigger);scheduler.start();}}⼆、quartz的基本组成 1、调度器--------------Scheduler Scheduler被⽤来对Trigger和Job进⾏管理。
Quartz用法一、什么是Quartz?Quartz是一个功能强大且广泛应用于Java中的开源任务调度框架。
它允许开发人员通过简单而灵活的方式在应用程序中调度和执行任务。
无论是简单的定时任务还是复杂的作业调度,Quartz都可以满足需求。
二、Quartz的基本概念在深入探讨Quartz的用法之前,我们首先需要了解一些基本概念。
1. 作业(Job)作业是Quartz中最基本的调度单元。
它表示一项任务或一个操作,可以被Quartz 调度和执行。
2. 触发器(Trigger)触发器是Quartz中用于指定作业何时执行的组件。
可以根据时间表达式(如每小时、每天等)来触发作业的执行,也可以根据特定的日期和时间来触发。
3. 调度器(Scheduler)调度器是Quartz的核心组件,它负责在指定的时间触发作业的执行。
调度器可以同时管理多个作业和触发器,并根据设定的调度策略来决定执行顺序。
三、Quartz的用法接下来,我们将深入探讨Quartz的用法,包括作业和触发器的创建、调度器的配置和管理。
1. 创建作业要创建一个作业,我们需要定义一个类,实现Quartz的Job接口,并重写其中的execute()方法。
在execute()方法中,我们可以编写具体的任务逻辑。
例如:public class MyJob implements Job {public void execute(JobExecutionContext context) throws JobExecutionExcept ion {// 编写具体的任务逻辑}}2. 创建触发器Quartz提供了多种触发器类型,可以根据需求灵活选择。
其中最常用的是SimpleTrigger和CronTrigger。
•SimpleTrigger:简单触发器会在指定的时间间隔内循环执行作业。
可以设置作业的开始时间、结束时间和重复次数。
•CronTrigger:基于Cron表达式触发器允许我们非常灵活地指定作业的执行时间。
定时任务框架Quartz简单⼊门⽬录⼀、什么是QuartzQuartz是OpenSymphony开源组织在Job scheduling领域⼜⼀个开源项⽬,完全由Java开发,可以⽤来执⾏定时任务,类似于java.util.Timer。
但是相较于Timer, Quartz增加了很多功能:持久性作业 - 就是保持调度定时的状态;作业管理 - 对调度作业进⾏有效的管理;⼤部分公司都会⽤到定时任务这个功能。
【举个例⼦】拿⽕车票购票来说,当你下单后,后台就会插⼊⼀条待⽀付的task(job),⼀般是30分钟,超过30min后就会执⾏这个job,去判断你是否⽀付,未⽀付就会取消此次订单;当你⽀付完成之后,后台拿到⽀付回调后就会再插⼊⼀条待消费的task(job),Job触发⽇期为⽕车票上的出发⽇期,超过这个时间就会执⾏这个job,判断是否使⽤等。
在我们实际的项⽬中,当Job过多的时候,肯定不能⼈⼯去操作,这时候就需要⼀个任务调度框架,帮我们⾃动去执⾏这些程序。
那么该如何实现⾃动执⾏这些程序的功能呢?(1)⾸先我们需要定义实现⼀个定时功能的接⼝,我们可以称之为Task(或Job),如定时发送邮件的task(Job),重启机器的task(Job),优惠券到期发送短信提醒的task(Job),实现接⼝如下:(2)有了任务之后,还需要⼀个能够实现触发任务去执⾏的触发器,触发器Trigger最基本的功能是指定Job的执⾏时间,执⾏间隔,运⾏次数等。
(3)有了Job和Trigger后,怎么样将两者结合起来呢?即怎样指定Trigger去执⾏指定的Job呢?这时需要⼀个Schedule,来负责这个功能的实现。
上⾯三个部分就是Quartz的基本组成部分:调度器:Scheduler任务:JobDetail触发器:Trigger,包括SimpleTrigger和CronTrigger⼆、Quartz搭建案例1、导⼊依赖的jar包<!-- https:///artifact/org.quartz-scheduler/quartz --><dependency><groupId>org.quartz-scheduler</groupId><artifactId>quartz</artifactId><version>2.3.0</version></dependency>2、新建⼀个能够打印任意内容的Job:// 打印任意内容public class PrintWordsJob implements Job{@Overridepublic void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {String printTime = new SimpleDateFormat("yy-MM-dd HH-mm-ss").format(new Date());System.out.println("PrintWordsJob start at:" + printTime + ", prints: Hello Job-" + new Random().nextInt(100)); }}3、创建Schedule,执⾏任务:public class MyScheduler {public static void main(String[] args) throws SchedulerException, InterruptedException {// 1、创建调度器SchedulerSchedulerFactory schedulerFactory = new StdSchedulerFactory();Scheduler scheduler = schedulerFactory.getScheduler();// 2、创建JobDetail实例,并与PrintWordsJob类绑定(Job执⾏内容)JobDetail jobDetail = JobBuilder.newJob(PrintWordsJob.class).withIdentity("job1", "group1").build();// 3、构建Trigger实例,每隔1s执⾏⼀次Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "triggerGroup1").startNow()//⽴即⽣效.withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(1)//每隔1s执⾏⼀次.repeatForever())//⼀直执⾏.build();//4、执⾏scheduler.scheduleJob(jobDetail, trigger);System.out.println("--------scheduler start ! ------------");scheduler.start();// 5、停⽌执⾏TimeUnit.MINUTES.sleep(1);scheduler.shutdown();System.out.println("--------scheduler shutdown ! ------------");}}运⾏程序,可以看到程序每隔1s会打印出内容,会在⼀分钟后结束:三、Quartz核⼼详解下⾯就程序中出现的⼏个参数,看⼀下Quartz框架中的⼏个重要参数:Job和JobDetailJobExecutionContextJobDataMapTrigger、SimpleTrigger、CronTrigger(1)Job和JobDetailJob是Quartz中的⼀个接⼝,接⼝下只有execute⽅法,在这个⽅法中编写业务逻辑。
Quartz核心概念:调度器、触发器、作业[谁什么时候干什么活]任务调度Quartz(!)为何需要任务调度?在web应用中,大多数任务是以一种"防止用户长时间等待"的方式完成的。
在Google搜索这样的例子中,减少等待时间对用户体验来说至关重要。
异步任务的一种解决方案是在用户提交后生成一个线程(来处理异步任务),但这也不能解决那些需要以一定时间间隔重复运行任务、或在每天的指定时间运行任务的情况。
让我们从一个数据库报表的例子来看看任务调度能如何帮助改善系统设计。
报表可能是错综复杂的,这取决于用户所需数据的种类,以及是否需要从一个或多个数据库收集大量数据。
用户可能需要很长时间来运行这样的"按需"报表。
因此,我们向这个报表示例中添加任务调度机制,以便用户可以安排在任何他们需要的时间生成报表,并以PDF或其他格式在email中发送。
用户可以让报表在每天的凌晨2:22,系统正处于低负荷时运行;也可以选择只在特定时间运行一次。
通过在报表应用中加入任务调度,我们可以为产品添加一项有用的功能,并改善用户体验。
幸运的是,有一个强大的开源解决方案可以让我们以标准的方式在web应用(或任何Java应用)中实施任务调度。
以下示例展示了在web应用中,如何使用Quartz来创建一个任务调度框架。
这个示例还使用了Struts Action framework 插件,以便在web应用启动时初始化任务调度机制。
Struts是最常见的MVC框架,为大多数开发人员所熟悉。
当然除此之外还有许多框架可以协助在web应用中实现MVC模式。
启动时初始化任务调度器我们首先要做的是建立一个Struts插件,让它在容器启动时创建我们的任务调度器。
在以下例子中,我们选择Tomcat作为web应用容器,不过这些示例在其他容器中也应当可以运行。
我们要创建一个Struts插件类,并在struts-config.xml中加入几行代码以使之可以工作。
Quartz的基本使⽤之⼊门(2.3.0版本)⼀、Quartz可以⽤来做什么Quartz是⼀个强⼤任务调度框架,我⼯作时候会在这些情况下使⽤到quartz框架,当然还有很多的应⽤场景,在这⾥只列举2个实际⽤到的餐厅系统会在每周四晚上的22点⾃动审核并⽣成报表⼈事系统会在每天早晨8点给有待办的⼈员⾃动发送Email提醒⼆、使⽤Quartz之前的准备1.建⽴⼀个Maven项⽬2.引⼊quartz的依赖 但然也可以使⽤这个2.3.0的依赖,下⾯的例⼦都是使⽤此依赖并实现了效果。
<!-- https:///artifact/org.quartz-scheduler/quartz --><dependency><groupId>org.quartz-scheduler</groupId><artifactId>quartz</artifactId><version>2.3.0</version></dependency>三、编写第⼀个Quartz任务案例 - 每隔2秒钟打印⼀次HelloQuartz先实现⼀下这个基本的Quartz的任务再来介绍⼀下Quartz的3个重要组成,JobDetail,Trigger,Scheduler1.创建⼀个类 HelloJob.java,这个类是编写我们的具体要实现任务(打印Hello Quartz)import org.quartz.Job;import org.quartz.JobExecutionContext;import org.quartz.JobExecutionException;import java.text.SimpleDateFormat;import java.util.Date;public class HelloJob implements Job{ public void execute(JobExecutionContext jobExecutionCo //打印当前的执⾏时间例如 2017-11-23 00:00:00Date date = new Date();SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");System.out.println("现在的时间是:"+ sf.format(date));//具体的业务逻辑System.out.println("Hello Quartz");}}2.创建⼀个类HelloScheduler.java,这个是具体触发我们的任务public class HelloScheduler {public static void main(String[] args) throws SchedulerException {//创建⼀个jobDetail的实例,将该实例与HelloJob Class绑定JobDetail jobDetail = JobBuilder.newJob(HelloJob.class).withIdentity("myJob").build();//创建⼀个Trigger触发器的实例,定义该job⽴即执⾏,并且每2秒执⾏⼀次,⼀直执⾏SimpleTrigger trigger = TriggerBuilder.newTrigger().withIdentity("myTrigger").startNow().withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(2).repeatForever()).build();//创建schedule实例StdSchedulerFactory factory = new StdSchedulerFactory();Scheduler scheduler = factory.getScheduler();scheduler.start();scheduler.scheduleJob(jobDetail,trigger);}}3.执⾏main⽅法,Run 'HelloScheduler.main()',可以看见如下效果,表明任务执⾏成功了4.⼀句话看懂quartz1、创建调度⼯⼚(); //⼯⼚模式2、根据⼯⼚取得调度器实例(); //⼯⼚模式3、Builder模式构建⼦组件<Job,Trigger> // builder模式, 如JobBuilder、TriggerBuilder、DateBuilder4、通过调度器组装⼦组件调度器.组装<⼦组件1,⼦组件2...> //⼯⼚模式5、调度器.start(); //⼯⼚模式四、第⼆个案例 - 每⽇的9点40分触发任务打印HelloQuartz先上代码,然后介绍⼀下cron表达式⽣成规则。
Quartz基础+实例1. 介绍Quartz体系结构:明⽩Quartz怎么⽤,⾸先要了解Scheduler(调度器)、Job(任务)和Trigger(触发器)这3个核⼼的概念。
1. Job:是⼀个接⼝,只定义⼀个⽅法execute(JobExecutionContext context),在实现接⼝的execute⽅法中编写所需要定时执⾏的Job(任务), JobExecutionContext类提供了调度应⽤的⼀些信息。
Job运⾏时的信息保存在JobDataMap实例中;2. JobDetail: Quartz每次调度Job时,都重新创建⼀个Job实例,所以它不直接接受⼀个Job的实例,相反它接收⼀个Job实现类(JobDetail:描述Job的实现类及其它相关的静态信息,如Job名字、描述、关联监听器等信息),以便运⾏时通过newInstance()的反射机制实例化Job。
3. Trigger:是⼀个类,描述触发Job执⾏的时间触发规则。
主要有SimpleTrigger和CronTrigger这两个⼦类。
当且仅当需调度⼀次或者以固定时间间隔周期执⾏调度,SimpleTrigger是最适合的选择;⽽CronTrigger则可以通过Cron表达式定义出各种复杂时间规则的调度⽅案:如⼯作⽇周⼀到周五的15:00~16:00执⾏调度等;Cron表达式的格式:秒分时⽇⽉周年(可选)。
字段名允许的值允许的特殊字符秒 0-59 , - * /分 0-59 , - * /⼩时 0-23 , - * /⽇ 1-31 , - * ? / L W C⽉ 1-12 or JAN-DEC , - * /周⼏ 1-7 or SUN-SAT , - * ? / L C # SUN, MON, TUE, WED, THU, FRI and SAT年 (可选字段) empty, 1970-2099 , - * /“?”字符:表⽰不确定的值“,”字符:指定数个值“-”字符:指定⼀个值的范围“/”字符:指定⼀个值的增加幅度。
本章对Quartz 框架一个快速的入门介绍,同时也大略指导你从哪里下载,构建和安装这个框架1. Quartz 框架的发展历程和现今许多在用的开源项目一样,Quartz之初也只是为个人开发者提供了一个简单的实现方案。
但是随着日益增多的关键人员的积极参与和慷慨的贡献,Quartz 已经成为了一个为众人所知,并且能帮助人们解决更大问题的框架。
Quartz 项目是由James House 创立的,它在1998年就有该框架最初的构思。
包括作业队列的概念,使用线程池来处理作业,也许它最早的模型已不为现今的Quartz使用者所知了。
在接下来的数年中,House 自己说他一直在关注着同一个需求:需要一个灵活的作业调度工具。
他在找寻便宜且具有丰富特征的Java作业调度工具时,让他面临着以下几个选择:·一个昂贵的商业化工具·嵌入在大框架之中的,根本用不着这么一个大框架·类似Unix Cron 或者Windows 的计划任务·自己亲自定制的方案House 有限的选择和在这个问题上的兴趣促成了他为作业调度器创建一个开源的项目。
在2001年春天,他在SourceForge 上创立了该项目,这一网址/projects/quartz现在还是有效的,只是已经不再维护了。
自从Quartz 的雏形一出来,众多的捐助者和开发人员加入到这个项目中来。
然而应该说,Quartz 能象今天这么存在还是要感谢House 以及他在作业调度领域中的兴趣。
在众多人眼中,他那解决问题的决心很值得称颂的。
2. 下载和安装Quartz在Quartz 的主页面/quartz中有下载链接(由OpenSymphony 提供的主机服务)。
在这里你可获取到最新版,也有几个早期版本供下载。
Quartz 下过来是一个完整的发行版,其中包括源代码和已编译好可直接使用的JAR 文件。
Quartz 的JAR 包还存在于ibiblio (译者注:/maven/) maven仓库中,很方便于你用Maven (译者注:一个比ANT更为强大的构建工具) 或者Ivy(译者注:一个免费基于Java的依赖管理器) 来构建系统。
Quartz使用(一)-入门使用很久没有用Quartz了,居然忘记如何使用了,这里赶紧记录下对Quartz就不说明了,直接上代码注:这里使用的是Quartz1.5.2版本(包:quartz-1.5.2.jar)简单的任务管理类import java.text.ParseException;import org.quartz.CronTrigger;import org.quartz.Job;import org.quartz.JobDetail;import org.quartz.Scheduler;import org.quartz.SchedulerException;import org.quartz.SchedulerFactory;import org.quartz.Trigger;import org.quartz.impl.StdSchedulerFactory;/*** @Title:Quartz管理类** @Description:** @Copyright:* @author zz 2008-10-8 14:19:01* @version 1.00.000**/public class QuartzManager {private static SchedulerFactory sf =new StdSchedulerFactory();private static String JOB_GROUP_NAME = "group1";private static String TRIGGER_GROUP_NAME = "trigger1";/*** 添加一个定时任务,使用默认的任务组名,触发器名,触发器组名* @param jobName 任务名* @param job 任务* @param time 时间设置,参考quartz说明文档* @throws SchedulerException* @throws ParseException*/public static void addJob(String jobName,Job job,String time)throws SchedulerException, ParseException{Scheduler sched = sf.getScheduler();JobDetail jobDetail =new JobDetail(jobName, JOB_GROUP_NAME, job.get Class());//任务名,任务组,任务执行类//触发器CronTrigger trigger =new CronTrigger(jobName, TRIGGER_GROUP_NAME);//触发器名,触发器组trigger.setCronExpression(time);//触发器时间设定sched.scheduleJob(jobDetail,trigger);//启动if(!sched.isShutdown())sched.start();}/*** 添加一个定时任务* @param jobName 任务名* @param jobGroupName 任务组名* @param triggerName 触发器名* @param triggerGroupName 触发器组名* @param job 任务* @param time 时间设置,参考quartz说明文档* @throws SchedulerException* @throws ParseException*/public static void addJob(String jobName,String jobGroupName,String triggerName,String triggerGroupName,Job job,String tim e)throws SchedulerException, ParseException{Scheduler sched = sf.getScheduler();JobDetail jobDetail =new JobDetail(jobName, jobGroupName, job.getClass ());//任务名,任务组,任务执行类//触发器CronTrigger trigger =new CronTrigger(triggerNam e, triggerGroupName);//触发器名,触发器组trigger.setCronExpression(time);//触发器时间设定sched.scheduleJob(jobDetail,trigger);if(!sched.isShutdown())sched.start();}/*** 修改一个任务的触发时间(使用默认的任务组名,触发器名,触发器组名)* @param jobName* @param time* @throws SchedulerException* @throws ParseException*/public static void modifyJobTim e(String jobName,String tim e)throws SchedulerException, ParseException{Scheduler sched = sf.getScheduler();Trigger trigger = sched.getTrigger(jobName,TRIGGER_GROUP_NAME);if(trigger != null){CronTrigger ct = (CronTrigger)trigger;ct.setCronExpression(time);sched.resum eTrigger(jobName,TRIGGER_GROUP_NAME);}}/*** 修改一个任务的触发时间* @param triggerName* @param triggerGroupName* @param time* @throws SchedulerException* @throws ParseException*/public static void m odifyJobTime(String triggerName,String triggerGroupName,String time)throws SchedulerException, ParseException{Scheduler sched = sf.getScheduler();Trigger trigger = sched.getTrigger(triggerName,triggerGroupName);if(trigger != null){CronTrigger ct = (CronTrigger)trigger;//修改时间ct.setCronExpression(time);//重启触发器sched.resum eTrigger(triggerName,triggerGroupName);}}/*** 移除一个任务(使用默认的任务组名,触发器名,触发器组名)* @param jobName* @throws SchedulerException*/public static void rem oveJob(String jobName)throws SchedulerException{Scheduler sched = sf.getScheduler();sched.pauseTrigger(jobName,TRIGGER_GROUP_NAME);//停止触发器sched.unscheduleJob(jobName,T RIGGER_GROUP_NAME);//移除触发器sched.deleteJob(jobName,JOB_GROUP_NAME);//删除任务}/*** 移除一个任务* @param jobName* @param jobGroupName* @param triggerName* @param triggerGroupName* @throws SchedulerException*/public static void rem oveJob(String jobName,String jobGroupName,String triggerName,String triggerGroupName)throws SchedulerException{Scheduler sched = sf.getScheduler();sched.pauseTrigger(triggerName,triggerGroupName);//停止触发器sched.unscheduleJob(triggerName,triggerGroupName);//移除触发器sched.deleteJob(jobName,jobGroupNam e);//删除任务}}测试工作类import org.quartz.Job;import org.quartz.JobExecutionContext;import org.quartz.JobExecutionException;public class TestJob implements Job {public void execute(JobExecutionContext arg0) throws JobExecutionExcepti on {// TODO Auto-generated m ethod stubSystem.out.println("★★★★★★★★★★★");}}测试类public class QuartzTest {/*** @param args*/public static void m ain(String[] args) {// TODO Auto-generated m ethod stubTestJob job =new TestJob();String job_name ="11";try {System.out.println("【系统启动】");QuartzManager.addJob(job_name,job,"0/5 * * * * ?");Thread.sleep(10000);System.out.println("【修改时间】");QuartzManager.modifyJobTime(job_name,"0/10 * * * * ?");Thread.sleep(20000);System.out.println("【移除定时】");QuartzManager.removeJob(job_name);Thread.sleep(10000);System.out.println("\n【添加定时任务】");QuartzManager.addJob(job_name,job,"0/5 * * * * ?");} catch (Exception e) {e.printStackTrace();}}}使用Quartz实现作业调度(二)来源:小熊时间:2008-08-05 16:10 字体:[大中小] 收藏我要投稿前面使用了Quartz 1.6来实现作业调度,但是只能指定运行的次数,在实际运用中就有些不足了。
Quartz 简单的一个实例SimpleJob.javapackage com.test.job;import org.quartz.Job;import org.quartz.JobExecutionContext;import org.quartz.JobExecutionException;public class SimpleJob implements Job{public void execute(JobExecutionContext context) throws JobExecutionException {// your business logic// ...System.out.println("simpleJob running ...."); }}TestSimpleJob.javapackage com.test.job;import java.text.ParseException;import org.quartz.CronExpression;import org.quartz.CronTrigger;import org.quartz.JobDetail;import org.quartz.Scheduler;import org.quartz.SchedulerException;import org.quartz.SimpleTrigger;import org.quartz.impl.StdSchedulerFactory;public class TestSimpleJob {public static void main(String[] args){try {Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();String jobName = "simpleJob";String groupName = "DEFAULT";//删除作业if(scheduler.getJobDetail(jobName,groupName) != null){scheduler.deleteJob(jobName, groupName);}//作业的详细信息//任务名称,任务组名称,任务实现类JobDetail jobDetail = newJobDetail(jobName,groupName,SimpleJob.class);//创建简单触发器SimpleTrigger simpleTrigger = newSimpleTrigger("simpleTrigger",null);simpleTrigger.setRepeatCount(100); // 调用100次simpleTrigger.setRepeatInterval(5*1000); //每5秒钟调用一次//注册作业scheduler.scheduleJob(jobDetail, simpleTrigger);CronTrigger cronTrigger = newCronTrigger("cronTrigger",null);CronExpression cronExpression = null;try {cronExpression = new CronExpression("0 0 12 * * ?"); //每天12点运行cronTrigger.setCronExpression(cronExpression);//注册作业scheduler.scheduleJob(jobDetail, cronTrigger);if(! scheduler.isShutdown()){scheduler.start();}} catch (ParseException e) {e.printStackTrace();}} catch (SchedulerException e) {e.printStackTrace();}}}Quarz 配置(一) - JobDetailQuartz是一个开源的作业调度框架,完全由java写的,你能通过它创建简单或者复杂的任务。
他能提供巨大的灵活性,但又不牺牲简单性。
Quartz的核心概念 :调度器、触发器、作业调度器(Scheduler)Scheduler负责管理Quartz的运行环境,Quartz它是基于多线程架构的,它启动的时候会初始化一套线程,这套线程会用来执行一些预置的作业。
要创建一个作业并能够被触发调用,必须在Scheduler上面注册一个JobDetail和Trigger。
Scheduler提携了所有Trigger和JobDetail,使它们协调工作。
这些Trigger和JobDetail 通过自身的name和group属性区分。
Scheduler 由SchedulerFactory产生,我们可以通过以下方式获取Scheduler的实例://从ServletContext上下文中查找SchedulerFactorySchedulerFactory factory = (SchedulerFactory)ServletActionContext.getServletContext().getAttribute("org.quartz.impl.StdSchedulerFa ctory.KEY");//获取Scheduler对象Scheduler defScheduler = factory.getScheduler();作业Job任务,其实就是一个接口。
要创建一个任务,必须得实现这个接口。
该接口只有一个execute 方法,任务每次被调用的时候都会执行这个execute方法的逻辑。
public class TestJob impletemens org.quartz.Job{@Overridepublic void execute(JobExecutionContext context) throws JobExecutionException{ // you business logic// …System.out.println("########### this is testJob running ############");}}JobDetailJobDetail 用来保存我们作业的详细信息。
一个JobDetail可以有多个Trigger,但是一个Trigger 只能对应一个JobDetail。
下面是JobDetail的一些常用的属性和含义JobDataMap这是一个给作业提供数据支持的数据结构,使用方法和java.util.Map一样,非常方便。
当一个作业被分配给调度器时,JobDataMap实例就随之生成。
Job有一个StatefulJob子接口,代表有状态的任务,该接口是一个没有方法的标签接口,其目的是让Quartz知道任务的类型,以便采用不同的执行方案。
无状态任务在执行时拥有自己的JobDataMap拷贝,对JobDataMap的更改不会影响下次的执行。
而有状态任务共享共享同一个JobDataMap实例,每次任务执行对JobDataMap所做的更改会保存下来,后面的执行可以看到这个更改,也即每次执行任务后都会对后面的执行发生影响。
正因为这个原因,无状态的Job可以并发执行,而有状态的StatefulJob不能并发执行,这意味着如果前次的StatefulJob还没有执行完毕,下一次的任务将阻塞等待,直到前次任务执行完毕。
有状态任务比无状态任务需要考虑更多的因素,程序往往拥有更高的复杂度,因此除非必要,应该尽量使用无状态的Job。
如果Quartz使用了数据库持久化任务调度信息,无状态的JobDataMap仅会在Scheduler 注册任务时保持一次,而有状态任务对应的JobDataMap在每次执行任务后都会进行保存。
JobDataMap实例也可以与一个触发器相关联。
这种情况下,对于同一作业的不同触发器,我们可以在JobDataMap中添加不同的数据,以便作业在不同时间执行时能够提供更为灵活的数据支持(学校上午放眼保健操录音第一版,下午放第二版)。
不管是有状态还是无状态的任务,在任务执行期间对Trigger的JobDataMap所做的更改都不会进行持久,也即不会对下次的执行产生影响。
Quartz 配置(二) - Trigger触发器(Trigger)Trigger是一个抽象类,Quartz提供了两个比较常用的触发器SimpleTrigger和CronTrigger。
它们都是Trigger的子类SimpleTrigger这是一个简单的触发器,通过它我们可以定义触发的时间,并选择性的设定重复的次数和间隔时间。
它有以下常用的属性CronTrigger这个触发器的功能非常强大,而且非常灵活,但需要掌握有关的Cron表达式知识触发器规则表达式配置:格式:[秒] [分] [小时] [日] [月] [周] [年]格式说明:总结:每个任务JobDetail可以绑定多个Trigger,但一个Trigger只能绑定一个任务,这种绑定关系由四种接口来执行:Java代码 Scheduler.scheduleJob(JobDetail, Trigger)该接口的作用是在将任务加入Quartz的同时绑定一个Trigger,Quartz会在加入该任务后自动设置Trigger的JobName与JobGroup为该JobDetail的name与group;Java代码 Scheduler.scheduleJob(Trigger)该接口的作用是将该Trigger绑定到其JobName与JobGroup指向的任务JobDetail。
这时的name与group需要在Trigger绑定前由Quartz的使用者来设置与调用Java代码 Scheduler.rescheduleJob(String, String, Trigger) 替换一个指定的Trigger, 即解除指定Trigger与任务的绑定,并将新的Trigger与任务绑定,Quartz会自动调整新Trigger的JobName与JobGroup,而旧的Trigger将被移除Java代码 Scheduler.triggerJob(String, String)系列创建一个立即触发的Trigger,并将其与name与group指定的任务绑定JobDetail有个属性叫durable,表明该任务没有任何trigger绑定时仍保存在Quartz的JobStore中,默认为false。