Quartz是OpenSymphony開源組織在Job scheduling領域又一個開源項目,是徹底由java開發的一個開源的任務日程管理系統,「任務進度管理器」就是一個在預先肯定(被歸入日程)的時間到達時,負責執行(或者通知)其餘軟件組件的系統。java
Quartz用一個小Java庫發佈文件(.jar文件),這個庫文件包含了全部Quartz核心功能。這些功能的主要接口(API)是Scheduler接口。它提供了簡單的操做,例如:將任務歸入日程或者從日程中取消,開始/中止/暫停日程進度。mysql
Quartz 任務調度的核心元素是 scheduler, trigger 和 job,其中 trigger 和 job 是任務調度的元數據, scheduler 是實際執行調度的控制器。spring
觸發器,用於定於任務調度的時間規則,即按照什麼時間規則去執行任務。Quartz 中主要提供了四種類型的 trigger:SimpleTrigger,CronTirgger,DateIntervalTrigger,和 NthIncludedDayTrigger。Trigger也有一個相關聯的JobDataMap,用於給Job傳遞一些觸發相關的參數。
最經常使用的:
SimpleTrigger:用來觸發只需執行一次或者在給定時間觸發而且重複N次且每次執行延遲必定時間的任務。
CronTrigger:按照日曆觸發,例如「每一個週五」,每月10日中午或者10:15分。sql
被調度的任務,主要有兩種類型的 job:無狀態的(stateless)和有狀態的(stateful)。數據庫
任務調度器,由 scheduler 工廠建立:DirectSchedulerFactory 或者 StdSchedulerFactory。 第二種工廠 StdSchedulerFactory 使用較多,由於 DirectSchedulerFactory 使用起來不夠方便,須要做許多詳細的手工編碼設置。 Scheduler 主要有三種:RemoteMBeanScheduler, RemoteScheduler 和 StdScheduler。服務器
做業一旦被調度,調度器須要記住而且跟蹤做業和它們的執行次數。Quartz經過一個稱之爲做業存儲(JobStore)的概念來作做業存儲和管理。併發
Quartz提供兩種基本做業存儲類型。第一種類型叫作RAMJobStore,它利用內存來持久化調度程序信息。
優勢: 不要外部數據庫,配置容易,運行速度快
缺點: 由於調度程序信息是存儲在被分配給JVM的內存裏面,因此,當應用程序中止運行時,全部調度信息將被丟失。另外由於存儲到JVM內存裏面,因此能夠存儲多少個Job和Trigger將會受到限制less
第二種類型的做業存儲稱爲JDBC做業存儲,提供兩種不一樣的實現。兩種JDBC做業存儲都須要JDBC驅動程序和後臺數據庫來持久化調度程序信息。這兩種類型的不一樣在於你是否想要控制數據庫事務或者釋放控制給應用服務器(這相似於J2EE領域中,容器管理事務CMT和Bean管理事務BMT之間的區別),這兩種JDBC做業存儲是:
JobStoreTX:當你想要控制事務或工做在非應用服務器環境中時使用;
JobStoreCMT:當你工做在應用服務器環境中和想要容器控制事務時使用。
優勢: 支持集羣,由於全部的任務信息都會保存到數據庫中,能夠控制事物,還有就是若是應用服務器關閉或者重啓,任務信息都不會丟失,而且能夠恢復因服務器關閉或者重啓而致使執行失敗的任務
缺點: 運行速度的快慢取決與鏈接數據庫的快慢ide
<dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> <version>2.2.3</version> </dependency> <dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz-jobs</artifactId> <version>2.2.3</version> </dependency>
定義jobui
public class MyJob implements Job { private static Logger logger = LoggerFactory.getLogger(MyJob.class); public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException { //打印當前的執行時間 例如 2019-11-12 00:00:00 Date date = new Date(); SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); System.out.println("如今的時間是:"+ sf.format(date)); //具體的業務邏輯 System.out.println("開始生成任務報表 或 開始發送郵件"); logger.info("開始執行定時任務"); } }
建立trigger,schedule,並啓動定時任務
//建立一個jobDetail的實例,將該實例與HelloJob Class綁定 JobDetail jobDetail = JobBuilder.newJob(MyJob.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);
先使用quartz自帶的建表語句建立表.
配置quartz.properties,以下:
# Default Properties file for use by StdSchedulerFactory # to create a Quartz Scheduler Instance, if a different # properties file is not explicitly specified. # # 調度器實例的名字,使用默認的DefaultQuartzScheduler就好 org.quartz.scheduler.instanceName: DefaultQuartzScheduler # 調度器實例的ID, 選擇AUTO org.quartz.scheduler.instanceId:AUTO org.quartz.scheduler.rmi.export: false org.quartz.scheduler.rmi.proxy: false # 跳過更新檢查 org.quartz.scheduler.skipUpdateCheck:true # 配置線程池 org.quartz.threadPool.class: org.quartz.simpl.SimpleThreadPool org.quartz.threadPool.threadCount: 10 org.quartz.threadPool.threadPriority: 5 org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread: true # # quartz默認的是將job信息存儲在內存中,quartz集羣必須將job信息持久化到數據庫中 org.quartz.jobStore.class: org.quartz.impl.jdbcjobstore.JobStoreTX org.quartz.jobStore.driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate org.quartz.jobStore.misfireThreshold:60000 ############ org.quartz.jobStore.useProperties:true #quartz數據表的前綴,quartz的數據表在 quartz-2.2.3\docs\dbTables 文件夾中, #選擇對應的數據庫版本,將數據庫建立出來 org.quartz.jobStore.tablePrefix:QRTZ_ # 最關鍵的 是否支持集羣 選擇true org.quartz.jobStore.isClustered:true org.quartz.jobStore.clusterCheckinInterval:15000 # dataSource #org.quartz.jobStore.dataSource:myDS #org.quartz.dataSource.myDS.connectionProvider.class:com.abc.util.MyPoolingconnectionProvider #org.quartz.dataSource.myDS.driver: com.mysql.jdbc.Driver #org.quartz.dataSource.myDS.url: jdbc:mysql://localhost:3306/quartz?useUnicode=true&characterEncoding=utf-8 #org.quartz.dataSource.myDS.user: root #org.quartz.dataSource.myDS.password: root #org.quartz.dataSource.myDS.maxConnections: 10
db.properties:
#quartz配置對應數據庫 jdbc.quartz.driver=com.mysql.jdbc.Driver jdbc.quartz.url=jdbc:mysql://127.0.0.1:26500/quartz?useUnicode=true&characterEncoding=utf-8 jdbc.quartz.username=root jdbc.quartz.password=vislecaina
spring-quartz.xml:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd "> <!-- 任務 --> <bean id="jobDetailFactoryBeanExample" class="org.springframework.scheduling.quartz.JobDetailFactoryBean"> <property name="jobClass" value="com.fiberhome.quartz.task.job.MyJob"/> <!-- 執行完成仍保留在數據庫中 --> <property name="durability" value="true"/> <!-- 這裏設置的jobDataAsMap能夠傳遞一些參數給做業任務 --> <property name="jobDataAsMap"> <map> <entry key="wish" value="hello"/> </map> </property> </bean> <bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean"> <!-- 這裏的JobDetail指的就是咱們配置的做業任務的bean --> <property name="jobDetail" ref="jobDetailFactoryBeanExample" /> <!-- 延遲5秒開始 --> <property name="startDelay" value="5000"></property> <!-- 每3秒重複一次 --> <property name="repeatInterval" value="60000"></property> </bean> <bean id="startQuartz" class="org.springframework.scheduling.quartz.SchedulerFactoryBean" lazy-init="false"> <property name="configLocation" value="classpath:quartz.properties" /> <property name="dataSource" ref="quartzDataSource" /> <!-- 若是這個覆蓋配置爲false,quratz啓動之後將以數據庫的數據爲準,配置文件的修改不起做用。--> <property name="overwriteExistingJobs" value="true" /> <!--指定使用哪些觸發器,spring會去調度觸發相應的觸發器,進而對做業任務進行調度處理--> <property name="triggers"> <list> <ref bean="simpleTrigger"/> </list> </property> <property name="jobFactory"> <bean class="com.fiberhome.quartz.task.jobfactory.JobFactory"/> </property> <property name="startupDelay" value="1"/> </bean> </beans>
Job類:
public class MyJob implements Job { @Autowired private UserService userService; /** * 要實現的任務 * * @param context job上下文 * @throws JobExecutionException */ @Override public void execute(JobExecutionContext context) throws JobExecutionException { User user = userService.getUser(1001); System.out.println("執行定時任務..."); System.out.println(user); } }
JobFactory類:
public class JobFactory extends SpringBeanJobFactory { @Autowired private AutowireCapableBeanFactory autowireCapableBeanFactory; @Override protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception { Object jobInstance = super.createJobInstance(bundle); autowireCapableBeanFactory.autowireBean(jobInstance); return jobInstance; } }