1、簡單的Quartz程序json
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Quartz; using Quartz.Impl; using Quartz.Listener; using Quartz.Impl.Matchers; using System.Threading; namespace ConsoleApp3 { class Program { static void Main(string[] args) { //scheduler [10 +1 都開啓了,只不過都是等待狀態] var scheduler = StdSchedulerFactory.GetDefaultScheduler().Result; //[start 會讓 調度線程 啓動,從jobstore中獲取快要執行的trigger,而後獲取trigger關聯的job進行執行。] scheduler.Start(); //job var job = JobBuilder.Create<JobTest>().Build(); //trigger var trigger = TriggerBuilder.Create().WithSimpleSchedule(x => x .WithIntervalInSeconds(1)//1s鍾執行一次 .RepeatForever()//重複執行 .Build()).Build(); //添加監聽 scheduler.ListenerManager.AddJobListener(new MyJobListener(), GroupMatcher<JobKey>.AnyGroup()); //開始調度 scheduler.ScheduleJob(job, trigger); Console.ReadLine(); } //面向AOP public class MyJobListener : IJobListener { public string Name => "test"; //job開始執行以前調用 public async Task JobExecutionVetoed(IJobExecutionContext context, CancellationToken cancellationToken = default(CancellationToken)) { Console.WriteLine("JobExecutionVetoed"); } //job每次執行以後調用 public async Task JobToBeExecuted(IJobExecutionContext context, CancellationToken cancellationToken = default(CancellationToken)) { Console.WriteLine("JobToBeExecuted"); } //job執行結束以後調用 public async Task JobWasExecuted(IJobExecutionContext context, JobExecutionException jobException, CancellationToken cancellationToken = default(CancellationToken)) { Console.WriteLine("JobWasExecuted"); } } } public class JobTest : IJob { public async Task Execute(IJobExecutionContext context) { Console.WriteLine("asd"); } } }
2、 quartz的五大構件async
1. Scheduler [一個大容器]ide
2. job測試
3. triggerui
4. SimpleThreadPool [最終的執行都是要委託給線程池]spa
10[WorkThread] + 1 [調度線程 QuartzSchedulerThread] => QuarzThread線程
SimpleThreadPool 默認是10個thread,是在thread上面進行的封裝,不是線程池線程。。。設計
QuartzSchedulerThread => public override void Run()3d
5. JobStore =>DbStore,RAMStorecode
timeTriggers 用於獲取最近的trigger的。
3、Job詳解 【JobBuilder】
var job = JobBuilder.Create<HelloJob>().Build();
在JobBuilder中執行執行的Action有四種方法。。。 Create 和 OfType
1. Create<T>
寫代碼方便。。
2. Type類型
後期綁定。。。。
Action不是來自解決方案的。。。 可能你要執行的Action來自於其餘的團隊,對方所作的事情就是實現一下IJob接口就能夠了。。。
咱們拿到這個Dll,作反射,直接把job丟給scheduler。。。。
3,StoreDurably方法
設置job是否持久化
默認狀況下: 一旦job沒有相對應的trigger,那麼這個job會被刪除。。。
若是一對一的狀況下,trigger刪除,job也會被刪除。。。
全部的Job,Trigger 都是在RAMJobStore裏面。。。
4,UsingJobData / SetJobData 都是給一個Job添加附加信息。。。
JobDataMap 就是一個字典,用於添加多個信息。。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Quartz; using Quartz.Impl; using Quartz.Listener; using Quartz.Impl.Matchers; using System.Threading; namespace ConsoleApp3 { class Program { static void Main(string[] args) { //scheduler [10 +1 都開啓了,只不過都是等待狀態] var scheduler = StdSchedulerFactory.GetDefaultScheduler().Result; //[start 會讓 調度線程 啓動,從jobstore中獲取快要執行的trigger,而後獲取trigger關聯的job進行執行。] scheduler.Start(); //job var job = JobBuilder.Create<JobTest>() .StoreDurably(true) .UsingJobData("username","hunter")//都是給一個Job添加附加信息 .Build(); //trigger var trigger = TriggerBuilder.Create().WithSimpleSchedule(x => x .WithIntervalInSeconds(1)//1s鍾執行一次 .RepeatForever()//重複執行 .Build()).Build(); //添加監聽 scheduler.ListenerManager.AddJobListener(new MyJobListener(), GroupMatcher<JobKey>.AnyGroup()); //開始調度 scheduler.ScheduleJob(job, trigger); Console.ReadLine(); } //面向AOP public class MyJobListener : IJobListener { public string Name => "test"; //job開始執行以前調用 public async Task JobExecutionVetoed(IJobExecutionContext context, CancellationToken cancellationToken = default(CancellationToken)) { Console.WriteLine("JobExecutionVetoed"); } //job每次執行以後調用 public async Task JobToBeExecuted(IJobExecutionContext context, CancellationToken cancellationToken = default(CancellationToken)) { Console.WriteLine("JobToBeExecuted"); } //job執行結束以後調用 public async Task JobWasExecuted(IJobExecutionContext context, JobExecutionException jobException, CancellationToken cancellationToken = default(CancellationToken)) { Console.WriteLine("JobWasExecuted"); } } } public class JobTest : IJob { public async Task Execute(IJobExecutionContext context) { //獲取附加信息 Console.WriteLine(context.MergedJobDataMap["username"]); } } }
5,WithIdentity: 若是沒有制定,那麼系統會給一個Guid的標識
if (key == null) { key = new JobKey(Guid.NewGuid().ToString(), null); }
4、TriggerBuilder
1. StartAt,EndAt,StartNow Trigger觸發的起始時間和結束時間
DateTimeOffset有時區概念,DateTime沒有時區的概念
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Quartz; using Quartz.Impl; using Quartz.Listener; using Quartz.Impl.Matchers; using System.Threading; namespace ConsoleApp3 { class Program { static void Main(string[] args) { //scheduler [10 +1 都開啓了,只不過都是等待狀態] var scheduler = StdSchedulerFactory.GetDefaultScheduler().Result; //[start 會讓 調度線程 啓動,從jobstore中獲取快要執行的trigger,而後獲取trigger關聯的job進行執行。] scheduler.Start(); //job var job = JobBuilder.Create<JobTest>() .StoreDurably(true) .UsingJobData("username","hunter")//都是給一個Job添加附加信息 .Build(); Console.WriteLine("開始"); //trigger var trigger = TriggerBuilder.Create() .StartAt(DateTimeOffset.Now.AddSeconds(1))//開始執行時間 .EndAt(DateTimeOffset.Now.AddSeconds(5))//執行結束時間 .WithSimpleSchedule(x => x .WithIntervalInSeconds(1)//1s鍾執行一次 .RepeatForever()//重複執行 .Build()).Build(); //添加監聽 scheduler.ListenerManager.AddJobListener(new MyJobListener(), GroupMatcher<JobKey>.AnyGroup()); //開始調度 scheduler.ScheduleJob(job, trigger); Console.ReadLine(); } //面向AOP public class MyJobListener : IJobListener { public string Name => "test"; //job開始執行以前調用 public async Task JobExecutionVetoed(IJobExecutionContext context, CancellationToken cancellationToken = default(CancellationToken)) { Console.WriteLine("JobExecutionVetoed"); } //job每次執行以後調用 public async Task JobToBeExecuted(IJobExecutionContext context, CancellationToken cancellationToken = default(CancellationToken)) { Console.WriteLine("JobToBeExecuted"); } //job執行結束以後調用 public async Task JobWasExecuted(IJobExecutionContext context, JobExecutionException jobException, CancellationToken cancellationToken = default(CancellationToken)) { Console.WriteLine("JobWasExecuted"); } } } public class JobTest : IJob { public async Task Execute(IJobExecutionContext context) { //獲取附加信息 Console.WriteLine(context.MergedJobDataMap["username"]); } } }
2,其餘一些方法
.ForJob(job)//在定義Trigger的時候,就能夠將對應關係作起來
.UsingJobData("aa","abc")//給Job添加附加信息
.WithPriority(1)//默認優先級【5】(優先級數字越大,優先級越高)
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Quartz; using Quartz.Impl; using Quartz.Listener; using Quartz.Impl.Matchers; using System.Threading; namespace ConsoleApp3 { class Program { static void Main(string[] args) { //scheduler [10 +1 都開啓了,只不過都是等待狀態] var scheduler = StdSchedulerFactory.GetDefaultScheduler().Result; //[start 會讓 調度線程 啓動,從jobstore中獲取快要執行的trigger,而後獲取trigger關聯的job進行執行。] scheduler.Start(); //job var job = JobBuilder.Create<JobTest>() .StoreDurably(true) .UsingJobData("username","hunter")//都是給一個Job添加附加信息 .Build(); Console.WriteLine("開始"); //trigger var trigger = TriggerBuilder.Create() .StartAt(DateTimeOffset.Now.AddSeconds(1))//開始執行時間 .EndAt(DateTimeOffset.Now.AddSeconds(5))//執行結束時間 .ForJob(job)//在定義Trigger的時候,就能夠將對應關係作起來 .UsingJobData("aa","abc")//給Job添加附加信息 .WithPriority(1)//默認優先級【5】(優先級數字越大,優先級越高) .WithSimpleSchedule(x => x .WithIntervalInSeconds(1)//1s鍾執行一次 .RepeatForever()//重複執行 .Build()).Build(); //添加監聽 scheduler.ListenerManager.AddJobListener(new MyJobListener(), GroupMatcher<JobKey>.AnyGroup()); //開始調度 scheduler.ScheduleJob(job, trigger); Console.ReadLine(); } //面向AOP public class MyJobListener : IJobListener { public string Name => "test"; //job開始執行以前調用 public async Task JobExecutionVetoed(IJobExecutionContext context, CancellationToken cancellationToken = default(CancellationToken)) { Console.WriteLine("JobExecutionVetoed"); } //job每次執行以後調用 public async Task JobToBeExecuted(IJobExecutionContext context, CancellationToken cancellationToken = default(CancellationToken)) { Console.WriteLine("JobToBeExecuted"); } //job執行結束以後調用 public async Task JobWasExecuted(IJobExecutionContext context, JobExecutionException jobException, CancellationToken cancellationToken = default(CancellationToken)) { Console.WriteLine("JobWasExecuted"); } } } public class JobTest : IJob { public async Task Execute(IJobExecutionContext context) { //獲取附加信息 Console.WriteLine(context.MergedJobDataMap["aa"]); } } }
5、四大trigger調度器
1,Simplescheduler
特色:只能在時分秒上作輪詢
RepeatForever() 指定觸發器將無限重複 WithInterval(TimeSpan timeSpan) 指定重複間隔(以毫秒爲單位) WithIntervalInHours(int hours) 指定重複間隔(以小時爲單位) WithIntervalInMinutes(int minutes) 指定重複間隔(以分鐘爲單位) WithIntervalInSeconds(int seconds) 以秒爲單位指定重複間隔 WithRepeatCount(int repeatCount) 重複執行次數(repeatCount+1)
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Quartz; using Quartz.Impl; using Quartz.Listener; using Quartz.Impl.Matchers; using System.Threading; namespace ConsoleApp3 { class Program { static void Main(string[] args) { //scheduler [10 +1 都開啓了,只不過都是等待狀態] var scheduler = StdSchedulerFactory.GetDefaultScheduler().Result; //[start 會讓 調度線程 啓動,從jobstore中獲取快要執行的trigger,而後獲取trigger關聯的job進行執行。] scheduler.Start(); //job var job = JobBuilder.Create<JobTest>().Build(); Console.WriteLine("開始"); //trigger var trigger = TriggerBuilder.Create().WithSimpleSchedule(x => x .WithIntervalInSeconds(1) .RepeatForever() .Build()).Build(); //開始調度 scheduler.ScheduleJob(job, trigger); Console.ReadLine(); } } public class JobTest : IJob { private static int index = 0; public async Task Execute(IJobExecutionContext context) { //記錄當前時間,記錄「scheduler」調度時間 ,記錄 下一次觸發時間 Console.WriteLine("index={0}, current={1},schedulertime={2},nexttime={3}", index++, DateTime.Now, context.ScheduledFireTimeUtc?.LocalDateTime, context.NextFireTimeUtc?.LocalDateTime); } } }
2, CalendarIntervalSchedule
特色:和日曆相關的輪詢(1天執行一次,一週執行一次,一個月執行一次,一年執行一次)
WithInterval(int interval, IntervalUnit unit) 指定重複間隔 WithIntervalInDays(int intervalInDays) 指定重複間隔(按天) WithIntervalInHours(int intervalInHours) 指定重複間隔(按小時) WithIntervalInMinutes(int intervalInMinutes) 指定重複間隔(按分鐘) WithIntervalInMonths(int intervalInMonths) 指定重複間隔(按月) WithIntervalInSeconds(int intervalInSeconds) 指定重複間隔(按秒) WithIntervalInWeeks(int intervalInWeeks) 指定重複間隔(按星期) WithIntervalInYears(int intervalInYears) 指定重複間隔(按年)
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Quartz; using Quartz.Impl; using Quartz.Listener; using Quartz.Impl.Matchers; using System.Threading; namespace ConsoleApp3 { class Program { static void Main(string[] args) { //scheduler [10 +1 都開啓了,只不過都是等待狀態] var scheduler = StdSchedulerFactory.GetDefaultScheduler().Result; //[start 會讓 調度線程 啓動,從jobstore中獲取快要執行的trigger,而後獲取trigger關聯的job進行執行。] scheduler.Start(); //job var job = JobBuilder.Create<JobTest>().Build(); Console.WriteLine("開始"); //trigger var trigger = TriggerBuilder.Create().WithCalendarIntervalSchedule(x => x .WithIntervalInWeeks(2)//每兩週執行一次 .Build()).Build(); //開始調度 scheduler.ScheduleJob(job, trigger); Console.ReadLine(); } } public class JobTest : IJob { private static int index = 0; public async Task Execute(IJobExecutionContext context) { //記錄當前時間,記錄「scheduler」調度時間 ,記錄 下一次觸發時間 Console.WriteLine("index={0}, current={1},schedulertime={2},nexttime={3}", index++, DateTime.Now, context.ScheduledFireTimeUtc?.LocalDateTime, context.NextFireTimeUtc?.LocalDateTime); } } }
3,DailyTimeIntervalScheduleBuilder
OnMondayThroughFriday() 週一至週五執行 OnSaturdayAndSunday() 週六和週日執行
OnEveryDay() 一週全部日子 WithInterval(int interval, IntervalUnit unit) 指定要生成的觸發器的時間單位和時間間隔。 WithIntervalInHours(int intervalInHours) 指定重複間隔(按天) WithIntervalInMinutes(int intervalInMinutes) 指定重複間隔(按分鐘) WithIntervalInSeconds(int intervalInSeconds) 指定重複間隔(按秒) StartingDailyAt(TimeOfDay.HourAndMinuteOfDay(8, 00) 開始執行時間 EndingDailyAt(TimeOfDay.HourAndMinuteOfDay(20, 00) 結束時間
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Quartz; using Quartz.Impl; using Quartz.Listener; using Quartz.Impl.Matchers; using System.Threading; namespace ConsoleApp3 { class Program { static void Main(string[] args) { //scheduler [10 +1 都開啓了,只不過都是等待狀態] var scheduler = StdSchedulerFactory.GetDefaultScheduler().Result; //[start 會讓 調度線程 啓動,從jobstore中獲取快要執行的trigger,而後獲取trigger關聯的job進行執行。] scheduler.Start(); //job var job = JobBuilder.Create<JobTest>().Build(); Console.WriteLine("開始"); //30分鐘檢測一次,8點-20點 //trigger var trigger = TriggerBuilder.Create().WithDailyTimeIntervalSchedule(x => x .OnEveryDay()//沒天執行 .StartingDailyAt(TimeOfDay.HourAndMinuteOfDay(8,0))//開始執行時間 .EndingDailyAt(TimeOfDay.HourAndMinuteOfDay(20,0))//結束執行時間 .WithIntervalInMinutes(30)//無論何時執行的此程序,都是每30分鐘整點執行一次(例如8:30,13:30) .Build()).Build(); //開始調度 scheduler.ScheduleJob(job, trigger); Console.ReadLine(); } } public class JobTest : IJob { private static int index = 0; public async Task Execute(IJobExecutionContext context) { index++; //記錄當前時間,記錄「scheduler」調度時間 ,記錄 下一次觸發時間 Console.WriteLine("index={0}, current={1},schedulertime={2},nexttime={3}", index, DateTime.Now, context.ScheduledFireTimeUtc?.LocalDateTime, context.NextFireTimeUtc?.LocalDateTime); } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Quartz; using Quartz.Impl; using Quartz.Listener; using Quartz.Impl.Matchers; using System.Threading; namespace ConsoleApp3 { class Program { static void Main(string[] args) { //scheduler [10 +1 都開啓了,只不過都是等待狀態] var scheduler = StdSchedulerFactory.GetDefaultScheduler().Result; //[start 會讓 調度線程 啓動,從jobstore中獲取快要執行的trigger,而後獲取trigger關聯的job進行執行。] scheduler.Start(); //job var job = JobBuilder.Create<JobTest>().Build(); Console.WriteLine("開始"); //天天凌晨2點跑一次 //trigger var trigger = TriggerBuilder.Create().WithDailyTimeIntervalSchedule(x => x .OnEveryDay()//沒天執行 .StartingDailyAt(TimeOfDay.HourAndMinuteOfDay(2,0))//開始執行時間 .EndingDailyAt(TimeOfDay.HourAndMinuteOfDay(2,1))//結束執行時間 .WithIntervalInMinutes(30)//巧妙設計,是程序天天只執行一次 .Build()).Build(); //注意作一個問題:在測試的時候先調整好計算機時間,在run此程序 //若是先run程序,在調整時間,會有問題 //開始調度 scheduler.ScheduleJob(job, trigger); Console.ReadLine(); } } public class JobTest : IJob { private static int index = 0; public async Task Execute(IJobExecutionContext context) { index++; //記錄當前時間,記錄「scheduler」調度時間 ,記錄 下一次觸發時間 Console.WriteLine("index={0}, current={1},schedulertime={2},nexttime={3}", index, DateTime.Now, context.ScheduledFireTimeUtc?.LocalDateTime, context.NextFireTimeUtc?.LocalDateTime); } } }
5,WithCronSchedule
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Quartz; using Quartz.Impl; using Quartz.Listener; using Quartz.Impl.Matchers; using System.Threading; namespace ConsoleApp3 { class Program { static void Main(string[] args) { //scheduler [10 +1 都開啓了,只不過都是等待狀態] var scheduler = StdSchedulerFactory.GetDefaultScheduler().Result; //[start 會讓 調度線程 啓動,從jobstore中獲取快要執行的trigger,而後獲取trigger關聯的job進行執行。] scheduler.Start(); //job var job = JobBuilder.Create<JobTest>().Build(); Console.WriteLine("開始"); //trigger var trigger = TriggerBuilder.Create().WithCronSchedule("* * * ? * MON").Build(); //注意作一個問題:在測試的時候先調整好計算機時間,在run此程序 //若是先run程序,在調整時間,會有問題 //開始調度 scheduler.ScheduleJob(job, trigger); Console.ReadLine(); } } public class JobTest : IJob { private static int index = 0; public async Task Execute(IJobExecutionContext context) { index++; //記錄當前時間,記錄「scheduler」調度時間 ,記錄 下一次觸發時間 Console.WriteLine("index={0}, current={1},schedulertime={2},nexttime={3}", index, DateTime.Now, context.ScheduledFireTimeUtc?.LocalDateTime, context.NextFireTimeUtc?.LocalDateTime); } } }
quartz中的cron表達式和Linux下的很相似,好比 "/5 * * ? * * *" 這樣的7位表達式,最後一位年非必選。
表達式從左到右,依此是秒、分、時、月第幾天、月、周幾、年。下面表格是要遵照的規範:
字段名 | 容許的值 | 容許的特殊字符 |
---|---|---|
Seconds | 0-59 | , - * / |
Minutes | 0-59 | , - * / |
Hours | 0-23 | , - * / |
Day of month | 1-31 | , - * ? / L W |
Month | 1-12 or JAN-DEC | , - * / |
Day of week | 1-7 or SUN-SAT | , - * ? / L # |
Year | 空, 1970-2099 | , - * / |
星期一 MON
星期二 TUE
星期三 WED
星期四 THU
星期五 FRI
星期六 SAT
星期天 SUN
特殊字符 | 解釋 |
, | 或的意思。例:分鐘位 5,10 即第5分鐘或10分都觸發。 |
/ | a/b。 a:表明起始時間,b頻率時間。 例; 分鐘位 3/5, 從第三分鐘開始,每5分鐘執行一次。 |
* | 頻率。 即每一次波動。 例;分鐘位 * 即表示每分鐘 |
- | 區間。 例: 分鐘位 5-10 即5到10分期間。 |
? | 任意值 。 即每一次波動。只能用在DayofMonth和DayofWeek,兩者衝突。指定一個另外一個一個要用? |
L | 表示最後。 只能用在DayofMonth和DayofWeek,4L即最後一個星期三 |
W | 工做日。 表示最後。 只能用在DayofWeek |
# | 4#2。 只能用DayofMonth。 某月的第二個星期三 |
實例:
天天8-20點間隔28分鐘執行一次:0 0/28 8-20 * * ?"
間隔10秒跑一次:0/10 * 8-20 * * ?
天天8-20天,30分鐘執行一次: 0 0/30 8-20 * * ?
週一到週五凌晨2點執行: 0 0 2 ? * MON-FRI 執行一次
」0 0 10,14,16 * * ?" 天天10點,14點,16點 觸發。
"0 0/5 14,18 * * ?" 天天14點或18點中,每5分鐘觸發 。
"0 4/15 14-18 * * ?" 天天14點到18點期間, 從第四分鐘觸發,每15分鐘一次。
"0 15 10 ? * 6L" 每個月的最後一個星期五上午10:15觸發。
6、操做案例
1,trigger先綁定job,而後在執行
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Quartz; using Quartz.Impl; using Quartz.Listener; using Quartz.Impl.Matchers; using System.Threading; namespace ConsoleApp3 { class Program { static void Main(string[] args) { Console.WriteLine("開始"); //scheduler [10 +1 都開啓了,只不過都是等待狀態] var scheduler = StdSchedulerFactory.GetDefaultScheduler().Result; //[start 會讓 調度線程 啓動,從jobstore中獲取快要執行的trigger,而後獲取trigger關聯的job進行執行。] scheduler.Start(); //job var job = JobBuilder.Create<JobTest>() .StoreDurably(true) .Build(); scheduler.AddJob(job, true); //trigger var trigger = TriggerBuilder.Create().ForJob(job) .WithCronSchedule("* * * * * ?").Build(); //使用這句話的前提是job必須是持久化的,不然只能使用下面那句話 scheduler.ScheduleJob(trigger); //scheduler.ScheduleJob(job,trigger); Console.ReadLine(); } } public class JobTest : IJob { private static int index = 0; public async Task Execute(IJobExecutionContext context) { index++; //記錄當前時間,記錄「scheduler」調度時間 ,記錄 下一次觸發時間 Console.WriteLine("index={0}, current={1},schedulertime={2},nexttime={3}", index, DateTime.Now, context.ScheduledFireTimeUtc?.LocalDateTime, context.NextFireTimeUtc?.LocalDateTime); } } }
2,job操做
List<JobDetailImpl> jobList = new List<JobDetailImpl>(); //第一步:獲取全部的job信息 var jobKeySet = scheduler.GetJobKeys(GroupMatcher<JobKey>.AnyGroup()); foreach (var jobKey in jobKeySet) { var jobDetail = (JobDetailImpl)scheduler.GetJobDetail(jobKey); jobList.Add(jobDetail); } var json = JsonConvert.SerializeObject(jobList.Select(i => new { i.Name, i.Group, i.Durable, i.JobDataMap, i.Description, TriggerList = string.Join(",", scheduler.GetTriggersOfJob(new JobKey(i.Name, i.Group)) .Select(m => m.Key.ToString())) }));
var exists = scheduler.CheckExists(new JobKey(jobRequest.JobName, jobRequest.JobGroupName)); if (exists && !jobRequest.IsEdit) { return Json("已經存在同名的Job,請更換!"); } var assemblyName = jobRequest.JobFullClass.Split('.')[0]; var fullName = jobRequest.JobFullClass; var dllpath = Request.MapPath(string.Format("~/bin/{0}.dll", assemblyName)); //須要執行的job名稱 var jobClassName = Assembly.LoadFile(dllpath) .CreateInstance(jobRequest.JobFullClass); //第一種方式: var job = JobBuilder.Create(jobClassName.GetType()).StoreDurably(true) .WithIdentity(jobRequest.JobName, jobRequest.JobGroupName) .WithDescription(jobRequest.Description) .Build(); scheduler.AddJob(job, true); //第二種方式:獲取job信息,再更新實體。。。 var jobdetail = scheduler.GetJobDetail(new JobKey(jobRequest.JobName, jobRequest.JobGroupName));
//job暫停,全部關聯的trigger也必須暫停 scheduler.PauseJob(new JobKey(jobName, groupName));
scheduler.ResumeJob(new JobKey(jobName, groupName));
2,trigger操做
List<CronTriggerImpl> triggerList = new List<CronTriggerImpl>(); //第一步:獲取全部的trigger信息 var triggerKeys = scheduler.GetTriggerKeys(GroupMatcher<TriggerKey>.AnyGroup()); foreach (var triggerkey in triggerKeys) { var triggerDetail = (CronTriggerImpl)scheduler.GetTrigger(triggerkey); triggerList.Add(triggerDetail); } var json = JsonConvert.SerializeObject(triggerList.Select(i => new { i.FullName, i.FullJobName, i.CronExpressionString, JobClassName = scheduler.GetJobDetail(i.JobKey).JobType.FullName, StartFireTime = i.StartTimeUtc.LocalDateTime.ToString("yyyy-MM-dd HH:mm:ss"), PrevFireTime = i.GetPreviousFireTimeUtc()?.LocalDateTime.ToString("yyyy-MM-dd HH:mm:ss"), NextFireTime = i.GetNextFireTimeUtc()?.LocalDateTime.ToString("yyyy-MM-dd HH:mm:ss"), TriggerStatus = scheduler.GetTriggerState(new TriggerKey(i.Name, i.Group)).ToString(), i.Priority, i.Description, i.Name, i.Group }));
var exists = scheduler.CheckExists(new TriggerKey(triggerRequest.TriggerName, triggerRequest.TriggerGroupName)); if (exists) { return Json("已經存在同名的trigger,請更換!"); } var forJobName = triggerRequest.ForJobName.Split('.'); var trigger = TriggerBuilder.Create().ForJob(forJobName[1], forJobName[0]) .WithIdentity(triggerRequest.TriggerName, triggerRequest.TriggerGroupName) .WithCronSchedule(triggerRequest.CronExpress) .WithDescription(triggerRequest.Description) .Build(); scheduler.ScheduleJob(trigger);
//暫停 「某一個trigger」 scheduler.PauseTrigger(new TriggerKey(name, group));
//恢復 「某一個trigger」 scheduler.ResumeTrigger(new TriggerKey(name, group));
scheduler.UnscheduleJob(new TriggerKey(name, group));
//編輯Trigger var forJobName = triggerRequest.ForJobName.Split('.'); var trigger = TriggerBuilder.Create().ForJob(forJobName[1], forJobName[0]) .WithIdentity(triggerRequest.TriggerName, triggerRequest.TriggerGroupName) .WithCronSchedule(triggerRequest.CronExpress) .WithDescription(triggerRequest.Description) .Build(); //編輯trigger操做 scheduler.RescheduleJob(new TriggerKey(triggerRequest.TriggerName, triggerRequest.TriggerGroupName), trigger);
3,scheduler操做
var meta = scheduler.GetMetaData();
if (scheduler.InStandbyMode) { //只有暫停的狀態,才能從新開啓 scheduler.Start(); }
if (scheduler.IsStarted) { //暫停scheduler scheduler.Standby(); }
if (scheduler.IsStarted || scheduler.InStandbyMode) { //暫停scheduler scheduler.Shutdown(); }
4,整個demo
using Newtonsoft.Json; using Quartz; using Quartz.Impl; using Quartz.Impl.Matchers; using Quartz.Impl.Triggers; using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Web; using System.Web.Mvc; using WebApplication1.Entitys; namespace WebApplication1.Controllers { [RoutePrefix("quartz")] public class QuartzController : Controller { static IScheduler scheduler = null; static QuartzController() { scheduler = StdSchedulerFactory.GetDefaultScheduler(); scheduler.Start(); } [Route("index")] public ActionResult Index() { return View(); } //查詢job [Route("joblist")] public JsonResult JobList() { List<JobDetailImpl> jobList = new List<JobDetailImpl>(); //第一步:獲取全部的job信息 var jobKeySet = scheduler.GetJobKeys(GroupMatcher<JobKey>.AnyGroup()); foreach (var jobKey in jobKeySet) { var jobDetail = (JobDetailImpl)scheduler.GetJobDetail(jobKey); jobList.Add(jobDetail); } var json = JsonConvert.SerializeObject(jobList.Select(i => new { i.Name, i.Group, i.Durable, i.JobDataMap, i.Description, TriggerList = string.Join(",", scheduler.GetTriggersOfJob(new JobKey(i.Name, i.Group)) .Select(m => m.Key.ToString())) })); return Json(json); } //添加job [Route("addjob")] public JsonResult AddJob(JobRequestEntity jobRequest) { try { var exists = scheduler.CheckExists(new JobKey(jobRequest.JobName, jobRequest.JobGroupName)); if (exists && !jobRequest.IsEdit) { return Json("已經存在同名的Job,請更換!"); } var assemblyName = jobRequest.JobFullClass.Split('.')[0]; var fullName = jobRequest.JobFullClass; var dllpath = Request.MapPath(string.Format("~/bin/{0}.dll", assemblyName)); //須要執行的job名稱 var jobClassName = Assembly.LoadFile(dllpath) .CreateInstance(jobRequest.JobFullClass); //第一種方式: var job = JobBuilder.Create(jobClassName.GetType()).StoreDurably(true) .WithIdentity(jobRequest.JobName, jobRequest.JobGroupName) .WithDescription(jobRequest.Description) .Build(); scheduler.AddJob(job, true); //第二種方式:獲取job信息,再更新實體。。。 var jobdetail = scheduler.GetJobDetail(new JobKey(jobRequest.JobName, jobRequest.JobGroupName)); return Json("1"); } catch (Exception ex) { throw; } } //暫停job(可恢復) [Route("pausejob")] public JsonResult PauseJob(string jobName, string groupName) { try { //job暫停,全部關聯的trigger也必須暫停 scheduler.PauseJob(new JobKey(jobName, groupName)); return Json(1); } catch (Exception ex) { throw; } } //恢復job [Route("resumejob")] public JsonResult ResumeJob(string jobName, string groupName) { try { scheduler.ResumeJob(new JobKey(jobName, groupName)); return Json(1); } catch (Exception ex) { throw; } } //刪除job [Route("removejob")] public JsonResult RemoveJob(string jobName, string groupName) { try { var isSuccess = scheduler.DeleteJob(new JobKey(jobName, groupName)); return Json(isSuccess); } catch (Exception ex) { throw; } } //trigger查詢 [Route("triggerlist")] public JsonResult TriggerList() { List<CronTriggerImpl> triggerList = new List<CronTriggerImpl>(); //第一步:獲取全部的trigger信息 var triggerKeys = scheduler.GetTriggerKeys(GroupMatcher<TriggerKey>.AnyGroup()); foreach (var triggerkey in triggerKeys) { var triggerDetail = (CronTriggerImpl)scheduler.GetTrigger(triggerkey); triggerList.Add(triggerDetail); } var json = JsonConvert.SerializeObject(triggerList.Select(i => new { i.FullName, i.FullJobName, i.CronExpressionString, JobClassName = scheduler.GetJobDetail(i.JobKey).JobType.FullName, StartFireTime = i.StartTimeUtc.LocalDateTime.ToString("yyyy-MM-dd HH:mm:ss"), PrevFireTime = i.GetPreviousFireTimeUtc()?.LocalDateTime.ToString("yyyy-MM-dd HH:mm:ss"), NextFireTime = i.GetNextFireTimeUtc()?.LocalDateTime.ToString("yyyy-MM-dd HH:mm:ss"), TriggerStatus = scheduler.GetTriggerState(new TriggerKey(i.Name, i.Group)).ToString(), i.Priority, i.Description, i.Name, i.Group })); return Json(json); } //添加trigger [Route("addtrigger")] public JsonResult AddTrigger(TriggerRequestEntity triggerRequest) { try { var exists = scheduler.CheckExists(new TriggerKey(triggerRequest.TriggerName, triggerRequest.TriggerGroupName)); if (exists) { return Json("已經存在同名的trigger,請更換!"); } var forJobName = triggerRequest.ForJobName.Split('.'); var trigger = TriggerBuilder.Create().ForJob(forJobName[1], forJobName[0]) .WithIdentity(triggerRequest.TriggerName, triggerRequest.TriggerGroupName) .WithCronSchedule(triggerRequest.CronExpress) .WithDescription(triggerRequest.Description) .Build(); scheduler.ScheduleJob(trigger); return Json("1"); } catch (Exception ex) { throw; } } //暫停trigger(可恢復) [Route("pausetrigger")] public JsonResult PauseTrigger(string name, string group) { try { //暫停 「某一個trigger」 scheduler.PauseTrigger(new TriggerKey(name, group)); return Json("1"); } catch (Exception ex) { throw; } } //恢復trigger [Route("resumetrigger")] public JsonResult ResumeTrigger(string name, string group) { try { //恢復 「某一個trigger」 scheduler.ResumeTrigger(new TriggerKey(name, group)); return Json("1"); } catch (Exception ex) { throw; } } //刪除trigger [Route("removetrigger")] public JsonResult RemoveTrigger(string name, string group) { try { scheduler.UnscheduleJob(new TriggerKey(name, group)); return Json("1"); } catch (Exception ex) { throw; } } //編輯trigger [Route("edittrigger")] public JsonResult EditTrigger(TriggerRequestEntity triggerRequest) { try { //編輯Trigger var forJobName = triggerRequest.ForJobName.Split('.'); var trigger = TriggerBuilder.Create().ForJob(forJobName[1], forJobName[0]) .WithIdentity(triggerRequest.TriggerName, triggerRequest.TriggerGroupName) .WithCronSchedule(triggerRequest.CronExpress) .WithDescription(triggerRequest.Description) .Build(); //編輯trigger操做 scheduler.RescheduleJob(new TriggerKey(triggerRequest.TriggerName, triggerRequest.TriggerGroupName), trigger); return Json("1"); } catch (Exception ex) { throw; } } //獲取scheduler元數據信息 [Route("getmeta")] public JsonResult GetMeta() { try { var meta = scheduler.GetMetaData(); var json = JsonConvert.SerializeObject(meta); return Json(json); } catch (Exception ex) { throw; } } /// <summary> /// 恢復scheduler /// </summary> /// <returns></returns> [Route("resumescheduler")] public JsonResult ResumeScheduler() { try { if (scheduler.InStandbyMode) { //只有暫停的狀態,才能從新開啓 scheduler.Start(); } return Json(1); } catch (Exception ex) { throw; } } /// <summary> /// 暫停scheduler /// </summary> /// <returns></returns> [Route("pausescheduler")] public JsonResult PauseScheduler() { try { if (scheduler.IsStarted) { //暫停scheduler scheduler.Standby(); } return Json(1); } catch (Exception ex) { throw; } } /// <summary> /// 關閉scheduler /// </summary> /// <returns></returns> [Route("shutdownscheduler")] public JsonResult ShutDownScheduler() { try { if (scheduler.IsStarted || scheduler.InStandbyMode) { //暫停scheduler scheduler.Shutdown(); } return Json(1); } catch (Exception ex) { throw; } } } }
下載地址:https://pan.baidu.com/s/1uQMuQEvsky1poiBzg1H3JA
7、六大calendar排除
1,DailyCalendar
【適合在某一天的時間段上作「減法操做」】
能夠動態的排除某天的某些時間段
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Quartz; using Quartz.Impl; using Quartz.Listener; using Quartz.Impl.Matchers; using System.Threading; using Quartz.Impl.Calendar; namespace ConsoleApp3 { class Program { static void Main(string[] args) { Console.WriteLine("開始"); //scheduler [10 +1 都開啓了,只不過都是等待狀態] var scheduler = StdSchedulerFactory.GetDefaultScheduler().Result; //[start 會讓 調度線程 啓動,從jobstore中獲取快要執行的trigger,而後獲取trigger關聯的job進行執行。] scheduler.Start(); //job var job = JobBuilder.Create<JobTest>() .StoreDurably(true) .Build(); scheduler.AddJob(job, true); //trigger var trigger = TriggerBuilder.Create().ForJob(job) .ModifiedByCalendar("daily") .WithCronSchedule("* * * * * ?").Build(); //天天20點到21點不要執行 var daily = new DailyCalendar(DateBuilder.DateOf(20, 0, 0).DateTime, DateBuilder.DateOf(21, 0, 0).DateTime); scheduler.AddCalendar("daily", daily, true, true); scheduler.ScheduleJob(trigger); Console.ReadLine(); } } public class JobTest : IJob { private static int index = 0; public async Task Execute(IJobExecutionContext context) { index++; //記錄當前時間,記錄「scheduler」調度時間 ,記錄 下一次觸發時間 Console.WriteLine("index={0}, current={1},schedulertime={2},nexttime={3}", index, DateTime.Now, context.ScheduledFireTimeUtc?.LocalDateTime, context.NextFireTimeUtc?.LocalDateTime); } } }
2,WeeklyCalendar
【適合以星期幾的維度上作「減法操做」】
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Quartz; using Quartz.Impl; using Quartz.Listener; using Quartz.Impl.Matchers; using System.Threading; using Quartz.Impl.Calendar; namespace ConsoleApp3 { class Program { static void Main(string[] args) { Console.WriteLine("開始"); //scheduler [10 +1 都開啓了,只不過都是等待狀態] var scheduler = StdSchedulerFactory.GetDefaultScheduler().Result; //[start 會讓 調度線程 啓動,從jobstore中獲取快要執行的trigger,而後獲取trigger關聯的job進行執行。] scheduler.Start(); //job var job = JobBuilder.Create<JobTest>() .StoreDurably(true) .Build(); scheduler.AddJob(job, true); //trigger var trigger = TriggerBuilder.Create().ForJob(job) .ModifiedByCalendar("calendar") .WithCronSchedule("* * * * * ?").Build(); //每週五不執行 WeeklyCalendar calendar = new WeeklyCalendar(); calendar.SetDayExcluded(DayOfWeek.Friday, true); scheduler.AddCalendar("calendar", calendar, true, true); scheduler.ScheduleJob(trigger); Console.ReadLine(); } } public class JobTest : IJob { private static int index = 0; public async Task Execute(IJobExecutionContext context) { index++; //記錄當前時間,記錄「scheduler」調度時間 ,記錄 下一次觸發時間 Console.WriteLine("index={0}, current={1},schedulertime={2},nexttime={3}", index, DateTime.Now, context.ScheduledFireTimeUtc?.LocalDateTime, context.NextFireTimeUtc?.LocalDateTime); } } }
3,HolidayCalendar
【適合當年的某一天不能執行】
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Quartz; using Quartz.Impl; using Quartz.Listener; using Quartz.Impl.Matchers; using System.Threading; using Quartz.Impl.Calendar; namespace ConsoleApp3 { class Program { static void Main(string[] args) { Console.WriteLine("開始"); //scheduler [10 +1 都開啓了,只不過都是等待狀態] var scheduler = StdSchedulerFactory.GetDefaultScheduler().Result; //[start 會讓 調度線程 啓動,從jobstore中獲取快要執行的trigger,而後獲取trigger關聯的job進行執行。] scheduler.Start(); //job var job = JobBuilder.Create<JobTest>() .StoreDurably(true) .Build(); scheduler.AddJob(job, true); //trigger var trigger = TriggerBuilder.Create().ForJob(job) .ModifiedByCalendar("calendar") .WithCronSchedule("* * * * * ?").Build(); //指定某一天不能執行 //6月16號不要執行 var calendar = new HolidayCalendar(); calendar.AddExcludedDate(DateTime.Now); scheduler.AddCalendar("calendar", calendar, true, true); scheduler.ScheduleJob(trigger); Console.ReadLine(); } } public class JobTest : IJob { private static int index = 0; public async Task Execute(IJobExecutionContext context) { index++; //記錄當前時間,記錄「scheduler」調度時間 ,記錄 下一次觸發時間 Console.WriteLine("index={0}, current={1},schedulertime={2},nexttime={3}", index, DateTime.Now, context.ScheduledFireTimeUtc?.LocalDateTime, context.NextFireTimeUtc?.LocalDateTime); } } }
4,MonthlyCalendar
【適合某個月中的某一天不能執行】
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Quartz; using Quartz.Impl; using Quartz.Listener; using Quartz.Impl.Matchers; using System.Threading; using Quartz.Impl.Calendar; namespace ConsoleApp3 { class Program { static void Main(string[] args) { Console.WriteLine("開始"); //scheduler [10 +1 都開啓了,只不過都是等待狀態] var scheduler = StdSchedulerFactory.GetDefaultScheduler().Result; //[start 會讓 調度線程 啓動,從jobstore中獲取快要執行的trigger,而後獲取trigger關聯的job進行執行。] scheduler.Start(); //job var job = JobBuilder.Create<JobTest>() .StoreDurably(true) .Build(); scheduler.AddJob(job, true); //trigger var trigger = TriggerBuilder.Create().ForJob(job) .ModifiedByCalendar("calendar") .WithCronSchedule("* * * * * ?").Build(); //每個月20號不要執行 var calendar = new MonthlyCalendar(); calendar.SetDayExcluded(20, true); scheduler.AddCalendar("calendar", calendar, true, true); scheduler.ScheduleJob(trigger); Console.ReadLine(); } } public class JobTest : IJob { private static int index = 0; public async Task Execute(IJobExecutionContext context) { index++; //記錄當前時間,記錄「scheduler」調度時間 ,記錄 下一次觸發時間 Console.WriteLine("index={0}, current={1},schedulertime={2},nexttime={3}", index, DateTime.Now, context.ScheduledFireTimeUtc?.LocalDateTime, context.NextFireTimeUtc?.LocalDateTime); } } }
5,AnnualCalendar
【適合每一年指定的某一天不能執行】
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Quartz; using Quartz.Impl; using Quartz.Listener; using Quartz.Impl.Matchers; using System.Threading; using Quartz.Impl.Calendar; namespace ConsoleApp3 { class Program { static void Main(string[] args) { Console.WriteLine("開始"); //scheduler [10 +1 都開啓了,只不過都是等待狀態] var scheduler = StdSchedulerFactory.GetDefaultScheduler().Result; //[start 會讓 調度線程 啓動,從jobstore中獲取快要執行的trigger,而後獲取trigger關聯的job進行執行。] scheduler.Start(); //job var job = JobBuilder.Create<JobTest>() .StoreDurably(true) .Build(); scheduler.AddJob(job, true); //trigger var trigger = TriggerBuilder.Create().ForJob(job) .ModifiedByCalendar("calendar") .WithCronSchedule("* * * * * ?").Build(); //指定月份中的某一天不能執行 var calendar = new AnnualCalendar(); calendar.SetDayExcluded(DateTime.Now, true); scheduler.AddCalendar("calendar", calendar, true, true); scheduler.ScheduleJob(trigger); Console.ReadLine(); } } public class JobTest : IJob { private static int index = 0; public async Task Execute(IJobExecutionContext context) { index++; //記錄當前時間,記錄「scheduler」調度時間 ,記錄 下一次觸發時間 Console.WriteLine("index={0}, current={1},schedulertime={2},nexttime={3}", index, DateTime.Now, context.ScheduledFireTimeUtc?.LocalDateTime, context.NextFireTimeUtc?.LocalDateTime); } } }
6,CronCalendar
【字符串表達式來排除某一天,某一個月份,某一年均可以】
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Quartz; using Quartz.Impl; using Quartz.Listener; using Quartz.Impl.Matchers; using System.Threading; using Quartz.Impl.Calendar; namespace ConsoleApp3 { class Program { static void Main(string[] args) { Console.WriteLine("開始"); //scheduler [10 +1 都開啓了,只不過都是等待狀態] var scheduler = StdSchedulerFactory.GetDefaultScheduler().Result; //[start 會讓 調度線程 啓動,從jobstore中獲取快要執行的trigger,而後獲取trigger關聯的job進行執行。] scheduler.Start(); //job var job = JobBuilder.Create<JobTest>() .StoreDurably(true) .Build(); scheduler.AddJob(job, true); //trigger var trigger = TriggerBuilder.Create().ForJob(job) .ModifiedByCalendar("calendar") .WithCronSchedule("* * * * * ?").Build(); //4月21號不要執行 var calendar = new CronCalendar("* * * 21 4 ?"); scheduler.AddCalendar("calendar", calendar, true, true); scheduler.ScheduleJob(trigger); Console.ReadLine(); } } public class JobTest : IJob { private static int index = 0; public async Task Execute(IJobExecutionContext context) { index++; //記錄當前時間,記錄「scheduler」調度時間 ,記錄 下一次觸發時間 Console.WriteLine("index={0}, current={1},schedulertime={2},nexttime={3}", index, DateTime.Now, context.ScheduledFireTimeUtc?.LocalDateTime, context.NextFireTimeUtc?.LocalDateTime); } } }