定时调度之Quartz
工作中我们经常碰到定时或者固定时间点去做一些事情,然后每天到时间点就会去做这样的事情,如果理解这样的场景,我们就要引入今天我们的主角Quartz,其实这个跟数据库的作业类似,但是不仅仅局限于数据库。
一: quartZ引入&三大核心对象简介
1:在项目中打开Nuget管理,然后搜索QuartZ,现在最新的版本是3.0.7,需要在Framework4.5.2上面使用。
2:quartZ的三大核心对象
A:IScheduler:单元/实例,在这里去完成定时任务的配置,只有单元启动,里面的作业才能正常运行
B:IJob:任务,定时执行动作就是Job
C:ITrigger:定时策略(设置执行的频率或者执行方式)
二:三大核心对象的初始化以及使用如下:
#region scheduler
Console.WriteLine("初始化scheduler......");
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();
#endregion //IJob ITrigger
{
//创建作业
IJobDetail jobDetail = JobBuilder.Create<TestJob>()
.WithIdentity("testjob", "group1")
.WithDescription("This is TestJob")
.Build(); //IJobDetail jobDetail = JobBuilder.Create<TestStatefulJob>()
// .WithIdentity("testjob", "group1")
// .WithDescription("This is TestJob")
// .Build(); 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("trigger1", "group1")
// .StartNow()
// .WithSimpleSchedule(x => x
// .WithIntervalInSeconds(10)
// .WithRepeatCount(10)
// .RepeatForever())
// .WithDescription("This is testjob's Trigger")
// .Build(); //创建时间策略
ITrigger trigger = TriggerBuilder.Create()
.WithIdentity("testtrigger1", "group1")
.StartAt(new DateTimeOffset(DateTime.Now.AddSeconds()))
//.StartNow()//StartAt
.WithCronSchedule("5/10 * * * * ?")//每隔一分钟
//"10,20,30,40,50,0 * * * * ?"
.WithDescription("This is testjob's Trigger")
.Build(); trigger.JobDataMap.Add("student4", "Ray");
trigger.JobDataMap.Add("student5", "心欲无痕");
trigger.JobDataMap.Add("student6", "风在飘动");
trigger.JobDataMap.Add("Year", DateTime.Now.Year + ); await scheduler.ScheduleJob(jobDetail, trigger);
Console.WriteLine("scheduler作业添加完成......");
}
public class TestJob : IJob
{
public TestJob()
{
Console.WriteLine("This is TestJob的构造。。。");
} public async Task Execute(IJobExecutionContext context)
{
await Task.Run(() =>
{
Console.WriteLine();
Console.WriteLine("*****************************");
{
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}");
//可以换成去数据库查询,可以做啥啥啥
//但是很多情况下,我们也是需要参数的
{
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();
});
}
}
三:任务或者定时策略传参
1:通过定时任务进行传参如下:
然后接收通过:
2:定时策略进行传参:
接收如下:
注意以上两种传参也可以统一通过下面的方式来接收参数,但是如果key相同,则会进行覆盖掉
四:常用的Trigggr
1:SimpleTrigger:从什么时间开始,间隔多久执行重复操作,可以限制最大次数,如下:
ITrigger trigger = TriggerBuilder.Create()
.WithIdentity("trigger1", "group1")
.StartNow()
.WithSimpleSchedule(x => x
.WithIntervalInSeconds()
.WithRepeatCount()
.RepeatForever()) //从什么时间开始,间隔多久执行重复操作,可以限制最大次数
.WithDescription("This is testjob's Trigger")
.Build();
2:Cron:表达式的方式,可以灵活订制时间规则(具体详情咨询)
ITrigger trigger = TriggerBuilder.Create()
.WithIdentity("testtrigger1", "group1")
.StartAt(new DateTimeOffset(DateTime.Now.AddSeconds()))
//.StartNow()//StartAt
.WithCronSchedule("5/10 * * * * ?")//每隔一分钟 //"10,20,30,40,50,0 * * * * ?"
.WithDescription("This is testjob's Trigger")
.Build();
五:Listener框架的各个环节--事件能做的监听
如果我们自己写定时任务的时候,因为是定时或者周期去做一些事情,所以有时候有问题或者出现了什么故障,我们只能通过我们自己写一下具体的日志,但是Quartz里面的Listener里面内置封装了一些监听接口,分别为:ISchedulerListener,ITriggerListener,IJobListener,里面有一些方法可以让我们去做一下其它的事情,我们下面分别实现了三个接口,代码如下:
1:jobListerer
public class CustomJobListener : IJobListener
{
public string Name => "CustomJobListener"; public async Task JobExecutionVetoed(IJobExecutionContext context, CancellationToken cancellationToken = default(CancellationToken))
{
await Task.Run(()=> {
Console.WriteLine($"CustomJobListener JobExecutionVetoed {context.JobDetail.Description}");
});
} public async Task JobToBeExecuted(IJobExecutionContext context, CancellationToken cancellationToken = default(CancellationToken))
{
await Task.Run(() => {
Console.WriteLine($"CustomJobListener JobToBeExecuted {context.JobDetail.Description}");
});
} public async Task JobWasExecuted(IJobExecutionContext context, JobExecutionException jobException, CancellationToken cancellationToken = default(CancellationToken))
{
await Task.Run(() => {
Console.WriteLine($"CustomJobListener JobWasExecuted {context.JobDetail.Description}");
});
}
}
2:ITriggerListener
public class CustomTriggerListener : ITriggerListener
{
public string Name => "CustomTriggerListener"; public async Task TriggerComplete(ITrigger trigger, IJobExecutionContext context, SchedulerInstruction triggerInstructionCode, CancellationToken cancellationToken = default(CancellationToken))
{
await Task.Run(() =>
{
Console.WriteLine($"CustomTriggerListener TriggerComplete {trigger.Description}");
});
} public async Task TriggerFired(ITrigger trigger, IJobExecutionContext context, CancellationToken cancellationToken = default(CancellationToken))
{
await Task.Run(() =>
{
Console.WriteLine($"CustomTriggerListener TriggerFired {trigger.Description}");
});
} public async Task TriggerMisfired(ITrigger trigger, CancellationToken cancellationToken = default(CancellationToken))
{
await Task.Run(() =>
{
Console.WriteLine($"CustomTriggerListener TriggerMisfired {trigger.Description}");
});
} /// <summary>
/// 要不要放弃job
/// </summary>
/// <param name="trigger"></param>
/// <param name="context"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<bool> VetoJobExecution(ITrigger trigger, IJobExecutionContext context, CancellationToken cancellationToken = default(CancellationToken))
{
await Task.Run(() =>
{
Console.WriteLine($"CustomTriggerListener TriggerMisfired {trigger.Description}");
});
return false;//false才能继续执行
}
}
3:ISchedulerListener
public class CustomSchedulerListener : ISchedulerListener
{
public async Task JobAdded(IJobDetail jobDetail, CancellationToken cancellationToken = default(CancellationToken))
{
await Task.Run(() =>
{
Console.WriteLine($"This is {nameof(CustomSchedulerListener)} JobAdded {jobDetail.Description}");
});
} public Task JobDeleted(JobKey jobKey, CancellationToken cancellationToken = default(CancellationToken))
{
throw new NotImplementedException();
} public Task JobInterrupted(JobKey jobKey, CancellationToken cancellationToken = default(CancellationToken))
{
throw new NotImplementedException();
} public Task JobPaused(JobKey jobKey, CancellationToken cancellationToken = default(CancellationToken))
{
throw new NotImplementedException();
} public Task JobResumed(JobKey jobKey, CancellationToken cancellationToken = default(CancellationToken))
{
throw new NotImplementedException();
} public Task JobScheduled(ITrigger trigger, CancellationToken cancellationToken = default(CancellationToken))
{
throw new NotImplementedException();
} public Task JobsPaused(string jobGroup, CancellationToken cancellationToken = default(CancellationToken))
{
throw new NotImplementedException();
} public Task JobsResumed(string jobGroup, CancellationToken cancellationToken = default(CancellationToken))
{
throw new NotImplementedException();
} public Task JobUnscheduled(TriggerKey triggerKey, CancellationToken cancellationToken = default(CancellationToken))
{
throw new NotImplementedException();
} public Task SchedulerError(string msg, SchedulerException cause, CancellationToken cancellationToken = default(CancellationToken))
{
throw new NotImplementedException();
} public Task SchedulerInStandbyMode(CancellationToken cancellationToken = default(CancellationToken))
{
throw new NotImplementedException();
} public Task SchedulerShutdown(CancellationToken cancellationToken = default(CancellationToken))
{
throw new NotImplementedException();
} public Task SchedulerShuttingdown(CancellationToken cancellationToken = default(CancellationToken))
{
throw new NotImplementedException();
} public async Task SchedulerStarted(CancellationToken cancellationToken = default(CancellationToken))
{
await Task.Run(() =>
{
Console.WriteLine($"This is {nameof(CustomSchedulerListener)} SchedulerStarted ");
});
} public async Task SchedulerStarting(CancellationToken cancellationToken = default(CancellationToken))
{
await Task.Run(() =>
{
Console.WriteLine($"This is {nameof(CustomSchedulerListener)} SchedulerStarting ");
});
} public Task SchedulingDataCleared(CancellationToken cancellationToken = default(CancellationToken))
{
throw new NotImplementedException();
} public Task TriggerFinalized(ITrigger trigger, CancellationToken cancellationToken = default(CancellationToken))
{
throw new NotImplementedException();
} public Task TriggerPaused(TriggerKey triggerKey, CancellationToken cancellationToken = default(CancellationToken))
{
throw new NotImplementedException();
} public Task TriggerResumed(TriggerKey triggerKey, CancellationToken cancellationToken = default(CancellationToken))
{
throw new NotImplementedException();
} public Task TriggersPaused(string triggerGroup, CancellationToken cancellationToken = default(CancellationToken))
{
throw new NotImplementedException();
} public Task TriggersResumed(string triggerGroup, CancellationToken cancellationToken = default(CancellationToken))
{
throw new NotImplementedException();
}
}
然后通过下面代码来融合到实例中:
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();
这样就完美的结合在一起了,然后实例,任务,策略每次发生的动作,都会以日志的形式输出来,当然可以记录任何形式的日志。
六:LogProvider可以展示框架运行的一些信息
Quartz.Logging内置了一些记录日志的类,然后需要记录日志的话,可以直接拿来使用,不用自己再去引用配置等记录日志了,下面是自己试着写了一个:
public class CustomConsoleLogProvider : 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中的init方法中
这样即实现了log的日志
如果想要测试,可以通过:
static void Main(string[] args)
{
try
{
Console.WriteLine("QuartZ.Net定时调度");
DispatcherManager.Init().GetAwaiter().GetResult();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Console.Read();
}
最新文章
- WINDOWS下绑定ARP绑定网关
- ubuntu14.04编译安装Git2.7
- BZOJ 2727 双十字(树状数组)
- 从零开始学android开发-通过WebService进行网络编程,使用工具类轻松实现
- 50道经典的JAVA编程题 (6-10)
- ajax创建对象
- Path Sum 解答
- (转)ZOJ 3687 The Review Plan I(禁为排列)
- 值得赞扬的尝试与进步——CSDN开源夏令营第一印象
- RocketMQ初步应用架构理论
- asp 自我定时删除
- sqlsever存储过程配合代理作业自动定时建表
- Centos中MySQL数据的备份和恢复
- Icehouse 创建Instance代码分析
- 20165235 祁瑛 2018-4 《Java程序设计》第七周学习总结
- Object 标签遮挡 Div 显示
- nghttp2 和nginx的实践
- vs2015打开慢的解决方法
- 20155318 2016-2017-2 《Java程序设计》第五周学习总结
- Java8中list转map
热门文章
- Ultimate Chicken Horse GameProject第二次迭代成果文档
- openjdk11 stretch基础镜像无法找到对应openjdk dbg 包的问题
- 【day03】Xhtml
- java 随笔
- CF1187D Subarray Sorting(神奇思路,线段树)
- 推荐一款移动端小视频App玲珑视频
- python面试题第一份
- Qt Quick 多媒体 - 播放音乐和视频
- Android studio(AS) svg图片使用
- 024 如何让html引用公共的头部和尾部(多个html文件公用一个header.html和footer.html)