儘可能的用聲明式處理軟體配置,其次才考慮編程式的方式。在上一篇《 Quartz 架構快速入門(一) 》中,如果我們要在 Job 啟動之後改變它的執行時間和頻度,必須去修改原始碼重新編譯。這種方式只適用於小的例子程式,但是對於一個大且複雜的系統,這就成了一個問題了。因此,假如能以聲明式部署 Quart Job 時,並且也是需求允許的情況下,你應該每次都選擇這種方式
·配置 quartz.properties 檔案
檔案 quartz.properties 定義了 Quartz 應用運行時行為,還包含了許多能控制 Quartz 運轉的屬性。這個檔案應該放在classpath所指的路徑下,比如我們這個java工程,就將它和下面將介紹的jobs.xml一起放在項目根目錄下就是。如果不清楚就查看.classpath檔案,它裡面就配置了你的項目的classpath。
我們來看看最基礎的 quartz.properties 檔案,並討論其中一些設定。下面是一個修剪版的 quartz.propertis檔案 #============================================================================
# Configure Main Scheduler Properties
#============================================================================
org.quartz.scheduler.instanceName = TestScheduler
org.quartz.scheduler.instanceId = AUTO
#============================================================================
# Configure ThreadPool
#============================================================================
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 3
org.quartz.threadPool.threadPriority = 5
#============================================================================
# Configure JobStore
#============================================================================
org.quartz.jobStore.misfireThreshold = 60000
org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore
#============================================================================
# Configure Plugins
#============================================================================
org.quartz.plugin.triggHistory.class = org.quartz.plugins.history.LoggingJobHistoryPlugin
org.quartz.plugin.jobInitializer.class = org.quartz.plugins.xml.JobInitializationPlugin
org.quartz.plugin.jobInitializer.fileNames = jobs.xml
org.quartz.plugin.jobInitializer.overWriteExistingJobs = true
org.quartz.plugin.jobInitializer.failOnFileNotFound = true
org.quartz.plugin.jobInitializer.scanInterval = 10
org.quartz.plugin.jobInitializer.wrapInUserTransaction = false
·調度器屬性
第一部分有兩行,分別設定調度器的執行個體名(instanceName) 和執行個體 ID (instanceId)。屬性 org.quartz.scheduler.instanceName 可以是你喜歡的任何字串。它用來在用到多個調度器區分特定的調度器執行個體。多個調度器通常用在叢集環境中。(Quartz 叢集將會在第十一章,“Quartz 叢集”中討論)。現在的話,設定如下的一個字串就行:org.quartz.scheduler.instanceName = QuartzScheduler
實際上,這也是當你沒有該屬性配置時的預設值。
調度器的第二個屬性是 org.quartz.scheduler.instanceId。和 instaneName 屬性一樣,instanceId 屬性也允許任何字串。這個值必須是在所有調度器執行個體中是唯一的,尤其是在一個叢集當中。假如你想 Quartz 幫你產生這個值的話,可以設定為 AUTO。如果 Quartz 架構是運行在非叢集環境中,那麼自動產生的值將會是 NON_CLUSTERED。假如是在叢集環境下使用 Quartz,這個值將會是主機名稱加上當前的日期和時間。大多情況下,設定為 AUTO 即可。
·線程池屬性
接下來的部分是設定有關線程必要的屬性值,這些線程在 Quartz 中是運行在後台擔當重任的。threadCount 屬性控制了多少個工作者線程被建立用來處理 Job。原則上是,要處理的 Job 越多,那麼需要的工作者線程也就越多。threadCount 的數值至少為 1。Quartz 沒有限定你設定工作者線程的最大值,但是在多數機器上設定該值超過100的話就會顯得相當不實用了,特別是在你的 Job 執行時間較長的情況下。這項沒有預設值,所以你必須為這個屬性設定一個值。
threadPriority 屬性設定工作者線程的優先順序。優先順序別高的線程比層級低的線程更優先得到執行。threadPriority 屬性的最大值是常量 java.lang.Thread.MAX_PRIORITY,等於10。最小值為常量 java.lang.Thread.MIN_PRIORITY,為1。這個屬性的正常值是 Thread.NORM_PRIORITY,為5。大多情況下,把它設定為5,這也是沒指定該屬性的預設值。
最後一個要設定的線程池屬性是 org.quartz.threadPool.class。這個值是一個實現了 org.quartz.spi.ThreadPool 介面的類的全限名稱。Quartz 內建的線程池實作類別是 org.quartz.smpl.SimpleThreadPool,它能夠滿足大多數使用者的需求。這個線程池實現具備簡單的行為,並經很好的測試過。它在調度器的生命週期中提供固定大小的線程池。你能根據需求建立自己的線程池實現,如果你想要一個隨需可伸縮的線程池時也許需要這麼做。這個屬性沒有預設值,你必須為其指定值。
·作業儲存設定
作業儲存部分的設定描述了在調度器執行個體的生命週期中,Job 和 Trigger 資訊是如何被儲存的。我們還沒有談論到作業儲存和它的目的;因為對當前例子是非必的,所以我們留待以後說明。現在的話,你所要瞭解的就是我們儲存調度器資訊在記憶體中而不是在關係型資料庫中就行了。
把調度器資訊儲存在記憶體中非常的快也易於配置。當調度器進程一旦被終止,所有的 Job 和 Trigger 的狀態就丟失了。要使 Job 儲存在記憶體中需通過設定 org.quartz.jobStrore.class 屬性為 org.quartz.simpl.RAMJobStore。假如我們不希望在 JVM 退出之後丟失調度器的狀態資訊的話,我們可以使用關係型資料庫來儲存這些資訊。這需要另一個作業儲存(JobStore) 實現,我們在後面將會討論到。第五章“Cron Trigger 和其他”和第六章“作業儲存和持久化”會提到你需要用到的不同類型的作業儲存實現。
·外掛程式配置
在這個簡單的 quartz.properties 檔案中最後一部分是你要用到的 Quart 外掛程式的配置。外掛程式常常在別的開源架構上使用到,比如 Apache 的 Struts 架構(見 http://struts.apache.org/)。
一個聲明式擴架構的方法就是通過新加實現了 org.quartz.spi.SchedulerPlugin 介面的類。SchedulerPlugin 介面中有給調度器調用的三個方法。
要在我們的例子中聲明式配置調度器資訊,我們會用到一個 Quartz 內建的叫做 org.quartz.plugins.xml.JobInitializationPlugin 的外掛程式。
預設時,這個外掛程式會在 classpath 中搜尋名為 quartz_jobs.xml 的檔案並從中載入 Job 和 Trigger 資訊。在下下面中討論 quartz_jobs.xml 檔案,這是我們所參考的非正式的 Job 定義檔案。
·為外掛程式修改 quartz.properties 配置
JobInitializationPlugin 找尋 quartz_jobs.xml 來獲得聲明的 Job 資訊。假如你想改變這個檔案名稱,你需要修改 quartz.properties 來告訴外掛程式去載入那個檔案。例如,假如你想要 Quartz 從名為 my_quartz_jobs.xml 的 XML 檔案中載入 Job 資訊,你不得不為外掛程式指定這一檔案 org.quartz.plugin.triggHistory.class = org.quartz.plugins.history.LoggingJobHistoryPlugin
org.quartz.plugin.jobInitializer.class = org.quartz.plugins.xml.JobInitializationPlugin
org.quartz.plugin.jobInitializer.fileNames = jobs.xml
org.quartz.plugin.jobInitializer.overWriteExistingJobs = true
org.quartz.plugin.jobInitializer.failOnFileNotFound = true
org.quartz.plugin.jobInitializer.scanInterval = 10
org.quartz.plugin.jobInitializer.wrapInUserTransaction = false
我們添加了屬性 org.quartz.plugin.jobInitializer.fileName 並設定該屬性值為我們想要的檔案名稱。這個檔案名稱要對 classloader 可見,也就是說要在 classpath 下。
當 Quartz 啟動後讀取 quartz.properties 檔案,然後初始化外掛程式。它會傳遞上面配置的所有屬性給外掛程式,這時候外掛程式也就得到通知去搜尋不同的檔案。
下面就是目錄掃描例子的 Job 定義的 XML 檔案。正如上一篇所樣本子那樣,這裡我們用的是聲明式途徑來配置 Job 和 Trigger 資訊的 <? xml version='1.0' encoding='utf-8' ?>
< quartz xmlns ="http://www.opensymphony.com/quartz/JobSchedulingData"
xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation ="http://www.opensymphony.com/quartz/JobSchedulingData
http://www.opensymphony.com/quartz/xml/job_scheduling_data_1_5.xsd"
version ="1.5" >
< job >
< job-detail >
< name > ScanDirectory </ name >
< group > DEFAULT </ group >
< description >
A job that scans a directory for files
</ description >
< job-class >
com.vista.quartz.ScanDirectoryJob
</ job-class >
< volatility > false </ volatility >
< durability > false </ durability >
< recover > false </ recover >
< job-data-map allows-transient-data ="true" >
< entry >
< key > SCAN_DIR </ key >
< value > D:/conf1 </ value >
</ entry >
</ job-data-map >
</ job-detail >
< trigger >
< simple >
< name > scanTrigger </ name >
< group > DEFAULT </ group >
< job-name > ScanDirectory </ job-name >
< job-group > DEFAULT </ job-group >
< start-time > 2008-09-03T14:43:00 </ start-time >
<!-- repeat indefinitely every 10 seconds -->
< repeat-count >