Quartz3.0(任务调度框架)
本文主要讲解:
1 quartZ引入&初始化&使用$核心对象Job、Trigger解析
2 三种Listener扩展订制
3 可视化界面管理
4 IOC容器结合
5 自定义的定时调度框架
6 定时任务可视化界面管理
7 配置文件使用和IOC容器结合
8 WindowsService应用
1 quartZ引入&初始化&使用$核心对象Job、Trigger解析
1.1.背景:
/// 定时调度:大半夜跑一些数据统计,排行榜
/// 数据同步—id&name更新–lucene索引更新
/// 其实跟数据库作业很像,但是这个不只是数据库
1.2. 使用方法:
nuget添加 Quartz 引用
1.2.1. 新建Testjob 任务类
/// <summary>
/// 定制执行任务计划
/// </summary>
public class Testjob : IJob
{
public async Task Execute(IJobExecutionContext context)
{
await Task.Run(() =>
{
Console.WriteLine();
Console.WriteLine("*****************************");
Console.WriteLine($">>>>>>>> This is {Thread.CurrentThread.ManagedThreadId} {DateTime.Now} <<<<<<<<<");
Console.WriteLine("*****************************");
Console.WriteLine();
});
}
}
1.2.2. 新建DispatcherManager类,初始化任务
/// <summary>
/// 初始化任务
/// </summary>
public class DispatcherManager
{
/// <summary>
/// 初始化
/// 三大核心对象:
/// IScheduler:单元/实例,在这里去完成定时任务的配置
/// 只有单元启动,里面的作业才能正常运行
/// IJob:任务,定时执行动作就是Job
/// ITrigger:定时策略
/// 就可以完成基本的定时任务
/// </summary>
/// <returns></returns>
public async static Task Init()
{
Console.WriteLine("初始化scheduler......");
//IScheduler
StdSchedulerFactory factory = new StdSchedulerFactory();
IScheduler scheduler = await factory.GetScheduler();
await scheduler.Start();
//执行定制动作
IJobDetail jobDetail = JobBuilder.Create<Testjob>()
.WithIdentity("testjob", "group1")
.WithDescription("This is TestJob")
.Build();
//创建时间策略
ITrigger trigger = TriggerBuilder.Create()
.WithIdentity("testtrigger1", "group1")
.StartAt(new DateTimeOffset(DateTime.Now.AddSeconds(10)))
//.StartNow()//StartAt
.WithCronSchedule("2/5 * * * * ?")//每隔5秒钟执行一次
//"10,20,30,40,50,0 * * * * ?"
.WithDescription("This is testjob's Trigger")
.Build();
await scheduler.ScheduleJob(jobDetail, trigger); //开始执行任务
Console.WriteLine("scheduler作业添加完成......");
}
}
1.2.3. 调用该初始化方法
namespace Example04
{
class Program
{
static void Main(string[] args)
{
try
{
Console.WriteLine("QuartZ.Net定时调度");
DispatcherManager.Init().GetAwaiter().GetResult();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Console.Read();
}
}
}
随便贴一个项目结构 :
执行结果 :
2种参数传递的方法&& 框架特性说明?
修改DispatcherManager
public async static Task Init()
{
Console.WriteLine("初始化scheduler......");
//IScheduler
StdSchedulerFactory factory = new StdSchedulerFactory();
IScheduler scheduler = await factory.GetScheduler();
await scheduler.Start();
//执行定制动作
IJobDetail jobDetail = JobBuilder.Create<Testjob>()
.WithIdentity("testjob", "group1")
.WithDescription("This is TestJob")
.Build();
//参数传递的方式1
{
jobDetail.JobDataMap.Add("student1", "Milor");
jobDetail.JobDataMap.Add("student2", "心如迷醉");
jobDetail.JobDataMap.Add("student3", "宇洋");
jobDetail.JobDataMap.Add("Year", DateTime.Now.Year);
}
//创建时间策略
ITrigger trigger = TriggerBuilder.Create()
.WithIdentity("testtrigger1", "group1")
.StartAt(new DateTimeOffset(DateTime.Now.AddSeconds(10)))
//.StartNow()//StartAt
.WithCronSchedule("2/5 * * * * ?")//每隔5秒钟执行一次
.WithDescription("This is testjob's Trigger")
.Build();
//参数传递的方式2
{
trigger.JobDataMap.Add("student4", "Ray");
trigger.JobDataMap.Add("student5", "心欲无痕");
trigger.JobDataMap.Add("student6", "风在飘动");
trigger.JobDataMap.Add("Year", DateTime.Now.Year + 1);
}
await scheduler.ScheduleJob(jobDetail, trigger); //开始执行任务
Console.WriteLine("scheduler作业添加完成......");
}
修改Testjob
[PersistJobDataAfterExecution]//执行后保留数据,更新JobDataMap
[DisallowConcurrentExecution]//拒绝同一时间重复执行,同一任务串行
public class Testjob : IJob
{
public async Task Execute(IJobExecutionContext context)
{
await Task.Run(() =>
{
Console.WriteLine();
Console.WriteLine("*****************************");
//接受jobDetail的参数
{
JobDataMap dataMap = context.JobDetail.JobDataMap;
Console.WriteLine(dataMap.Get("student1"));
Console.WriteLine(dataMap.Get("student2"));
Console.WriteLine(dataMap.Get("student3"));
Console.WriteLine(dataMap.GetInt("Year"));
}
Console.WriteLine($">>>>>>>> This is {Thread.CurrentThread.ManagedThreadId} {DateTime.Now} <<<<<<<<<");
//可以换成去数据库查询,可以做啥啥啥,但是很多情况下,我们也是需要参数的
//接受trigger的参数
{
JobDataMap dataMap = context.Trigger.JobDataMap;
Console.WriteLine(dataMap.Get("student4"));
Console.WriteLine(dataMap.Get("student5"));
Console.WriteLine(dataMap.Get("student6"));
Console.WriteLine(dataMap.GetInt("Year"));
}
//接受全部参数
{
Console.WriteLine("&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&");
JobDataMap dataMap = context.MergedJobDataMap;
Console.WriteLine(dataMap.Get("student1"));
Console.WriteLine(dataMap.Get("student2"));
Console.WriteLine(dataMap.Get("student3"));
Console.WriteLine(dataMap.Get("student4"));
Console.WriteLine(dataMap.Get("student5"));
Console.WriteLine(dataMap.Get("student6"));
Console.WriteLine(dataMap.GetInt("Year"));
}
Console.WriteLine("*****************************");
Console.WriteLine();
});
}
}
结果 :
2. 三种Listener扩展监听
继承框架接口实现方法即可!
///<summary>
///1. 监听 IJobListener
/// </summary>
public class CustomJobListener : IJobListener{}
///<summary>
///2. 监听 Scheduler
/// </summary>
public class CustomSchedulerListener : ISchedulerListener{}
///<summary>
/// 监听 Trigger
/// </summary>
public class CustomTriggerListener : ITriggerListener{}
修改 DispatcherManager
StdSchedulerFactory factory = new StdSchedulerFactory();
IScheduler scheduler = await factory.GetScheduler();
scheduler.ListenerManager.AddSchedulerListener(new CustomSchedulerListener());
scheduler.ListenerManager.AddTriggerListener(new CustomTriggerListener());
scheduler.ListenerManager.AddJobListener(new CustomJobListener());
await scheduler.Start();
2.2. Quartz 框架的日志记录系统
新建ConsoleLogProvider 文件
/// <summary>
/// 自定义日志
/// </summary>
public class ConsoleLogProvider : ILogProvider
{
public Logger GetLogger(string name)
{
return new Logger((level, func, exception, parameters) =>
{
if (level >= LogLevel.Info && func != null)
{
Console.WriteLine($">>>>>>>>>>>>>>>>[{ DateTime.Now.ToLongTimeString()}] [{ level}] { func()} {string.Join(";", parameters.Select(p => p == null ? " " : p.ToString()))} 来自自定义日志{name}>>>>>>>>>>>>>>>");
}
return true;
});
}
public IDisposable OpenNestedContext(string message)
{
throw new NotImplementedException();
}
public IDisposable OpenMappedContext(string key, string value)
{
throw new NotImplementedException();
}
}
在 DispatcherManager 文件中添加日志请求
public async static Task Init()
{
#region 自定义框架日志
LogProvider.SetCurrentLogProvider(new ConsoleLogProvider());
#endregion
}