之前一直想搞個後臺任務管理系統,零零散散的搞到現在,也算完成了。 這裡發佈出來,請園裡的dalao批評指導! 廢話不多說,進入正題。 github地址:https://github.com/YANGKANG01/QuartzNetJob 一、項目結構 項目結構如下: ORM使用的是SqlSugar版 ...
之前一直想搞個後臺任務管理系統,零零散散的搞到現在,也算完成了。
這裡發佈出來,請園裡的dalao批評指導!
廢話不多說,進入正題。
github地址:https://github.com/YANGKANG01/QuartzNetJob
一、項目結構
項目結構如下:
ORM使用的是SqlSugar
版本是4.6.4.3
QuartzNet
使用的版本是3.0.2
Asp.Net Core
版本為2.0
類庫使用的是 .Net Standard
類庫 QuartzNet2.Core
是.Net Framework
的類庫,使用的QuartzNet
版本是2.6,這裡把它也放入了當前項目,方便不是Core
的項目使用。
後臺運行效果如下:
任務執行如下:
Linux執行如下:
二、項目源碼
資料庫表可使用SqlSugar
生成,如下圖:
項目中主要的類SchedulerCenter
任務調度管理中心,源碼如下:
using QuartzNet.Entity; using Quartz; using Quartz.Impl; using System; using System.Collections.Specialized; using System.Threading.Tasks; using Five.QuartzNetJob.Utils.Tool; using System.Reflection; using System.Collections.Generic; namespace QuartzNet3.Core { /// <summary> /// 任務調度中心 /// </summary> public class SchedulerCenter { /// <summary> /// 任務調度對象 /// </summary> public static readonly SchedulerCenter Instance; static SchedulerCenter() { Instance = new SchedulerCenter(); } private Task<IScheduler> _scheduler; /// <summary> /// 返回任務計劃(調度器) /// </summary> /// <returns></returns> private Task<IScheduler> Scheduler { get { if (this._scheduler != null) { return this._scheduler; } // 從Factory中獲取Scheduler實例 NameValueCollection props = new NameValueCollection { { "quartz.serializer.type", "binary" }, //以下配置需要資料庫表配合使用,表結構sql地址:https://github.com/quartznet/quartznet/tree/master/database/tables //{ "quartz.jobStore.type","Quartz.Impl.AdoJobStore.JobStoreTX, Quartz"}, //{ "quartz.jobStore.driverDelegateType","Quartz.Impl.AdoJobStore.StdAdoDelegate, Quartz"}, //{ "quartz.jobStore.tablePrefix","QRTZ_"}, //{ "quartz.jobStore.dataSource","myDS"}, //{ "quartz.dataSource.myDS.connectionString",AppSettingHelper.MysqlConnection},//連接字元串 //{ "quartz.dataSource.myDS.provider","MySql"}, //{ "quartz.jobStore.useProperties","true"} }; StdSchedulerFactory factory = new StdSchedulerFactory(props); return this._scheduler = factory.GetScheduler(); } } /// <summary> /// 運行指定的計劃(泛型指定IJob實現類) /// </summary> /// <param name="jobGroup">任務分組</param> /// <param name="jobName">任務名稱</param> /// <returns></returns> public async Task<BaseQuartzNetResult> RunScheduleJob<T, V>(string jobGroup, string jobName) where T : ScheduleManage, new() where V : IJob { BaseQuartzNetResult result; //開啟調度器 await this.Scheduler.Result.Start(); //創建指定泛型類型參數指定的類型實例 T t = Activator.CreateInstance<T>(); //獲取任務實例 ScheduleEntity scheduleModel = t.GetScheduleModel(jobGroup, jobName); //添加任務 var addResult = AddScheduleJob<V>(scheduleModel).Result; if (addResult.Code == 1000) { scheduleModel.Status = EnumType.JobStatus.已啟用; t.UpdateScheduleStatus(scheduleModel); //用給定的密鑰恢復(取消暫停)IJobDetail await this.Scheduler.Result.ResumeJob(new JobKey(jobName, jobGroup)); result = new BaseQuartzNetResult { Code = 1000, Msg = "啟動成功" }; } else { result = new BaseQuartzNetResult { Code = -1 }; } return result; } /// <summary> /// 運行指定的計劃(映射處理IJob實現類) /// </summary> /// <param name="jobGroup">任務分組</param> /// <param name="jobName">任務名稱</param> /// <returns></returns> public async Task<BaseQuartzNetResult> RunScheduleJob<T>(string jobGroup, string jobName) where T : ScheduleManage { BaseQuartzNetResult result; //開啟調度器 await this.Scheduler.Result.Start(); //創建指定泛型類型參數指定的類型實例 T t = Activator.CreateInstance<T>(); //獲取任務實例 ScheduleEntity scheduleModel = t.GetScheduleModel(jobGroup, jobName); //添加任務 var addResult = AddScheduleJob(scheduleModel).Result; if (addResult.Code == 1000) { scheduleModel.Status = EnumType.JobStatus.已啟用; t.UpdateScheduleStatus(scheduleModel); //用給定的密鑰恢復(取消暫停)IJobDetail await this.Scheduler.Result.ResumeJob(new JobKey(jobName, jobGroup)); result = new BaseQuartzNetResult { Code = 1000, Msg = "啟動成功" }; } else { result = new BaseQuartzNetResult { Code = -1 }; } return result; } /// <summary> /// 添加一個工作調度(映射程式集指定IJob實現類) /// </summary> /// <param name="m"></param> /// <returns></returns> private async Task<BaseQuartzNetResult> AddScheduleJob(ScheduleEntity m) { var result = new BaseQuartzNetResult(); try { //檢查任務是否已存在 var jk = new JobKey(m.JobName, m.JobGroup); if (await this.Scheduler.Result.CheckExists(jk)) { //刪除已經存在任務 await this.Scheduler.Result.DeleteJob(jk); } //反射獲取任務執行類 var jobType = FileHelper.GetAbsolutePath(m.AssemblyName, m.AssemblyName + "." + m.ClassName); // 定義這個工作,並將其綁定到我們的IJob實現類 IJobDetail job = new JobDetailImpl(m.JobName, m.JobGroup, jobType); //IJobDetail job = JobBuilder.CreateForAsync<T>().WithIdentity(m.JobName, m.JobGroup).Build(); // 創建觸發器 ITrigger trigger; //校驗是否正確的執行周期表達式 if (!string.IsNullOrEmpty(m.Cron) && CronExpression.IsValidExpression(m.Cron)) { trigger = CreateCronTrigger(m); } else { trigger = CreateSimpleTrigger(m); } // 告訴Quartz使用我們的觸發器來安排作業 await this.Scheduler.Result.ScheduleJob(job, trigger); result.Code = 1000; } catch (Exception ex) { await Console.Out.WriteLineAsync(string.Format("添加任務出錯{0}", ex.Message)); result.Code = 1001; result.Msg = ex.Message; } return result; } /// <summary> /// 添加任務調度(指定IJob實現類) /// </summary> /// <typeparam name="T"></typeparam> /// <param name="m"></param> /// <returns></returns> private async Task<BaseQuartzNetResult> AddScheduleJob<T>(ScheduleEntity m) where T : IJob { var result = new BaseQuartzNetResult(); try { //檢查任務是否已存在 var jk = new JobKey(m.JobName, m.JobGroup); if (await this.Scheduler.Result.CheckExists(jk)) { //刪除已經存在任務 await this.Scheduler.Result.DeleteJob(jk); } //反射獲取任務執行類 // var jobType = FileHelper.GetAbsolutePath(m.AssemblyName, m.AssemblyName + "." + m.ClassName); // 定義這個工作,並將其綁定到我們的IJob實現類 //IJobDetail job = new JobDetailImpl(m.JobName, m.JobGroup, jobType); IJobDetail job = JobBuilder.CreateForAsync<T>().WithIdentity(m.JobName, m.JobGroup).Build(); // 創建觸發器 ITrigger trigger; //校驗是否正確的執行周期表達式 if (!string.IsNullOrEmpty(m.Cron) && CronExpression.IsValidExpression(m.Cron)) { trigger = CreateCronTrigger(m); } else { trigger = CreateSimpleTrigger(m); } // 告訴Quartz使用我們的觸發器來安排作業 await this.Scheduler.Result.ScheduleJob(job, trigger); result.Code = 1000; } catch (Exception ex) { await Console.Out.WriteLineAsync(string.Format("添加任務出錯", ex.Message)); result.Code = 1001; result.Msg = ex.Message; } return result; } /// <summary> /// 暫停指定的計劃 /// </summary> /// <param name="jobGroup">任務分組</param> /// <param name="jobName">任務名稱</param> /// <param name="isDelete">停止並刪除任務</param> /// <returns></returns> public BaseQuartzNetResult StopScheduleJob<T>(string jobGroup, string jobName, bool isDelete = false) where T : ScheduleManage, new() { BaseQuartzNetResult result; try { this.Scheduler.Result.PauseJob(new JobKey(jobName, jobGroup)); if (isDelete) { Activator.CreateInstance<T>().RemoveScheduleModel(jobGroup, jobName); } result = new BaseQuartzNetResult { Code = 1000, Msg = "停止任務計劃成功!" }; } catch (Exception ex) { result = new BaseQuartzNetResult { Code = -1, Msg = "停止任務計劃失敗" }; } return result; } /// <summary> /// 恢復運行暫停的任務 /// </summary> /// <param name="jobName">任務名稱</param> /// <param name="jobGroup">任務分組</param> public async void ResumeJob(string jobName, string jobGroup) { try { //檢查任務是否存在 var jk = new JobKey(jobName, jobGroup); if (await this.Scheduler.Result.CheckExists(jk)) { //任務已經存在則暫停任務 await this.Scheduler.Result.ResumeJob(jk); await Console.Out.WriteLineAsync(string.Format("任務“{0}”恢復運行", jobName)); } } catch (Exception ex) { await Console.Out.WriteLineAsync(string.Format("恢復任務失敗!{0}", ex)); } } /// <summary> /// 停止任務調度 /// </summary> public async void StopScheduleAsync() { try { //判斷調度是否已經關閉 if (!this.Scheduler.Result.IsShutdown) { //等待任務運行完成 await this.Scheduler.Result.Shutdown(); await Console.Out.WriteLineAsync("任務調度停止!"); } } catch (Exception ex) { await Console.Out.WriteLineAsync(string.Format("任務調度停止失敗!", ex)); } } /// <summary> /// 創建類型Simple的觸發器 /// </summary> /// <param name="m"></param> /// <returns></returns> private ITrigger CreateSimpleTrigger(ScheduleEntity m) { //作業觸發器 if (m.RunTimes > 0) { return TriggerBuilder.Create() .WithIdentity(m.JobName, m.JobGroup) .StartAt(m.BeginTime)//開始時間 .EndAt(m.EndTime)//結束數據 .WithSimpleSchedule(x => x .WithIntervalInSeconds(m.IntervalSecond)//執行時間間隔,單位秒 .WithRepeatCount(m.RunTimes))//執行次數、預設從0開始 .ForJob(m.JobName, m.JobGroup)//作業名稱 .Build(); } else { return TriggerBuilder.Create() .WithIdentity(m.JobName, m.JobGroup) .StartAt(m.BeginTime)//開始時間 .EndAt(m.EndTime)//結束數據 .WithSimpleSchedule(x => x .WithIntervalInSeconds(m.IntervalSecond)//執行時間間隔,單位秒 .RepeatForever())//無限迴圈 .ForJob(m.JobName, m.JobGroup)//作業名稱 .Build(); } } /// <summary> /// 創建類型Cron的觸發器 /// </summary> /// <param name="m"></param> /// <returns></returns> private ITrigger CreateCronTrigger(ScheduleEntity m) { // 作業觸發器 return TriggerBuilder.Create() .WithIdentity(m.JobName, m.JobGroup) .StartAt(m.BeginTime)//開始時間 .EndAt(m.EndTime)//結束數據 .WithCronSchedule(m.Cron)//指定cron表達式 .ForJob(m.JobName, m.JobGroup)//作業名稱 .Build(); } } }
想瞭解項目整體信息的可以下載源碼看看,歡迎dalao批評指導!