Quartz
1 Quartz是一个强大的、开源的、轻量级的任务调度框架 Quartz官方文档
2 Quartz中有五个重要的概念
- Scheduler 调度器
- Trigger 触发器
- Job 工作任务
- ThreadPool 线程池 ,不是CLI的线程池,而是Quartz特有的线程池
- JobStrore 调度存储,存储执行计划的具体信息 ,可以存储在内存中RawStore,也可以持久化到数据库中 DbStore
3 使用Quartz需要先导入Nuget依赖包
<ItemGroup><PackageReference Include="Quartz" Version="3.8.1" /></ItemGroup>
4 Quartz的示例代码
public class Demo1{/// <summary>/// 使用WithSimpleSchedule触发器构建简单的间隔重复N次的Job数据/// </summary>/// <returns></returns>public async Task demo1(){//从调度工厂类中获得调度器StdSchedulerFactory factory = new StdSchedulerFactory();IScheduler scheduler = await factory.GetScheduler();await scheduler.Start(); //调度器必须启动,否则调度任务实例的执行{//创建Job 使用建造者模式创建Job,绑定的工作Job实例为HelloJobIJobDetail job = JobBuilder.Create<HelloJob>().WithIdentity("job1", "group1").Build();//创建触发器 group1组下名为trigger1的触发器 。间隔1s,重复次数为3次ITrigger trigger = TriggerBuilder.Create().WithIdentity("trigger1", "group1").StartNow() //立即触发.WithSimpleSchedule(x => x.WithIntervalInSeconds(1).WithRepeatCount(3)).Build();//调度器根据触发器规则去调度工作任务 HelloJobawait scheduler.ScheduleJob(job, trigger);}}/// <summary>/// 使用WithDailyTimeIntervalSchedule来构建复杂的触发器逻辑/// </summary>/// <returns></returns>public async Task demo2() {//从调度工厂类中获得调度器StdSchedulerFactory factory = new StdSchedulerFactory();IScheduler scheduler = await factory.GetScheduler();await scheduler.Start(); {//创建Job 使用建造者模式创建Job,绑定的工作Job实例为HelloJobIJobDetail job = JobBuilder.Create<HelloJob>().WithIdentity("job1", "group1").Build();ITrigger trigger = TriggerBuilder.Create().WithIdentity("trigger1", "group1").StartNow() //立即触发.WithDailyTimeIntervalSchedule(action =>/*** OnDaysOfTheWeek 方法接受一个 DayOfWeek 枚举数组作为参数,你可以传入一个或多个 DayOfWeek 枚举值来指定具体的星期几。* 除了手动列出每一天,Quartz.NET 还提供了一些方便的方法来快速选择一周的特定日子组,例如:* OnMondayThroughFriday(): 周一至周五 OnSaturdayAndSunday(): 周六和周日 OnEveryDay(): 每天*/action.OnDaysOfTheWeek(DayOfWeek.Monday, DayOfWeek.Tuesday, DayOfWeek.Wednesday, DayOfWeek.Thursday, DayOfWeek.Friday) //周一到周五.StartingDailyAt(TimeOfDay.HourAndMinuteOfDay(12, 00)) //每天12点开始.EndingDailyAt(TimeOfDay.HourAndMinuteOfDay(14, 00)) // 每天到23:59结束.WithIntervalInMinutes(30)//每间隔30分钟执行一次.WithRepeatCount(3) //重复3次// .OnEveryDay() //.OnMondayThroughFriday() //.OnSaturdayAndSunday() ).Build();//调度器根据触发器规则去调度工作任务 HelloJobawait scheduler.ScheduleJob(job, trigger);}}/// <summary>/// 使用Corn触发器来触发任务/// </summary>/// <returns></returns>public async Task demo3() {IScheduler scheduler = await StdSchedulerFactory.GetDefaultScheduler();scheduler.Start();{IJobDetail job = JobBuilder.Create<HelloJob>().WithIdentity("job1","group1").Build() ;ITrigger trigger = TriggerBuilder.Create().WithIdentity("trigger1", "group1").WithCronSchedule("* * * * * ? *") //cron表达式执行.Build(); //无限循环执行await scheduler.ScheduleJob(job,trigger);}}/// <summary>/// 触发器排除特定的日期/// </summary>/// <returns></returns>public async Task demo4() {IScheduler scheduler = await StdSchedulerFactory.GetDefaultScheduler();scheduler.Start();{IJobDetail job = JobBuilder.Create<HelloJob>().WithIdentity("job1", "group1").Build();ITrigger trigger = TriggerBuilder.Create().WithIdentity("trigger1", "group1").WithCronSchedule("* * * * * ? *") //cron表达式执行.ModifiedByCalendar("exclude_time") //.Build(); //无限循环执行//排除17:00-17:30的时间DailyCalendar dailyCalendar = new DailyCalendar(DateBuilder.DateOf(17,0,0).DateTime, DateBuilder.DateOf(17,30,0).DateTime);// 将日历添加到调度器await scheduler.AddCalendar("exclude_time", dailyCalendar, false, true);await scheduler.ScheduleJob(job, trigger);}}}
5 Quartz 与AOP
Quartz 中也有自己的切面编程逻辑,可以通过添加监听器的方式,去给工作任务装配额外的工作逻辑,比如记录日志、发送通知或其他自定义业务逻辑。
添加监听器
/// <summary>/// Quartz中的AOP 切面编程/// </summary>public class JobListener : IJobListener{public string Name { get; }public JobListener(string Name) {this.Name = Name;}public Task JobExecutionVetoed(IJobExecutionContext context, CancellationToken cancellationToken = default){throw new NotImplementedException();}/// <summary>/// Job方法前执行/// </summary>/// <param name="context"></param>/// <param name="cancellationToken"></param>/// <returns></returns>public async Task JobToBeExecuted(IJobExecutionContext context, CancellationToken cancellationToken = default){Console.WriteLine("method before ");}/// <summary>/// Job方法后执行/// </summary>/// <param name="context"></param>/// <param name="jobException"></param>/// <param name="cancellationToken"></param>/// <returns></returns>public async Task JobWasExecuted(IJobExecutionContext context, JobExecutionException jobException, CancellationToken cancellationToken = default){Console.WriteLine("method after ");}}
调度器中去装配JobListener
public async Task demo5() {//从调度工厂类中获得调度器StdSchedulerFactory factory = new StdSchedulerFactory();IScheduler scheduler = await factory.GetScheduler();await scheduler.Start(); //调度器必须启动,否则调度任务实例的执行{//创建Job 使用建造者模式创建Job,绑定的工作Job实例为HelloJobIJobDetail job = JobBuilder.Create<HelloJob>().WithIdentity("job1", "group1").Build();//创建触发器 group1组下名为trigger1的触发器 。间隔1s,重复次数为3次ITrigger trigger = TriggerBuilder.Create().WithIdentity("trigger1", "group1").StartNow() //立即触发.WithSimpleSchedule(x => x.WithIntervalInSeconds(1).WithRepeatCount(3)).Build();//调度器注册JobListener,那么触发的工作任务就能在执行前与执行后处理一定的业务逻辑scheduler.ListenerManager.AddJobListener(new JobListener("listener"));//调度器根据触发器规则去调度工作任务 HelloJobawait scheduler.ScheduleJob(job, trigger);}}
除了可以在Job上增加AOP操作,也能针对触发器增加AOP操作。可以通过实现 ITriggerListener的类来定义一个在触发器触发时的切面类。使用触发器的监听器类时,同样只需要加入到调度器的ListenerManager中。