quartz使用案例篇【面试+工作】

quartz使用案例篇【面试+工作】

一.Quartz特点

运行环境

  • Quartz 可以运行嵌入在另一个独立式应用程序
  • Quartz 可以在应用程序服务器(或servlet容器)内被实例化,并且参与XA事务
  • Quartz 可以作为一个独立的程序运行(其自己的Java虚拟机内),可以通过RMI使用
  • Quartz 可以被实例化,作为独立的项目集群(负载平衡和故障转移功能),用于作业的执行

作业调度

作业被安排在一个给定的触发时运行。触发器可以使用以下指令的接近任何组合来创建:

  • 在一天中的某个时间(到毫秒)
  • 在一周的某几天
  • 在每月的某一天
  • 在一年中的某些日期
  • 不在注册的日历中列出的特定日期(如商业节假日除外)
  • 重复特定次数
  • 重复进行,直到一个特定的时间/日期
  • 无限重复
  • 重复的延迟时间间隔

作业是由其创建者赋予的名字,也可以组织成命名组。触发器也可以给予名称和放置在组中,以方便地将它们调度内组织。作业可以被添加到所述调度器一次,而是具有多个触发器注册。在企业Java环境中,作业可以执行自己的工作作为分布式(XA)事务的一部分。

作业执行

  • 作业可以实现简单的作业接口,为作业执行工作的任何Java类。
  • Job类的实例可以通过Quartz被实例化,或者通过应用程序框架。
  • 当触发时,调度通知实现JobListener和TriggerListener接口零个或多个Java对象(监听器可以是简单的Java对象,或EJB,JMS或发布者等)。这些监听器在作业已经执行之后通知。
  • 由于作业完成后返回JobCompletionCode,它通知的成功或失败的调度。JobCompletionCode还可以指示的基础上,成功的话就采取行动调度/失败的代码 - 如立即重新执行作业。

作业持久性

  • Quartz的设计包括可被实现以提供的作业存储各种机制一个作业存储接口
  • 通过使用包含的JDBCJobStore,所有的作业和触发器配置为“非挥发性”都存储在通过JDBC关系数据库。
  • 通过使用包含的RAMJobStore,所有的作业和触发器存储在RAM,因此不计划执行仍然存在 - 但这是无需使用外部数据库的优势。

事务

  • 可以参与JTA事务,通过使用JobStoreCMT(JDBCJobStore的子类)。
  • Quartz可以管理JTA事务(开始并提交它们)周围作业的执行,从而使作业执行的工作自动将JTA事务中发生。

集群

  • 故障切换
  • 负载均衡
  • Quartz的内置的群集功能,通过JDBCJobStore(如上所述)依靠数据库持久
  • Terracotta扩展Quartz提供集群功能,而不需要一个支持数据库

监听器和插件

  • 应用程序可以捕捉事件的调度监控或通过实现一个或多个监听器接口控制工作/触发行为。
  • 插件机制,可以用来添加功能,Quartz让作业执行过程中或工作负载和触发定义的历史不受限在一个文件中。
  • 附带了一些“工厂建有”插件和监听器。

二.入门案例

Quartz, 是一个企业级调度工作的框架,帮助Java应用程序到调度工作/任务在指定的日期和时间运行。

本教程教作为一个入门介绍如何开发使用调度工作(在写本教程时使用的最新Quartz 2.2.1 )

1. 下载Quartz

可以从官方网站或Maven中央存储库下载Quartz库文件;

File : quartz.properties

org.quartz.scheduler.instanceName = MyScheduler

org.quartz.threadPool.threadCount = 3

org.quartz.jobStore.class =org.quartz.simpl.RAMJobStore

2. Quartz 作业

Quartz作业定义要运行什么?

File : HelloJob

package cn.com.javahelp.common;

import org.quartz.Job;import org.quartz.JobExecutionContext;import org.quartz.JobExecutionException;

public class HelloJob implements Job{

public void execute(JobExecutionContext context)

throws JobExecutionException {

System.out.println("Hello Quartz!");

}}

3. Quartz触发器

定义Quartz触发器,当Quartz运行在上面的Quartz作业。

像老版本的Quartz,仍然有两种类型的触发器在Quartz2,但API有些变化:

· SimpleTrigger – 允许设置开始时间,结束时间,重复间隔。

· CronTrigger – 允许UNIX cron表达式来指定日期和时间来运行作业。

SimpleTrigger – 每5秒运行。

Trigger trigger = TriggerBuilder

.newTrigger()

.withIdentity("dummyTriggerName", "group1")

.withSchedule(

SimpleScheduleBuilder.simpleSchedule()

.withIntervalInSeconds(5).repeatForever())

.build();

CronTrigger – 每5秒运行。

Trigger trigger = TriggerBuilder

.newTrigger()

.withIdentity("dummyTriggerName", "group1")

.withSchedule(

CronScheduleBuilder.cronSchedule("0/5 * * * * ?"))

.build();

注意 请阅读 官方文档 更多的Quartz2触发器的例子。

4. Scheduler

调度类链接“工作”和“触发器”到一起,并执行它。

Scheduler scheduler = new StdSchedulerFactory().getScheduler();

scheduler.start();

scheduler.scheduleJob(job, trigger);

5. 完整的例子

Quartz2 两个 SimpleTrigger 和 CronTrigger 完整的例子。

SimpleTrigger的例子 - 每间隔5秒运行。

package cn.com.javahelp.quartz;

import org.quartz.JobBuilder;

import org.quartz.JobDetail;

import org.quartz.Scheduler;

import org.quartz.SimpleScheduleBuilder;

import org.quartz.Trigger;

import org.quartz.TriggerBuilder;

import org.quartz.impl.StdSchedulerFactory;

public class SimpleTriggerExample {

public static void main(String[] args) throws Exception {

// Quartz 1.6.3

// JobDetail job = new JobDetail();

// job.setName("dummyJobName");

// job.setJobClass(HelloJob.class);

JobDetail job = JobBuilder.newJob(HelloJob.class)

.withIdentity("dummyJobName", "group1").build();

//Quartz 1.6.3

// SimpleTrigger trigger = new SimpleTrigger();

// trigger.setStartTime(new Date(System.currentTimeMillis() + 1000));

// trigger.setRepeatCount(SimpleTrigger.REPEAT_INDEFINITELY);

// trigger.setRepeatInterval(30000);

// Trigger the job to run on the next round minute

Trigger trigger = TriggerBuilder

.newTrigger()

.withIdentity("dummyTriggerName", "group1")

.withSchedule(

SimpleScheduleBuilder.simpleSchedule()

.withIntervalInSeconds(5).repeatForever())

.build();

// schedule it

Scheduler scheduler = new StdSchedulerFactory().getScheduler();

scheduler.start();

scheduler.scheduleJob(job, trigger);

}}

CronTrigger例子 - 同样,在每5秒运行作业。

package cn.com.javahelp.quartz;

import org.quartz.CronScheduleBuilder;

import org.quartz.JobBuilder;

import org.quartz.JobDetail;

import org.quartz.Scheduler;

import org.quartz.Trigger;

import org.quartz.TriggerBuilder;

import org.quartz.impl.StdSchedulerFactory;

public class CronTriggerExample {

public static void main( String[] args ) throws Exception

{

//Quartz 1.6.3

//JobDetail job = new JobDetail();

//job.setName("dummyJobName");

//job.setJobClass(HelloJob.class);

JobDetail job = JobBuilder.newJob(HelloJob.class)

.withIdentity("dummyJobName", "group1").build();

//Quartz 1.6.3

//CronTrigger trigger = new CronTrigger();

//trigger.setName("dummyTriggerName");

//trigger.setCronExpression("0/5 * * * * ?");

Trigger trigger = TriggerBuilder

.newTrigger()

.withIdentity("dummyTriggerName", "group1")

.withSchedule(

CronScheduleBuilder.cronSchedule("0/5 * * * * ?"))

.build();

//schedule it

Scheduler scheduler = new StdSchedulerFactory().getScheduler();

scheduler.start();

scheduler.scheduleJob(job, trigger);

}}

三.作业监听详解

我们将展示/介绍如何创建一个JobListener,跟踪运行工作状态在作业完成等。

P.S 这个例子是Quartz 2.1.5

1. Quartz 作业

作业 - 用于打印一个简单的信息,并抛出一个JobExecutionException进行测试。

File : HelloJob.java

package cn.com.javahelp;

import org.quartz.Job;import org.quartz.JobExecutionContext;import org.quartz.JobExecutionException;

public class HelloJob implements Job{

public void execute(JobExecutionContext context)

throws JobExecutionException {

System.out.println("Hello Quartz! - by yiibai.com");

//Throw exception for testing

throw new JobExecutionException("Testing Exception");

}

}

2. JobListener

创建一个JobListener,只是实现了JobListener接口,并覆盖所有的接口的方法。

File : HelloJobListener.java

package cn.com.javahelp.quartz.listener;

import org.quartz.JobExecutionContext;import org.quartz.JobExecutionException;import org.quartz.JobListener;

public class HelloJobListener implements JobListener {

public static final String LISTENER_NAME = "dummyJobListenerName";

@Override

public String getName() {

return LISTENER_NAME; //must return a name

}

// Run this if job is about to be executed.

@Override

public void jobToBeExecuted(JobExecutionContext context) {

String jobName = context.getJobDetail().getKey().toString();

System.out.println("jobToBeExecuted");

System.out.println("Job : " + jobName + " is going to start...");

}

// No idea when will run this?

@Override

public void jobExecutionVetoed(JobExecutionContext context) {

System.out.println("jobExecutionVetoed");

}

//Run this after job has been executed

@Override

public void jobWasExecuted(JobExecutionContext context,

JobExecutionException jobException) {

System.out.println("jobWasExecuted");

String jobName = context.getJobDetail().getKey().toString();

System.out.println("Job : " + jobName + " is finished...");

if (!jobException.getMessage().equals("")) {

System.out.println("Exception thrown by: " + jobName

+ " Exception: " + jobException.getMessage());

}

}

}

注意: 不知道什么是“jobExecutionVetoed”,并会在何时触发?

3. CronTrigger

例如上面HelloJobListener连接到调度和监控作业的状态。

File : CronTriggerExample.java

package cn.com.javahelp.quartz;

import org.quartz.CronScheduleBuilder;

import org.quartz.JobBuilder;

import org.quartz.JobDetail;

import org.quartz.JobKey;

import org.quartz.Scheduler;

import org.quartz.Trigger;

import org.quartz.TriggerBuilder;

import org.quartz.impl.StdSchedulerFactory;

import org.quartz.impl.matchers.KeyMatcher;

import cn.com.javahelp.quartz.listener.HelloJobListener;

public class CronTriggerExample {

public static void main( String[] args ) throws Exception

{

JobKey jobKey = new JobKey("dummyJobName", "group1");

JobDetail job = JobBuilder.newJob(HelloJob.class)

.withIdentity(jobKey).build();

Trigger trigger = TriggerBuilder

.newTrigger()

.withIdentity("dummyTriggerName", "group1")

.withSchedule(

CronScheduleBuilder.cronSchedule("0/5 * * * * ?"))

.build();

Scheduler scheduler = new StdSchedulerFactory().getScheduler();

//Listener attached to jobKey

scheduler.getListenerManager().addJobListener(

new HelloJobListener(), KeyMatcher.keyEquals(jobKey)

);

//Listener attached to group named "group 1" only.

//scheduler.getListenerManager().addJobListener(

// new HelloJobListener(), GroupMatcher.jobGroupEquals("group1")

//);

scheduler.start();

scheduler.scheduleJob(job, trigger);

}}

运行CronTriggerExample.java, 这里是输出结果:

jobToBeExecuted

Job : group1.dummyJobName is going to start...

Hello Quartz! - by yiibai.com

jobWasExecuted

Job : group1.dummyJobName is started and finished...

Exception thrown by: group1.dummyJobName Exception: Testing Exception

jobToBeExecuted

Job : group1.dummyJobName is going to start...

Hello Quartz! - by yiibai.com

jobWasExecuted

Job : group1.dummyJobName is started and finished...

Exception thrown by: group1.dummyJobName Exception: Testing Exception

四.执行多作业

在这个例子中,我们将介绍如何通过Quartz API 多个作业。在Quartz调度框架中,每个作业将被连接到一个唯一的触发,并且由调度器运行它。

P.S:在 Quartz 中,一个触发器触发多个作业是不可以的。

1. Quartz APIs

创建3个作业,JobA,JobB和JobC。

package cn.com.javahelp.quartz;

import org.quartz.Job;

import org.quartz.JobExecutionContext;

import org.quartz.JobExecutionException;

public class JobA implements Job {

@Override

public void execute(JobExecutionContext context)

throws JobExecutionException {

System.out.println("Job A is runing //every 5 seconds ");

}

}

package cn.com.javahelp.quartz;

import org.quartz.Job;

import org.quartz.JobExecutionContext;

import org.quartz.JobExecutionException;

public class JobB implements Job {

@Override

public void execute(JobExecutionContext context)

throws JobExecutionException {

System.out.println("Job B is runing");

}

}

package cn.com.javahelp.quartz;

import org.quartz.Job;

import org.quartz.JobExecutionContext;

import org.quartz.JobExecutionException;

public class JobC implements Job {

@Override

public void execute(JobExecutionContext context)

throws JobExecutionException {

System.out.println("Job C is runing");

}

}

使用QuartzAPI声明上述3个作业,分配它们到特定触发器并调度它。

package cn.com.javahelp.quartz;

import org.quartz.CronScheduleBuilder;

import org.quartz.JobBuilder;

import org.quartz.JobDetail;

import org.quartz.JobKey;

import org.quartz.Scheduler;

import org.quartz.Trigger;

import org.quartz.TriggerBuilder;

import org.quartz.impl.StdSchedulerFactory;

public class CronTriggerExample {

public static void main( String[] args ) throws Exception

{

JobKey jobKeyA = new JobKey("jobA", "group1");

JobDetail jobA = JobBuilder.newJob(JobA.class)

.withIdentity(jobKeyA).build();

JobKey jobKeyB = new JobKey("jobB", "group1");

JobDetail jobB = JobBuilder.newJob(JobB.class)

.withIdentity(jobKeyB).build();

JobKey jobKeyC = new JobKey("jobC", "group1");

JobDetail jobC = JobBuilder.newJob(JobC.class)

.withIdentity(jobKeyC).build();

Trigger trigger1 = TriggerBuilder

.newTrigger()

.withIdentity("dummyTriggerName1", "group1")

.withSchedule(

CronScheduleBuilder.cronSchedule("0/5 * * * * ?"))

.build();

Trigger trigger2 = TriggerBuilder

.newTrigger()

.withIdentity("dummyTriggerName2", "group1")

.withSchedule(

CronScheduleBuilder.cronSchedule("0/5 * * * * ?"))

.build();

Trigger trigger3 = TriggerBuilder

.newTrigger()

.withIdentity("dummyTriggerName3", "group1")

.withSchedule(

CronScheduleBuilder.cronSchedule("0/5 * * * * ?"))

.build();

Scheduler scheduler = new StdSchedulerFactory().getScheduler();

scheduler.start();

scheduler.scheduleJob(jobA, trigger1);

scheduler.scheduleJob(jobB, trigger2);

scheduler.scheduleJob(jobC, trigger3);

}}

输出结果如上:

Job A is runing //every 5 seconds

Job B is runing

Job C is runing

Job A is runing //every 5 seconds

Job B is runing

Job C is runing

五.列出调度所有作业

下面是两个代码片段展示如何列出所有Quartz的作业。Quartz2 API都发生了很大变化,所以语法和Quartz1.x是不同的

1. Quartz 2.2.1 示例

Scheduler scheduler = new StdSchedulerFactory().getScheduler();

for (String groupName : scheduler.getJobGroupNames()) {

for (JobKey jobKey : scheduler.getJobKeys(GroupMatcher.jobGroupEquals(groupName))) {

String jobName = jobKey.getName();

String jobGroup = jobKey.getGroup();

//get job's trigger

List<Trigger> triggers = (List<Trigger>) scheduler.getTriggersOfJob(jobKey);

Date nextFireTime = triggers.get(0).getNextFireTime();

System.out.println("[jobName] : " + jobName + " [groupName] : "

+ jobGroup + " - " + nextFireTime);

}

}

2. Quartz 1.8.6 示例

Scheduler scheduler = new StdSchedulerFactory().getScheduler();

//loop all group

for (String groupName : scheduler.getJobGroupNames()) {

//loop all jobs by groupname

for (String jobName : scheduler.getJobNames(groupName)) {

//get job's trigger

Trigger[] triggers = scheduler.getTriggersOfJob(jobName,groupName);

Date nextFireTime = triggers[0].getNextFireTime();

System.out.println("[jobName] : " + jobName + " [groupName] : "

+ groupName + " - " + nextFireTime);

}

}

原文发布于微信公众号 - Java帮帮(javahelp)

原文发表时间:2018-06-03

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏葡萄城控件技术团队

Wijmo 更优美的jQuery UI部件集:服务器端Grid魔法

在之前的一篇文章中,我们讨论了如何添加一大堆的超赞的功能到一个标准的HTML表,并把它转换成一个“grid”表格。今天我想要做的事情是向你展示如何将这些功能转到...

22160
来自专栏大内老A

我的WCF之旅(6):在Winform Application中调用Duplex Service出现TimeoutException的原因和解决方案

几个星期之前写了一篇关于如何通过WCF进行 双向通信的文章([原创]我的WCF之旅(3):在WCF中实现双向通信(Bi-directional Communic...

22580
来自专栏ASP.NET MVC5 后台权限管理系统

已经重写,源码和文章请跳转http://www.cnblogs.com/ymnets/p/5621706.html

文章由于写得比较仓促 已经重写,源码和文章请跳转 http://www.cnblogs.com/ymnets/p/5621706.html  前言: 导入导出实...

31680
来自专栏ASP.NET MVC5 后台权限管理系统

ASP.NET MVC5+EF6+EasyUI 后台管理系统(87)-MVC Excel导入和导出

按照之前的做法,更新到EF。并利用T4生成DAL,BLL,MODEL。再用代码生成器生成界面复制进解决方案,一步到位

22800
来自专栏Java架构师学习

Zookeeper-watcher机制源码分析(一)Watcher的基本流程

ZooKeeper 的 Watcher 机制,总的来说可以分为三个过程:客户端注册 Watcher、服务器处理 Watcher 和客户端回调 Watcher

10620
来自专栏技术之路

Caliburn.Micro学习笔记(四)----IHandle<T>实现多语言功能

说一下IHandle<T>实现多语言功能 因为Caliburn.Micro是基于MvvM的UI与codebehind分离, binding可以是双向的所以我们想...

25270
来自专栏大内老A

我的WCF之旅(6):在Winform Application中调用Duplex Service出现TimeoutException的原因和解决方案

几个星期之前写了一篇关于如何通过WCF进行 双向通信的文章([原创]我的WCF之旅(3):在WCF中实现双向通信(Bi-directional Communic...

18660
来自专栏ASP.NET MVC5 后台权限管理系统

ASP.NET MVC5+EF6+EasyUI 后台管理系统(6)-Unity 依赖注入

前言 为了符合后面更新后的重构系统,文章于2016-11-1日重写 本节重构一下代码,采用IOC控制反转,也就是依赖注入 您可以访问http://unit...

30070
来自专栏hbbliyong

母版页

1. 在整个站点中应用母版页 <configuration> <system.web> <pages masterPageFile="~/Site...

32440
来自专栏.net core新时代

npoi批量导入实现及相关技巧

  批量导入功能对于大部分后台系统来说都是不可或缺的一部分,常见的场景-基础数据的录入(部门,用户),用批量导入方便快捷。最近项目需要用到批量导入,决定花点时间...

50650

扫码关注云+社区

领取腾讯云代金券