ABP+AdminLTE+Bootstrap Table權限管理系統一期 Github:https://github.com/Jimmey-Jiang/ABP-ASP.NET-Boilerplate-Project-CMShtml
Quartz.NET是一個開源的做業調度框架,是 OpenSymphony
的 Quartz API
的.NET移植,它用C#寫成,可用於winform
和asp.net
應用中。它提供了巨大的靈活性而不犧牲簡單性。你可以用它來爲執行一個做業而建立簡單的或複雜的調度。它有不少特徵,如:數據庫支持,集羣,插件,支持cron-like
表達式等等。很是適合在平時的工做中,定時輪詢數據庫同步,定時郵件通知,定時處理數據等.git
對Quartz.NET不熟悉的能夠先看下 官方學習文檔:www.quartz-scheduler.net/documentati… 使用實例介紹:www.quartz-scheduler.net/documentati… 官方的源代碼下載:sourceforge.net/projects/qu…github
特性 它一些很好的特性:數據庫
Windows
服務,WebSite
,winform
等。Quartz框架的一些基礎概念解釋:bash
名稱 | 描述 |
---|---|
Scheduler | 做業調度器。 |
IJob | 做業接口,繼承並實現Execute, 編寫執行的具體做業邏輯。 |
JobBuilder | 根據設置,生成一個詳細做業信息(JobDetail)。 |
TriggerBuilder | 根據規則,生產對應的Trig |
##實戰框架
基礎概念我就懶得講了,你也懶得聽了,直接上代碼吧。 首先配置一下Web.config
,其實這步無關緊要,能夠直接跳過,只是爲了配置一些常量,獲取固定的時間,可是不是必要的。asp.net
<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>
複製代碼
ISystemSchedulerService
以及SystemSchedulerService
,代碼上面都有詳細的註釋,我就不重複了。 接口:public interface ISystemSchedulerService: IApplicationService
{
void StartScheduler();
}
複製代碼
service: SystemSchedulerService
async
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的關鍵接口和類是:ide
IScheduler
- 與調度程序交互的主要API。 -IJob
- 您但願由調度程序執行的組件實現的接口。IJobDetail
- 用於定義做業的實例。ITrigger
- 定義執行給定Job的時間表的組件。JobBuilder
- 用於定義/構建obDetail
實例,它定義了Jobs
的實例。TriggerBuilder
- 用於定義/構建觸發器實例。一個調度程序的生命週期是由它爲界的創做,經過SchedulerFactory
和其有關方法的調用。一旦建立了IScheduler
接口,就可使用添加,刪除和列出做業和觸發器,並執行其餘與調度相關的操做(例如暫停觸發器)。可是,調度程序不會實際上對任何觸發器(執行做業)執行操做,直到使用Start()
方法啓動它。學習
構建做業定義的代碼塊使用使用流暢接口的JobBuilder
建立產品IJobDetail
。一樣,構建觸發器的代碼塊使用TriggerBuilder
流暢的接口和特定於觸發器類型的擴展方法。可能的時間延長方法是:
示例中的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有內建的持久化後臺job隊列和後臺worker
系統。若是對於後臺workers你有更高級的計劃安排需求,Quartz
會是一個更好的選擇。對於持久化後臺job隊列,Hangfire
也是一個好的選擇。 ABP中Quartz應用其實蠻簡單的。
[DependsOn(
typeof(AbpQuartzModule)
)]
public class ABPCMSWebModule : AbpModule
{
}
複製代碼
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 returned
ISimpleTrigger 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);
複製代碼
另一些經常使用的中止做業的指令常量
在構建SimpleTriggers時,能夠將簡單的時間表(經過SimpleSchedulerBuilder)指定爲中止做業指令:
trigger = TriggerBuilder.Create()
.WithIdentity("trigger7", "group1")
.WithSimpleSchedule(x => x
.WithIntervalInMinutes(5)
.RepeatForever()
.WithMisfireHandlingInstructionNextWithExistingCount())
.Build();
複製代碼
Cron-Expressions
用於配置CronTrigger
的實例。Cron-Expressions
是由七個子表達式組成的字符串,它們描述了計劃的各個細節。這些子表達式用空格分隔,表示:
示例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 here trigger = 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文檔具備對其行爲的描述)。說明包括:
全部觸發器都有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