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实例为HelloJob
IJobDetail 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();
//调度器根据触发器规则去调度工作任务 HelloJob
await 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实例为HelloJob
IJobDetail 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();
//调度器根据触发器规则去调度工作任务 HelloJob
await 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实例为HelloJob
IJobDetail 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"));
//调度器根据触发器规则去调度工作任务 HelloJob
await scheduler.ScheduleJob(job, trigger);
}
}
除了可以在Job上增加AOP操作,也能针对触发器增加AOP操作。可以通过实现 ITriggerListener的类来定义一个在触发器触发时的切面类。使用触发器的监听器类时,同样只需要加入到调度器的ListenerManager中。