ABP module-zero +AdminLTE+Bootstrap Table+jQuery权限管理系统第十七节--Quartz与ABP框架Abp.Quartz及扩展
来源:互联网 发布:淘宝客新手如何玩鹊桥 编辑:程序博客网 时间:2024/06/04 18:43
- Quartz简介
- 参考
- 实战
- Quartz API
- 工作和触发器
- AbpQuartz
- 扩展
- Cron时间表达式
- 其他
ABP+AdminLTE+Bootstrap Table权限管理系统一期
Github:https://github.com/Jimmey-Jiang/ABP-ASP.NET-Boilerplate-Project-CMS
Quartz简介
Quartz.NET是一个开源的作业调度框架,是 OpenSymphony
的 Quartz API
的.NET移植,它用C#写成,可用于winform
和asp.net
应用中。它提供了巨大的灵活性而不牺牲简单性。你能够用它来为执行一个作业而创建简单的或复杂的调度。它有很多特征,如:数据库支持,集群,插件,支持cron-like
表达式等等。非常适合在平时的工作中,定时轮询数据库同步,定时邮件通知,定时处理数据等.
参考
对Quartz.NET不熟悉的可以先看下
官方学习文档:http://www.quartz-scheduler.net/documentation/index.html
使用实例介绍:http://www.quartz-scheduler.net/documentation/quartz-2.x/quick-start.html
官方的源代码下载:http://sourceforge.net/projects/quartznet/files/quartznet/
特性
它一些很好的特性:
1. 支持集群,作业分组,作业远程管理。
2. 自定义精细的时间触发器,使用简单,作业和触发分离。
3. 数据库支持,可以寄宿Windows
服务,WebSite
,winform
等。
Quartz框架的一些基础概念解释:
实战
- Web.config配置
基础概念我就懒得讲了,你也懒得听了,直接上代码吧。
首先配置一下Web.config
,其实这步可有可无,可以直接跳过,只是为了配置一些常量,获取固定的时间,但是不是必要的。
<sectionGroup name="JobList"> <section name="Job" type="System.Configuration.NameValueSectionHandler, System, Version=1.0.5000.0,Culture=neutral, PublicKeyToken=b77a5c561934e089"/> </sectionGroup>
<JobList> <Job> <!--这里是一个任务节点--> <add key="Url" value="http://www.baidu.com" /> <!--需要访问的Url--> <add key="Hour" value="10" /> <!--开始时间小时--> <!--开始时间小时,注意:这里的小时为0-23,如果是1点的话就是1,而不是01--> <add key="Minute" value="30" /> <!--开始时间分钟--> <!--开始时间分钟,注意:同上0-59--> </Job> </JobList>
- 创建service
创建ISystemSchedulerService
以及SystemSchedulerService
,代码上面都有详细的注释,我就不重复了。
接口:
public interface ISystemSchedulerService: IApplicationService { void StartScheduler(); }
service: SystemSchedulerService
public class SystemSchedulerService : ISystemSchedulerService { private IScheduler _scheduler; public ILogger _Logger { get; set; } public SystemSchedulerService() { _Logger = NullLogger.Instance; } public void StopScheduler() { _scheduler.Shutdown(); } public void StartScheduler() { try { //这里读取配置文件中的任务开始时间 int hour = int.Parse(((NameValueCollection)ConfigurationManager.GetSection("JobList/Job"))["Hour"]); int minute = int.Parse(((NameValueCollection)ConfigurationManager.GetSection("JobList/Job"))["Minute"]); ISchedulerFactory schedulerFactory = new StdSchedulerFactory();//内存调度 _scheduler = schedulerFactory.GetScheduler(); //创建一个Job来执行特定的任务 IJobDetail myLogJob = new JobDetailImpl("myLogJob", typeof(MyLogJob)); //创建并定义触发器的规则(每天执行一次时间为:时:分) ITrigger trigger = TriggerBuilder.Create() .WithDailyTimeIntervalSchedule( a => a.WithIntervalInHours(24).OnEveryDay().StartingDailyAt(TimeOfDay.HourAndMinuteOfDay(hour, minute))).Build(); _scheduler.Clear(); //将创建好的任务和触发规则加入到Quartz中 _scheduler.ScheduleJob(myLogJob, trigger); //开始 _scheduler.Start(); } catch (Exception ex) { _Logger.Info(ex.Message); } } }
Quartz API
Quartz API的关键接口和类是:
- IScheduler
- 与调度程序交互的主要API。
-IJob
- 您希望由调度程序执行的组件实现的接口。
- IJobDetail
- 用于定义作业的实例。
- ITrigger
- 定义执行给定Job的时间表的组件。
- JobBuilder
- 用于定义/构建obDetail
实例,它定义了Jobs
的实例。
- TriggerBuilder
- 用于定义/构建触发器实例。
一个调度程序的生命周期是由它为界的创作,通过SchedulerFactory
和其有关方法的调用。一旦创建了IScheduler
接口,就可以使用添加,删除和列出作业和触发器,并执行其他与调度相关的操作(例如暂停触发器)。但是,调度程序不会实际上对任何触发器(执行作业)执行操作,直到使用Start()
方法启动它。
构建作业定义的代码块使用使用流畅接口的JobBuilder
创建产品IJobDetail
。同样,构建触发器的代码块使用TriggerBuilder
流畅的接口和特定于触发器类型的扩展方法。可能的时间延长方法是:
- WithCalendarIntervalSchedule
- WithCronSchedule
- WithDailyTimeIntervalSchedule
- WithSimpleSchedule
示例中的ITrigger
其实可以不读取配置信息的。这就是我说的不用配置Web.config
也可以。效果如下,每隔10秒执行一次。
ITrigger trigger = TriggerBuilder.Create() .WithDailyTimeIntervalSchedule( a => a.WithIntervalInSeconds(10)).Build();
工作和触发器
代码:
public class MyLogJob : JobBase, ITransientDependency { public ILogger _Logger { get; set; } public MyLogJob() { _Logger = NullLogger.Instance; } public override void Execute(IJobExecutionContext context) { try { _Logger.Info("QuartzJob 任务开始运行"); for (int i = 0; i < 10; i++) { _Logger.InfoFormat("QuartzJob 正在运行{0}", i); } _Logger.Info("QuartzJob任务运行结束"); } catch (Exception ex) { _Logger.Error("运行异常:"+ex.Message, ex); } } }
当作业的触发器触发,Execute(..)
方法由调度程序的工作线程之一调用。传递给此方法的JobExecutionContext
对象为作业实例提供有关其“运行时”环境的信息 ( 调度程序执行的逻辑),触发执行的触发器的逻辑。 JobDetail
对象是在Job
添加到调度器时由Quartz.NET
客户端创建的。它包含Job的各种属性设置,以及一个JobDataMap
,它可以用来存储作业类的给定实例的状态信息
触发器对象用于触发作业的执行(或“触发”)。当你想安排一个工作,你实例化一个触发器并“调整”它的属性来提供你想要的调度。触发器也可能有一个与它们相关的JobDataMap
- 这对于传递参数到一个特定于触发器的触发的Job
是很有用的。Quartz
提供了一些不同的触发器类型,但最常用的类型是SimpleTrigger
(接口ISimpleTrigger
)和CronTrigger
(接口ICronTrigger
)。
如果您需要“一次性”执行(在某个特定时间只执行一项作业),或者您需要在给定时间开始工作,并且重复执行N次,SimpleTrigger
会很方便的T之间执行。如果您希望基于类似日历的时间表(例如“每个星期五,中午”或“每个月的第10天的10:15”)触发,则CronTrigger
非常有用。
public class UserInfoController : ABPCMSControllerBase { private readonly ISystemSchedulerService _iSystemSchedulerService; public UserInfoController(ISystemSchedulerService iSystemSchedulerService) { _iSystemSchedulerService = iSystemSchedulerService; } [HttpGet] [DontWrapResult] public async Task<ActionResult> GetUserInfo() { _iSystemSchedulerService.StartScheduler(); }}
然后我们在前台控制器里面调用ISystemSchedulerService
的StartScheduler()
方法。然后运行项目。
然后我们打开日志Web\App_Data\Logs\Logs.txt
,看下效果:
每隔十秒钟执行一次。
Abp.Quartz
ABP有內建的持久化后台job队列和后台worker
系统。如果对于后台workers你有更高级的计划安排需求,Quartz
会是一个更好的选择。对于持久化后台job队列,Hangfire
也是一个好的选择。
ABP中Quartz应用其实蛮简单的。
1. 首先Abp.Quartz nuget包
2. 然后加上引入到项目中。
[DependsOn( typeof(AbpQuartzModule) )] public class ABPCMSWebModule : AbpModule { }
- 创建Jobs
这里我们就用上面例子中的job,当然创建一个新job,你可以实现Quartz
的IJob
接口,或者继承JobBase
类(定义在Abp.Quartz包),这个类包含一些帮助属性和方法(例如日志和本地化)。
public class MyLogJob : JobBase, ITransientDependency{ public override void Execute(IJobExecutionContext context) { Logger.Info("Executed MyLogJob :)"); }}
4.创建调度作业 IQuartzScheduleJobManager
接口被用来创建调度作业。你可以在类中注入该接口(或者你可以在你的模块的PostInitialize
方法中解析和使用它)来调度作业。这里我们把之前创建的MyLogJob引用进来。
效果如下:
public async Task<ActionResult> ScheduleJob() { await _jobManager.ScheduleAsync<MyLogJob>( job => { job.WithIdentity("MyLogJobIdentity", "MyGroup") .WithDescription("A job to simply write logs."); }, trigger => { trigger.StartNow() .WithSimpleSchedule(schedule => { schedule.RepeatForever() .WithIntervalInSeconds(5) .Build(); }); }); _jobManager.Start(); return Content("OK, scheduled!"); }
效果一样。
经过上面四步,就完成Abp.Quartz运用,是挺简单的。
扩展
####SimpleTrigger
说一下SimpleTrigger
,WithCronSchedule()
这里有三种方式,一种就是上面说到的Web.config
配置,一种是WithCronSchedule
设置时间参数。还有一种是WithCronSchedule("")
拥有强大的Cron
时间表达式。
SimpleTrigge
r应满足你的日程安排需求,如果你需要在某个特定时刻及时执行一次作业,或者在特定时间执行一次,然后在特定时间间隔重复执行。如果你想让触发器在2018年1月13日上午11点23分54秒执行,然后再执行5次,每10秒执行一次。
通过这个描述,你可能不会觉得奇怪的是,SimpleTrigger
的属性包括:开始时间和结束时间,重复计数和重复间隔。所有这些属性都与您所期望的完全相同,只有一些与结束时间属性相关的特殊注释。
SimpleTrigger
实例是使用TriggerBuilder
(用于触发器的主属性)和WithSimpleSchedule
扩展方法(用于SimpleTrigger
特有的属性)构建的。
在特定的时刻建立一个触发器,不要重复:
// trigger builder creates simple trigger by default, actually an ITrigger is returnedISimpleTrigger trigger = (ISimpleTrigger) TriggerBuilder.Create() .WithIdentity("trigger1", "group1") .StartAt(myStartTime) // some Date .ForJob("job1", "group1") // identify job with name, group strings .Build();
建立一个特定时刻的触发器,然后每十秒钟重复十次:
trigger = TriggerBuilder.Create() .WithIdentity("trigger3", "group1") .StartAt(myTimeToStartFiring) // if a start time is not given (if this line were omitted), "now" is implied .WithSimpleSchedule(x => x .WithIntervalInSeconds(10) .WithRepeatCount(10)) // note that 10 repeats will give a total of 11 firings .ForJob(myJob) // identify job with handle to its JobDetail itself .Build();
建立一个触发器,将在未来五分钟内触发一次:
trigger = (ISimpleTrigger) TriggerBuilder.Create() .WithIdentity("trigger5", "group1") .StartAt(DateBuilder.FutureDate(5, IntervalUnit.Minute)) // use DateBuilder to create a date in the future .ForJob(myJobKey) // identify job with its JobKey .Build();
建立一个触发器,现在会触发,然后每隔五分钟重复一次,直到22:00:
trigger = TriggerBuilder.Create() .WithIdentity("trigger7", "group1") .WithSimpleSchedule(x => x .WithIntervalInMinutes(5) .RepeatForever()) .EndAt(DateBuilder.DateOf(22, 0, 0)) .Build();
建立一个触发器,将在下一个小时的顶部执行,然后每2小时重复一次:
trigger = TriggerBuilder.Create() .WithIdentity("trigger8") // because group is not specified, "trigger8" will be in the default group .StartAt(DateBuilder.EvenHourDate(null)) // get the next even-hour (minutes and seconds zero ("00:00")) .WithSimpleSchedule(x => x .WithIntervalInHours(2) .RepeatForever()) // note that in this example, 'forJob(..)' is not called // - which is valid if the trigger is passed to the scheduler along with the job .Build();await scheduler.scheduleJob(trigger, job);
另外一些常用的停止作业的指令常量
- MisfireInstruction.IgnoreMisfirePolicy
- MisfirePolicy.SimpleTrigger.FireNow
- MisfirePolicy.SimpleTrigger.RescheduleNowWithExistingRepeatCount
- MisfirePolicy.SimpleTrigger.RescheduleNowWithRemainingRepeatCount
- MisfirePolicy.SimpleTrigger.RescheduleNextWithRemainingCount
- MisfirePolicy.SimpleTrigger.RescheduleNextWithExistingCount
在构建SimpleTriggers时,可以将简单的时间表(通过SimpleSchedulerBuilder)指定为停止作业指令:
trigger = TriggerBuilder.Create() .WithIdentity("trigger7", "group1") .WithSimpleSchedule(x => x .WithIntervalInMinutes(5) .RepeatForever() .WithMisfireHandlingInstructionNextWithExistingCount()) .Build();
Cron时间表达式。
Cron-Expressions
用于配置CronTrigger
的实例。Cron-Expressions
是由七个子表达式组成的字符串,它们描述了计划的各个细节。这些子表达式用空格分隔,表示:
- Seconds
- Minutes
- Hours
- Day-of-Month
- Month
- Day-of-Week
- Year (optional field)
示例Cron表达式
下面是一些表达式及其含义的例子 - 你可以在CronTrigger
的API文档中找到更多的例子
CronTrigger示例1 - 创建一个触发器的表达式,每5分钟触发一次 "0 0/5 * * * ?"
CronTrigger示例2 - 一个表达式,用于创建在分钟后10秒(即上午10:00:10,上午10:05:10等)每5分钟触发一次的触发器。 "10 0/5 * * * ?"
CronTrigger示例3 - 一个表达式,用于在每个星期三和星期五的10:30,11:30,12:30和13:30创建一个触发器。 "0 30 10-13 ? * WED,FRI"
CronTrigger示例4 - 一个表达式,用于创建一个触发器,在每个月的第5天和第20天的上午8点到上午10点之间每隔半小时触发一次。请注意,触发器不会在上午10点,仅在8点,8点,9点和9点30分 "0 0/30 8-9 5,20 * ?"
请注意,一些调度要求过于复杂,无法用一个触发器来表示 - 例如“上午9点至上午10点之间每5分钟一次,下午1点至10点之间每20分钟一次”。在这种情况下解决方案是简单地创建两个触发器,并注册他们两个运行相同的工作。
CronTrigger
实例使用TriggerBuilder
(用于触发器的主属性)和WithCronSchedule
扩展方法(用于CronTrigger
特定的属性)构建。
您也可以使用CronScheduleBuilder
的静态方法来创建计划。
建立一个触发器,每隔上午8点到下午5点,每隔一分钟一次:
trigger = TriggerBuilder.Create() .WithIdentity("trigger3", "group1") .WithCronSchedule("0 0/2 8-17 * * ?") .ForJob("myJob", "group1") .Build();
建立一个触发器,每天在上午10:42开始:
// we use CronScheduleBuilder's static helper methods heretrigger = TriggerBuilder.Create() .WithIdentity("trigger3", "group1") .WithSchedule(CronScheduleBuilder.DailyAtHourAndMinute(10, 42)) .ForJob(myJobKey) .Build();
要么 -
trigger = TriggerBuilder.Create() .WithIdentity("trigger3", "group1") .WithCronSchedule("0 42 10 * * ?") .ForJob("myJob", "group1") .Build();
建立一个触发器,将在星期三上午10:42,在系统默认的时区以外的其他时间触发:
trigger = TriggerBuilder.Create() .WithIdentity("trigger3", "group1") .WithSchedule(CronScheduleBuilder .WeeklyOnDayAndHourAndMinute(DayOfWeek.Wednesday, 10, 42) .InTimeZone(TimeZoneInfo.FindSystemTimeZoneById("Central America Standard Time"))) .ForJob(myJobKey) .Build();
要么 -
trigger = TriggerBuilder.Create() .WithIdentity("trigger3", "group1") .WithCronSchedule("0 42 10 ? * WED", x => x .InTimeZone(TimeZoneInfo.FindSystemTimeZoneById("Central America Standard Time"))) .ForJob(myJobKey) .Build();
以下指令可用于通知Quartz
在CronTrigger
发生停止作业时应该执行的操作。(本教程的“更多关于触发器”部分介绍了停止作业情况)。这些指令被定义为常量(并且API文档具有对其行为的描述)。说明包括:
- MisfireInstruction.IgnoreMisfirePolicy
- MisfireInstruction.CronTrigger.DoNothing
- MisfireInstruction.CronTrigger.FireOnceNow
所有触发器都有MisfireInstrution.SmartPolicy
指令可供使用,并且此指令也是所有触发器类型的默认值。CronTrigger
将“智能策略”指令解释为MisfireInstruction.CronTrigger.FireOnceNow。CronTrigger.UpdateAfterMisfire()
方法的API文档解释了此行为的确切详细信息。
在构建CronTriggers时,您可以将缺火指令指定为cron时间表的一部分(通过WithCronSchedule扩展方法):
trigger = TriggerBuilder.Create() .WithIdentity("trigger3", "group1") .WithCronSchedule("0 0/2 8-17 * * ?", x => x .WithMisfireHandlingInstructionFireAndProceed()) .ForJob("myJob", "group1") .Build();
其他
我们可以看一下,源码中对IQuartzScheduleJobManager
的ScheduleAsync
方法的封装,其实就是Scheduler.ScheduleJob
处理了一下。
如果要使用模块的PostInitialize
方法中解析和使用它来调度作业,也是可以的。
using System.Reflection;using Abp.Dependency;using Abp.Modules;using Abp.Quartz.Configuration;using Abp.Threading.BackgroundWorkers;using Quartz;namespace Abp.Quartz{ [DependsOn(typeof (AbpKernelModule))] public class AbpQuartzModule : AbpModule { public override void PreInitialize() { IocManager.Register<IAbpQuartzConfiguration, AbpQuartzConfiguration>(); Configuration.Modules.AbpQuartz().Scheduler.JobFactory = new AbpQuartzJobFactory(IocManager); } public override void Initialize() { IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly()); } public override void PostInitialize() { IocManager.RegisterIfNot<IJobListener, AbpQuartzJobListener>(); Configuration.Modules.AbpQuartz().Scheduler.ListenerManager.AddJobListener(IocManager.Resolve<IJobListener>()); if (Configuration.BackgroundJobs.IsJobExecutionEnabled) { IocManager.Resolve<IBackgroundWorkerManager>().Add(IocManager.Resolve<IQuartzScheduleJobManager>()); } } }}
JobBase
封装的一些方法,继承自IJob
ABP+AdminLTE+Bootstrap Table权限管理系统一期
Github:https://github.com/Jimmey-Jiang/ABP-ASP.NET-Boilerplate-Project-CMS
- ABP module-zero +AdminLTE+Bootstrap Table+jQuery权限管理系统第十七节--Quartz与ABP框架Abp.Quartz及扩展
- ABP module-zero +AdminLTE+Bootstrap Table+jQuery权限管理系统第十六节--SignalR与ABP框架Abp.Web.SignalR及扩展
- ABP module-zero +AdminLTE+Bootstrap Table+jQuery权限管理系统第十五节--缓存小结与ABP框架项目中 Redis Cache的实现
- ABP+AdminLTE+Bootstrap Table权限管理系统第六节--abp控制器扩展及json封装
- ABP module-zero +AdminLTE+Bootstrap Table+jQuery权限管理系统第十二节--小结,Bootstrap Table之角色管理
- ABP module-zero +AdminLTE+Bootstrap Table+jQuery权限管理系统第十二节--小结,Bootstrap Table之角色管理
- ABP module-zero +AdminLTE+Bootstrap Table+jQuery权限管理系统第十三节--RBAC模式及ABP权限管理(附赠福利)
- ABP+AdminLTE+Bootstrap Table权限管理系统一期
- ABP+AdminLTE+Bootstrap Table权限管理系统第二节--在ABP的基础做数据库脚本处理
- ABP+AdminLTE+Bootstrap Table权限管理系统第十一节--bootstrap table之用户管理列表
- ABP+AdminLTE+Bootstrap Table权限管理系统第一节--使用ASP.NET Boilerplate模板创建解决方案
- 后台工作者HangFire与ABP框架Abp.Hangfire及扩展
- ABP官方文档(四十六)【集成Quartz】
- abp及实战框架概述
- abp及实战框架概述
- abp及实战框架概述
- abp及实战框架概述
- abp及实战框架概述
- Hive的DDL和DML操作
- Oracle Operation
- JS——canvas(1)
- Python wmi Cookbook 中文翻译
- 1.3java第一个程序HellWorld
- ABP module-zero +AdminLTE+Bootstrap Table+jQuery权限管理系统第十七节--Quartz与ABP框架Abp.Quartz及扩展
- PostgreSQL配置文件--复制
- 程序编译优化等级说明
- JAVA实例学习一为什么要用策略模式
- Solr7.1.0 安装部署(centos7)
- 二叉树的链式存储
- java的几种对象(po,dto,dao等)
- leveldb status学习
- MFC下的CRC16计算器