因為工作上的需要,第一次接觸Quartz,這裡就先來簡單介紹一下我對Quartz近期的學習使用心得,以下內容若有任何錯誤,也請不吝指教,畢竟是第一次接觸,可能還有許多地方學習不足。
Quartz是一個Open Source 的工作排程(job schedule) library或稱框架,它讓我們更容易的去安排、管理多個job(可以是幾個而已,也可能成千上萬個)的執行時間,以及怎麼執行(多久執行一次)等。名詞解釋不用說太多,趕快進入正題,該怎麼開始使用它來進行工作排程,接下來的說明是以整合進Web Application為主,我使用的Web Server是Tomcat 7.0。- 先至Quartz的官網 下載最新的Jar檔,目前最新的版本為Quartz 2.2.1,下載下來請將lib底下的jar檔複製到WEB-INF/lib底下,我的2.2.1版分別有以下這些jar檔:
- quartz-2.2.1
- quartz-jobs-2.2.1
- slf4j-api-1.6.6
- slf4j-log4j12-1.6.6
- c3p0-0.9.1.1
- 在Web.xml內加入如下的listener設定:
<listener> <listener-class> org.quartz.ee.servlet.QuartzInitializerListener </listener-class> </listener>
- 在src根目錄下新增一個quartz.properties檔案,用來設定排程器(scheduler)的一些參數,我的設定檔內容簡單如下(這邊盡量先以最簡單的方式完成設定):
<!--當程式中有多個scheduler時,用來區別不同scheduler --> org.quartz.scheduler.instanceName = MyScheduler <!--同一時間能夠並行執行的job個數,規定是只要正的整數值,但一般是限定在1~100 --> org.quartz.threadPool.threadCount = 5 <!--設定儲存scheduling資訊(job,triggers,calendars)的位置,這邊就如一般設定儲存在記憶體中 --> org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore # ----------------------------- Plugins --------------------------- # <!--Quartz並沒有內建的logging實作,所以務必指定幫我們執行log的class --> org.quartz.plugin.triggerHistory.class=org.quartz.plugins.history.LoggingTriggerHistoryPlugin <!-- Trigger在fire(發起)job執行時,要顯示的log資訊內容及格式 --> org.quartz.plugin.triggerHistory.triggerFiredMessage=Trigger [{1}.{0}] fired job [{6}.{5}] scheduled at: {2, date, dd-MM-yyyy HH:mm:ss.SSS}, next scheduled at: {3, date, dd-MM-yyyy HH:mm:ss.SSS} <!-- Trigger在job完成執行時,要顯示的log資訊內容及格式 --> org.quartz.plugin.triggerHistory.triggerCompleteMessage=Trigger {1}.{0} completed firing job {6}.{5} at {4, date, yyyy-MM-dd HH:mm:ss.SSS} with resulting trigger instruction code: {9}. Next scheduled at: {3, date, dd-MM-yyyy HH:mm:ss.SSS} <!-- Trigger在fire(發起)job執行卻misFire時,要顯示的log資訊內容及格式 --> org.quartz.plugin.triggerHistory.triggerMisfiredMessage=Trigger {1}.{0} misfired job {6}.{5} at: {4, date, yyyy/MM/dd HH:mm:ss }. Should have fired at: {3, date,yyyy/MM/dd HH:mm:ss} <!--此plugin 會從預設檔名為quartz_data.xml的設定檔讀取jobs和triggers設定並加至scheduler中 --> org.quartz.plugin.jobInitializer.class=org.quartz.plugins.xml.XMLSchedulingDataProcessorPlugin
- 寫一個自己的job class,此class必須實作org.quartz.Job 這個interface,我的code如下:
package com.xxx.util.Quartz.job; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import org.quartz.DisallowConcurrentExecution; import org.quartz.Job; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; @DisallowConcurrentExecution public class TestJob2 implements Job{ public void execute(JobExecutionContext arg0) throws JobExecutionException { Calendar expectedDateTime=Calendar.getInstance(); expectedDateTime.add(Calendar.MILLISECOND, 5000); Long expectedExecuteTime= expectedDateTime.getTimeInMillis(); Date date=new Date(); while (expectedExecuteTime!=date.getTime() && expectedExecuteTime > date.getTime()) { long leftMilliSecond = expectedExecuteTime-date.getTime(); System.out.println("Thread name:"+Thread.currentThread().getName()+ "\n There is still have "+leftMilliSecond/1000.0 +" seconds"); try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } date=new Date(); } SimpleDateFormat sdf=new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); System.out.println("I am job2 ,It's "+sdf.format(new Date())); } }
- 最後,新增一個quartz_data.xml(預設檔名)放在src根目錄下,內容如下:
<job-scheduling-data version="1.8" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.quartz-scheduler.org/xml/JobSchedulingData" xsi:schemalocation="http://www.quartz-scheduler.org/xml/JobSchedulingData http://www.quartz-scheduler.org/xml/job_scheduling_data_1_8.xsd"> <schedule> <job> <name>TestJob</name> <job-class>com.xxx.util.Quartz.job.TestJob2</job-class> </job> <trigger> <cron> <name>CronTestJob</name> <job-name>TestJob</job-name> <cron-expression>0/5 * * * * ?</cron-expression> </cron> </trigger> </schedule> </job-scheduling-data>
此設定是安排job每五秒執行一次,cron-expression請參考 cron-expression1、cron-expression詳細說明
PS:下面列出兩個對大家可能有用的參考網址
1.Quartz 官網內的Configuration Reference,裏頭按照不同主題將configuration做詳細的分類說明
2.Quartz 2.2.1 API
您好依照您上面的設定之後跑出了下面這一串
回覆刪除嚴重: Exception sending context initialized event to listener instance of class org.quartz.ee.servlet.QuartzInitializerListener
java.lang.NoClassDefFoundError: javax/transaction/UserTransaction
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Unknown Source)
at java.lang.Class.privateGetPublicMethods(Unknown Source)
at java.lang.Class.getMethods(Unknown Source)
at java.beans.Introspector.getPublicDeclaredMethods(Unknown Source)
at java.beans.Introspector.getTargetMethodInfo(Unknown Source)
at java.beans.Introspector.getBeanInfo(Unknown Source)
at java.beans.Introspector.getBeanInfo(Unknown Source)
at org.quartz.impl.StdSchedulerFactory.setBeanProps(StdSchedulerFactory.java:1393)
at org.quartz.impl.StdSchedulerFactory.instantiate(StdSchedulerFactory.java:1057)
at org.quartz.impl.StdSchedulerFactory.getScheduler(StdSchedulerFactory.java:1519)
at org.quartz.ee.servlet.QuartzInitializerListener.contextInitialized(QuartzInitializerListener.java:171)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4887)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5381)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1559)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1549)
at java.util.concurrent.FutureTask.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.ClassNotFoundException: javax.transaction.UserTransaction
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1714)
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1559)
... 21 more
五月 28, 2014 3:51:57 下午 org.apache.catalina.core.StandardContext startInternal
嚴重: Error listenerStart
五月 28, 2014 3:51:57 下午 org.apache.catalina.core.StandardContext startInternal
嚴重: Context [/testjquery] startup failed due to previous errors
請問有解嗎,謝謝。
加入jta-1.1.jar以解決錯誤。
刪除但出現
log4j:WARN No appenders could be found for logger (org.quartz.ee.servlet.QuartzInitializerListener).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
且無資料顯示
您好,你的提示訊息看起來只是沒有設定 log4j的properties檔,但理論上應該還是可以正常的啟動Quartz,所以你設定的job有開始跑嗎?
刪除