Quarz完成定時任務(非註解版)
Quartz作業排程框架(附整合Spring)
Quartz是OpenSymphony開源組織在Job scheduling領域又一個開源專案,它可以與J2EE與J2SE應用程
Quartz是OpenSymphony開源組織在Job scheduling領域又一個開源專案,它可以與J2EE與J2SE應用程式相結合也可以單獨使用。Quartz可以用來建立簡單或為執行十個,百個,甚至是好幾萬個Jobs這樣複雜的程式。Jobs可以做成標準的Java元件或 EJBs。Quartz的最新版本為Quartz 2.3.0。
1. 結構
Quartz是一個完全由java編寫的開源作業排程框架。不要讓作業排程這個術語嚇著你。儘管Quartz框架整合了許多額外功能, 但就其簡易形式看,你會發現它易用得簡直讓人受不了!。簡單地建立一個實現org.quartz.Job介面的java類。Job介面包含唯一的方法:
public void execute(JobExecutionContext context)
throws JobExecutionException;
在你的Job介面實現類裡面,新增一些邏輯到execute()方法。一旦你配置好Job實現類並設定好排程時間表,Quartz將密切注意剩餘時間。當排程程式確定該是通知你的作業的時候,
1. 框架特徵
編輯
Quartz框架有一個豐富的特徵集。事實上,Quartz有太多特性以致不能在一種情況中全部領會,下面列出了一些有意思的特徵,但沒時間在此詳細討論。
監聽器和外掛
每個人都喜歡監聽和外掛。今天,幾乎下載任何開源框架,你必定會發現支援這兩個概念。監聽是你建立的
一旦你的一個具體監聽被呼叫,你就能使用這個技術來做一些你想要在監聽類裡面做的事情。例如,你如果想要在每次作業完成時傳送一個電子郵件,你可以將這個邏輯寫進作業裡面,也可以寫進JobListener裡面。寫進JobListener的方式強制使用鬆耦合有利於設計上做到更好。
Quartz外掛是一個新的功能特性,無須修改Quartz原始碼便可被建立和新增進Quartz框架。他為想要擴充套件Quartz框架又沒有時間提交改變給Quartz開發團隊和等待新版本的開發人員而設計。如果你熟悉Struts外掛的話,那麼完全可以理解Quartz外掛的使用。
與其Quartz提供一個不能滿足你需要的有限擴充套件點,還不如通過使用外掛來擁有可修整的擴充套件點。
叢集Quartz應用
Quartz應用能被叢集,是水平叢集還是垂直叢集取決於你自己的需要。叢集提供以下好處:
·伸縮性
·高可用性
·負載均衡
Quartz可以藉助關係資料庫和JDBC作業儲存支援叢集。
Terracotta擴充套件quartz提供叢集功能而不需要資料庫支援
相關工具
Quartz經常會用到cron表示式,可以使用國外網站cronmaker輔助生成cron表示式。
1. 核心介面和類
1) Scheduler介面
它提供了對作業計劃的啟動、停止、恢復、刪除、對作業計劃的重新定製的方法
它通過JobDetail和trigger建立一個作業計劃
2) Job介面
只需要實現一個方法void execute(JobExecutionContext context)
程式中需要被執行的作業就需要在execute中實現。
3) JobDetail類
通過JobDetail類可以設定具體執行的Job,並且給執行的Job設定名稱,組,描述等資訊,該類包括一個JobDetail(String name,String group,Class JobClass)構造器,它的引數
分別是job的名稱,組名,和實現了job介面的實現類
4) Trigger類
主要是設定觸發Job執行的時間觸發規則,主要有SimpleTrigger和CronTrigger這兩個子類。
SimpleTrigger擅長執行單次執行或者固定週期計劃任務執行。
CronTrigger則可以通過Cron表示式定義出各種複雜的時間規則的排程方案。
1. Cron表示式
語法為 秒 分 時 日 月 年(可省略)
1. Cron表示式訓練
(1) */5 ** ** ? --每隔5秒執行一次
(2) 0 */1 *** ? –每隔1分鐘執行一次
(3) 00 23 ** ? – 每天23點執行一次
(4) 00 1? ** --每週日凌晨1點執行一次
(5) 00 11 *? 每月1號凌晨1點執行一次
(6) 0 26,29,33 ***? 在26分,29分,33分執行一次
1. Spring整合QuartZ框架
一個普通的java類,配置JobDetail,Trigger,Scheduler
1. 依賴的jar包
Spring-context-support.jar
Spring-tx.jar
Quartz.jar
<!-- https://mvnrepository.com/artifact/org.springframework/spring-tx -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>5.0.6.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.quartz-scheduler/quartz -->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.2.3</version>
</dependency>
1. 搭建專案
3. 配置檔案
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.2.xsd ">
<context:component-scan base-package="com.cxl.scheduler"/>
<bean id="myJob" class="com.cxl.scheduler.MyJob"/>
<!--指定需要定時執行的方法-->
<bean id="myJobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject" ref="myJob"/>
<property name="targetMethod" value="mockCallService"/>
</bean>
<!--按指定頻率執行-->
<bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">
<property name="jobDetail" ref="myJobDetail"/>
<!--啟動延時-->
<property name="startDelay" value="0"></property>
<!--執行評率,單位,毫秒-->
<property name="repeatInterval" value="2000"/>
</bean>
<!--
<!–按指定時間執行–>
<bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<property name="jobDetail" ref="myJobDetail"/>
<property name="cronExpression" value="0 26,27 16 * * ?"/>
</bean>-->
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<ref bean="simpleTrigger"/>
<!--<ref bean="cronTrigger"/>-->
</list>
</property>
</bean>
4. 執行專案(以simpleTrigger來啟動)
可以發現,它是每2秒使用這個方法一次
按是制定時間來執行
1. QuartZ工具類
.
import static org.quartz.JobBuilder.newJob;
import static org.quartz.JobKey.jobKey;
import static org.quartz.TriggerBuilder.newTrigger;
import static org.quartz.CronScheduleBuilder.cronSchedule;
import static org.quartz.TriggerKey.triggerKey;
import java.util.Date;
import org.quartz.CronTrigger;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
public class QuartzUtils {
private static String JOB_NAME = "EXTJWEB_NAME";
private static String JOB_GROUP_NAME = "EXTJWEB_JOBGROUP_NAME";
private static String TRIGGER_NAME = "EXTJWEB_NAME";
private static String TRIGGER_GROUP_NAME = "EXTJWEB_TRIGGERGROUP_NAME";
/**
* @Description: 新增一個定時任務,使用預設的任務組名,觸發器名,觸發器組名
* @param sched:排程器
* @param jobClass:任務
* @param time:時間設定,CronExpression表示式
*/
public static void addJob(Scheduler sched, @SuppressWarnings("rawtypes") Class jobClass, String time) {
addJob(sched, jobClass,time,JOB_NAME,JOB_GROUP_NAME,TRIGGER_NAME,TRIGGER_GROUP_NAME);
}
/**
* @Description: 新增一個定時任務
* @param sched:排程器
* @param jobClass:任務
* @param time:時間設定,CronExpression表示式
* @param jobName:任務名
* @param jobGroupName:任務組名
* @param triggerName:觸發器名
* @param triggerGroupName:觸發器組名
*/
public static void addJob(Scheduler sched, @SuppressWarnings("rawtypes") Class jobClass, String time,
String jobName, String jobGroupName, String triggerName, String triggerGroupName) {
JobDetail job = newJob(jobClass).withIdentity(jobName, jobGroupName).build();
CronTrigger trigger = newTrigger().withIdentity(triggerName, triggerGroupName)
.withSchedule(cronSchedule(time)).build();
try {
// 返回為 null 新增失敗
Date ft = sched.scheduleJob(job, trigger);
} catch (SchedulerException e) {
e.printStackTrace();
}
}
/**
* @Description: 定義一個任務之後進行觸發設定(使用預設的任務組名,觸發器名,觸發器組名)
* @param sched:排程器
* @param time
*/
@SuppressWarnings("rawtypes")
public static void addJObLaterUse(Scheduler sched, @SuppressWarnings("rawtypes") Class jobClass, String time) {
addJObLaterUse(sched,jobClass,time,JOB_NAME,JOB_GROUP_NAME);
}
/**
* @Description: 定義一個任務之後進行觸發設定
* @param sched:排程器
* @param time
* @param jobName:任務名
* @param jobGroupName:任務組名
*/
@SuppressWarnings("rawtypes")
public static void addJObLaterUse(Scheduler sched, @SuppressWarnings("rawtypes") Class jobClass, String time,
String jobName,String jobGroupName) {
JobDetail job = newJob(jobClass).withIdentity(jobName, jobGroupName).storeDurably().build();
try {
sched.addJob(job, false);
} catch (SchedulerException e) {
e.printStackTrace();
}
}
/**
* @Description: 對已儲存的任務進行scheduling(使用預設的任務組名,觸發器名,觸發器組名)
* @param sched:排程器
* @param time
* @param jobName:任務名
* @param jobGroupName:任務組名
*/
@SuppressWarnings("rawtypes")
public static void schedulingStoredJOb(Scheduler sched, @SuppressWarnings("rawtypes") Class jobClass, String time) {
schedulingStoredJOb(sched,jobClass,time,JOB_NAME,JOB_GROUP_NAME,TRIGGER_NAME,TRIGGER_GROUP_NAME);
}
/**
* @Description: 對已儲存的任務進行scheduling
* @param sched:排程器
* @param time
* @param jobName:任務名
* @param jobGroupName:任務組名
*/
@SuppressWarnings("rawtypes")
public static void schedulingStoredJOb(Scheduler sched, @SuppressWarnings("rawtypes") Class jobClass, String time,
String jobName,String jobGroupName,String triggerName, String triggerGroupName) {
Trigger trigger = newTrigger().withIdentity(triggerName, triggerGroupName).startNow()
.forJob(jobKey(jobName,jobGroupName))
.build();
try {
sched.scheduleJob(trigger);
} catch (SchedulerException e) {
e.printStackTrace();
}
}
/**
* @Description: 修改一個任務的觸發時間(使用預設的任務組名,觸發器名,觸發器組名)
* @param sched:排程器
* @param time
*/
@SuppressWarnings("rawtypes")
public static void modifyJobTime(Scheduler sched, String time) {
modifyJobTime(sched, TRIGGER_NAME, TRIGGER_GROUP_NAME, time);
}
/**
* @Description: 修改一個任務的觸發時間
* @param sched:排程器
* @param triggerName
* @param triggerGroupName
* @param time
*/
public static void modifyJobTime(Scheduler sched, String triggerName, String triggerGroupName, String time) {
Trigger trigger = newTrigger().withIdentity(triggerName, triggerGroupName).withSchedule(cronSchedule(time)).startNow().build();
try {
sched.rescheduleJob(triggerKey(triggerName, triggerGroupName), trigger);
} catch (SchedulerException e) {
e.printStackTrace();
}
}
/**
* @Description: 修改一個任務(使用預設的任務組名,任務名)
* @param sched:排程器
*/
@SuppressWarnings("rawtypes")
public static void modifyJob(Scheduler sched, @SuppressWarnings("rawtypes") Class jobClass) {
modifyJob(sched,jobClass,JOB_NAME,JOB_GROUP_NAME);
}
/**
* @Description: 修改一個任務
* @param sched:排程器
* @param jobName:任務名
* @param jobGroupName:任務組名
*/
public static void modifyJob(Scheduler sched, @SuppressWarnings("rawtypes") Class jobClass, String jobName,String jobGroupName) {
JobDetail job1 = newJob(jobClass).withIdentity(jobName,jobGroupName).build();
try {
sched.addJob(job1, true);
} catch (SchedulerException e) {
e.printStackTrace();
}
}
/**
* @Description: 刪除一個任務的的trigger
* @param sched:排程器
* @param triggerName
* @param triggerGroupName
*/
public static void unschedulingJob(Scheduler sched,String triggerName, String triggerGroupName) {
try {
sched.unscheduleJob(triggerKey(triggerName,triggerGroupName));
} catch (SchedulerException e) {
e.printStackTrace();
}
}
/**
* @Description: 移除一個任務,以及任務的所有trigger
* @param sched:排程器
* @param jobName
*/
public static void removeJob(Scheduler sched, String jobName,String jobGroupName) {
try {
sched.deleteJob(jobKey(jobName,jobGroupName));
} catch (SchedulerException e) {
e.printStackTrace();
}
}
/**
* @Description:啟動所有定時任務
* @param sched:排程器
*/
public static void startJobs(Scheduler sched) {
try {
sched.start();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* @Description:關閉所有定時任務
* @param sched:排程器
*/
public static void shutdownJobs(Scheduler sched) {
try {
if (!sched.isShutdown()) {
//未傳參或false:不等待執行完成便結束;true:等待任務執行完才結束
sched.shutdown();
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}