經常在項目中遇到定時任務的時候,通常第一個想到的是Timer定時器,但是這玩意功能太弱雞,實際上通常採用的是專業化的第三方調度框架,比如說 Quartz,它具有功能強大和應用的靈活性,我想使用過的人都非常瞭解,那麼本篇就來說說如何通過代碼和配置文件來進行job和trigger的配置。 一:常規的jo ...
經常在項目中遇到定時任務的時候,通常第一個想到的是Timer定時器,但是這玩意功能太弱雞,實際上通常採用的是專業化的第三方調度框架,比如說
Quartz,它具有功能強大和應用的靈活性,我想使用過的人都非常瞭解,那麼本篇就來說說如何通過代碼和配置文件來進行job和trigger的配置。
一:常規的job,trigger配置方式
這種常規的方式也是我們初步學習Quartz最先瞭解到的,即通過JobBuilder和TriggerBuilder來鏈式一個IJobDetail和ISimpleTrigger,比如下麵的代碼。
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 IScheduler scheduler = StdSchedulerFactory.GetDefaultScheduler(); 6 7 scheduler.Start(); 8 9 var job = JobBuilder.Create<HelloJob>().Build(); 10 11 var trigger = TriggerBuilder.Create().WithSimpleSchedule(m => m.WithIntervalInSeconds(1) 12 .RepeatForever()) 13 .StartNow() 14 .Build(); 15 16 scheduler.ScheduleJob(job, trigger); 17 18 Console.Read(); 19 } 20 }
上面這段代碼可以看出,在BuildJob的時候,使用提供的HelloJob作為當前的定時調度的任務,下麵的ISimpleTrigger的意思就是每一秒鐘執行一次HelloJob,
僅此而已,然後就是HelloJob的具體定義,非常簡單,實現一個IJob介面。
1 public class HelloJob : IJob 2 { 3 private string name = string.Empty; 4 public void Execute(IJobExecutionContext context) 5 { 6 Console.WriteLine("當前時間: {0} ", DateTime.Now); 7 } 8 }
然後可以把程式跑起來,看看最後的一個結果,可以看到每秒鐘都有一個數據輸出:
這種方式貌似很完美,但是也有一個不利點,現在需求有變更,我需要將WithIntervalInSeconds(1) 改成WithIntervalInSeconds(2),也就是每秒執行
一次改成每兩秒執行一次,這個就頭疼了,你不得不面對改一次需求,就需要編譯一次再發佈,這樣的傷筋動骨,我想你也不大願意吧?面對這種需求肯定是
有辦法的,不信的話,你可以往下看。
二:在quartz_jobs.xml定義job和trigger
上面這種硬編碼帶來的壞處我也跟大家講到了,接下來看看如何使用xml配置job和trigger,當我們從nuget中獲取quartz框架的時候,應該都會發現你的
解決方案中多了一個xsd文件,但是可能有很多人並不知道這個xsd文件到底是用來幹嘛的。。。。其實就是用來寫xml時做代碼提示用的,好了,下麵我就一
步步的展示給大家。
1. 從nuget下載文件,沒什麼好說的,在“引用”上右擊滑鼠,選擇“管理NuGet程式包”看下圖:
然後你會看到多了一個job_scheduling_data_2_0.xsd文件。
2. 接下來新建一個quartz_jobs.xml文件,然後選中visual studio中的xml菜單欄,選中“架構”菜單項。
3. 在彈出的對話框中,選擇“添加”按鈕,找到從nuget中生成的job_scheduling_data_2_0.xsd,然後點擊完成。
4. 然後就可以在xml中自由的編碼,你會發現關於job和trigger的代碼有提示了。。。這極大的提高了我們的開發
效率,對吧。
好了,下麵貼出完整的xml案例,從xml中大概也能看得出來,在schedule中定義了一個job和trigger,在job-type節點中定義了需要執行job的命名空間和類名,
有點意思吧,也是最終schedule需要調度的任務。
<?xml version="1.0" encoding="utf-8" ?> <job-scheduling-data xmlns="http://quartznet.sourceforge.net/JobSchedulingData"> <processing-directives> <overwrite-existing-data>true</overwrite-existing-data> </processing-directives> <schedule> <job> <name>sampleJob</name> <group>sampleGroup</group> <description>Sample job for Quartz Server</description> <job-type>ConsoleApplication5.HelloJob,ConsoleApplication5</job-type> <durable>true</durable> <recover>false</recover> </job> <trigger> <simple> <name>sampleSimpleTrigger</name> <group>sampleSimpleGroup</group> <description>Simple trigger to simply fire sample job</description> <job-name>sampleJob</job-name> <job-group>sampleGroup</job-group> <misfire-instruction>SmartPolicy</misfire-instruction> <repeat-count>-1</repeat-count> <repeat-interval>1000</repeat-interval> </simple> </trigger> </schedule> </job-scheduling-data>
5. job的配置文件基本上算是搞定了,然後配置Quartz.Plugin.Xml.XMLSchedulingDataProcessorPlugin類來處理
這個xml文件,同時指定下quartz_jobs.xml的路徑,如下所示:
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 var factory = new StdSchedulerFactory(new System.Collections.Specialized.NameValueCollection() 6 { 7 {"quartz.plugin.xml.fileNames","~/quartz_jobs.xml" }, 8 {"quartz.plugin.xml.type","Quartz.Plugin.Xml.XMLSchedulingDataProcessorPlugin,Quartz"} 9 }); 10 11 IScheduler scheduler = factory.GetScheduler(); 12 13 scheduler.Start(); 14 } 15 }
好了,基本上就這樣配置結束了,最後一點要註意的就是配置一下quartz_jobs.xml始終複製到bin文件下,如圖:
最後跑一下源代碼看看,效果咋樣,看到沒有,是不是很牛逼。
好了,現在是不是發現你的靈活性有很大提高了,如果將1s改成2s,我只需要把quartz_jobs.xml中的<repeat-interval>1000</repeat-interval>,改成
<repeat-interval>2000</repeat-interval>就可是做到對trigger的動態配置,是不是很酷。
最後附完整案例:ConsoleApplication5.zip