今天抽出一點點時間來造一個小輪子,是關於定時任務這塊的。mysql
這篇文章主要從一下幾點介紹:git
- 建立數據庫管理表
- 建立web項目
- 引入quarzt nuget 包
- 寫具體配置操做,實現定時任務處理
第一步:建立一個空web項目,引入quarzt nuget 包github
建立TB.AspNetCore.Quartz web項目和TB.AspNetCore.Data 類庫,在web項目中引入Quartz nuget包web
第二部:數據庫建立一張管理表sql
-- ---------------------------- -- Table structure for ScheduleInfo -- ---------------------------- DROP TABLE IF EXISTS `ScheduleInfo`; CREATE TABLE `ScheduleInfo` ( `Id` int(11) NOT NULL AUTO_INCREMENT COMMENT '編號', `JobGroup` varchar(100) NOT NULL DEFAULT '' COMMENT '任務組', `JobName` varchar(50) NOT NULL DEFAULT '' COMMENT '任務名', `RunStatus` int(11) NOT NULL DEFAULT '0' COMMENT '運行狀態', `CromExpress` varchar(40) NOT NULL DEFAULT '' COMMENT 'Crom表達式', `StarRunTime` datetime DEFAULT NULL COMMENT '開始運行時間', `EndRunTime` datetime DEFAULT NULL COMMENT '結束運行時間', `NextRunTime` datetime DEFAULT NULL COMMENT '下次運行時間', `Token` varchar(40) NOT NULL DEFAULT '' COMMENT 'Token', `AppID` varchar(40) NOT NULL DEFAULT '' COMMENT 'AppID', `ServiceCode` varchar(40) DEFAULT NULL, `InterfaceCode` varchar(40) DEFAULT NULL, `TaskDescription` varchar(200) DEFAULT NULL, `DataStatus` int(11) DEFAULT NULL COMMENT '數據狀態', `CreateAuthr` varchar(30) DEFAULT NULL COMMENT '建立人', `CreateTime` datetime DEFAULT NULL COMMENT '建立時間', PRIMARY KEY (`Id`) ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
建立數據庫的表結構如圖所示,接下來咱們在Data項目裏添加mysql數據庫驅動nuget包數據庫
打開PM,執行數據庫反向工程命令,從數據庫生成model實體服務器
Scaffold-DbContext "Server=你的服務器地址;Database=你的數據庫;User=數據庫用戶名;Password=你的數據庫密碼;" "Pomelo.EntityFrameworkCore.MySql" -OutputDir Entity**2.1.1 建議不要選用,防坑!微信
將連接字符串換成你本身的,咱們又新添加了一個service文件夾和一個Enum文件夾async
其中,BaseService 裏封裝了針對數據操做的基本crud,quartz裏封裝了關於定時任務的配置,enum裏枚舉了任務狀態,具體代碼以下ui
public enum JobStatus { [Description("已啓用")] 已啓用, [Description("運行中")] 待運行, [Description("執行中")] 執行中, [Description("執行完成")] 執行完成, [Description("執行任務計劃中")] 執行任務計劃中, [Description("已中止")] 已中止, }
下面是baseservice裏具體方法
public class BaseService { protected static object obj = new object(); public ggb_offlinebetaContext _context; protected ggb_offlinebetaContext DataContext { get { if (_context == null) { _context = new ggb_offlinebetaContext(); } return _context; } } public BaseService() { } #region 封裝基crud /// <summary> /// 只能是惟一記錄 多記錄引起異常 /// </summary> /// <typeparam name="TSource"></typeparam> /// <param name="predicate"></param> /// <returns></returns> public TSource Single<TSource>(Expression<Func<TSource, bool>> predicate = null) where TSource : class { if (predicate == null) { return this.DataContext.Set<TSource>().SingleOrDefault(); } return this.DataContext.Set<TSource>().SingleOrDefault(predicate); } /// <summary> /// 查詢一條記錄 /// </summary> /// <typeparam name="TSource"></typeparam> /// <param name="predicate"></param> /// <returns></returns> public TSource First<TSource>(Expression<Func<TSource, bool>> predicate = null) where TSource : class { if (predicate == null) { return this.DataContext.Set<TSource>().FirstOrDefault(); } return this.DataContext.Set<TSource>().FirstOrDefault(predicate); } /// <summary> /// where條件查詢 /// </summary> /// <typeparam name="TSource"></typeparam> /// <param name="predicate"></param> /// <returns></returns> public IQueryable<TSource> Where<TSource>(Expression<Func<TSource, bool>> predicate = null) where TSource : class { if (predicate == null) { return this.DataContext.Set<TSource>().AsQueryable(); } return this.DataContext.Set<TSource>().Where(predicate); } /// <summary> /// 記錄數 /// </summary> /// <typeparam name="TSource"></typeparam> /// <param name="predicate"></param> /// <returns></returns> public int Count<TSource>(Expression<Func<TSource, bool>> predicate = null) where TSource : class { if (predicate == null) { return this.DataContext.Set<TSource>().Count(); } return this.DataContext.Set<TSource>().Count(predicate); } /// <summary> /// 根據條件判斷記錄是否存在 /// </summary> /// <typeparam name="TSource"></typeparam> /// <param name="predicate"></param> /// <returns></returns> /// Any肯定序列是否包含任何元素 public bool Exists<TSource>(Expression<Func<TSource, bool>> predicate = null) where TSource : class { if (predicate == null) { return this.DataContext.Set<TSource>().Any(); } return this.DataContext.Set<TSource>().Any(predicate); } /// <summary> /// 查詢所有 /// </summary> /// <typeparam name="TSource"></typeparam> /// <returns></returns> public IQueryable<TSource> Query<TSource>() where TSource : class { return this.DataContext.Set<TSource>(); } /// <summary> /// paging the query 分頁查詢 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="query"></param> /// <param name="pageIndex">page index</param> /// <param name="pageSize">page size </param> /// <param name="count">total row record count</param> /// <returns></returns> public IQueryable<T> Pages<T>(IQueryable<T> query, int pageIndex, int pageSize, out int count) where T : class { if (pageIndex < 1) { pageIndex = 1; } if (pageSize < 1) { pageSize = 10; } count = query.Count(); query = query.Skip((pageIndex - 1) * pageSize).Take(pageSize); return query; } /// <summary> /// 分頁查詢 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="pageIndex"></param> /// <param name="pageSize"></param> /// <param name="count"></param> /// <returns></returns> public IQueryable<T> Pages<T>(int pageIndex, int pageSize, out int count) where T : class { if (pageIndex < 1) { pageIndex = 1; } if (pageSize < 1) { pageSize = 10; } var query = this.DataContext.Set<T>().AsQueryable(); count = query.Count(); query = query.Skip((pageIndex - 1) * pageSize).Take(pageSize); return query; } #endregion /// <summary> /// 作一次提交 /// </summary> #region Save Changes public void Save() { //todo 須要驗證是否須要釋放 using (this.DataContext) { this.DataContext.SaveChanges(); } } /// <summary> /// 添加 /// </summary> /// <param name="entity"></param> /// <param name="save"></param> public void Add(object entity, bool save = false) { this.DataContext.Add(entity); if (save) { this.Save(); } } /// <summary> /// 更新實體 /// </summary> /// <param name="entity"></param> /// <param name="save"></param> public void Update(object entity, bool save = false) { this.DataContext.Update(entity); if (save) { this.Save(); } } /// <summary> /// 更新2 /// </summary> /// <param name="list"></param> /// <param name="save"></param> public void Update(IEnumerable<object> list, bool save = false) { this.DataContext.UpdateRange(list); if (save) { this.Save(); } } /// <summary> /// 刪除1 /// </summary> /// <param name="entity"></param> /// <param name="save"></param> public void Delete(object entity, bool save = false) { this.DataContext.Remove(entity); if (save) { this.Save(); } } /// <summary> /// 刪除2 /// </summary> /// <param name="list"></param> /// <param name="save"></param> public void Delete(IEnumerable<object> list, bool save = false) { this.DataContext.RemoveRange(list); if (save) { this.Save(); } } #endregion ///// <summary> ///// 釋放資源 ///// </summary> //public void Dispose() //{ // _context.Dispose(); //} }
下面是任務調度中心代碼
/// <summary> /// 任務調度中心 /// </summary> public class JobCenter { /// <summary> /// 任務計劃 /// </summary> public static IScheduler scheduler = null; public static async Task<IScheduler> GetSchedulerAsync() { if (scheduler != null) { return scheduler; } else { ISchedulerFactory schedf = new StdSchedulerFactory(); IScheduler sched = await schedf.GetScheduler(); return sched; } } /// <summary> /// 添加任務計劃//或者進程終止後的開啓 /// </summary> /// <returns></returns> public async Task<bool> AddScheduleJobAsync(ScheduleInfo m) { try { if (m != null) { if (m.StarRunTime == null) { m.StarRunTime = DateTime.Now; } DateTimeOffset starRunTime = DateBuilder.NextGivenSecondDate(m.StarRunTime, 1); if (m.EndRunTime == null) { m.EndRunTime = DateTime.MaxValue.AddDays(-1); } DateTimeOffset endRunTime = DateBuilder.NextGivenSecondDate(m.EndRunTime, 1); scheduler = await GetSchedulerAsync(); IJobDetail job = JobBuilder.Create<HttpJob>() .WithIdentity(m.JobName, m.JobGroup) .Build(); ICronTrigger trigger = (ICronTrigger)TriggerBuilder.Create() .StartAt(starRunTime) .EndAt(endRunTime) .WithIdentity(m.JobName, m.JobGroup) .WithCronSchedule(m.CromExpress) .Build(); //將信息寫入 new ScheduleManage().AddSchedule(m); await scheduler.ScheduleJob(job, trigger); await scheduler.Start(); await StopScheduleJobAsync(m.JobGroup, m.JobName); return true; } return false; } catch (Exception ex) { //MyLogger.WriteError(ex, null); return false; } } /// <summary> /// 暫停指定任務計劃 /// </summary> /// <returns></returns> public async Task<string> StopScheduleJobAsync(string jobGroup, string jobName) { try { scheduler = await GetSchedulerAsync(); //使任務暫停 await scheduler.PauseJob(new JobKey(jobName, jobGroup)); //更新數據庫 new ScheduleManage().UpdateScheduleStatus(new ScheduleInfo() { JobName = jobName, JobGroup = jobGroup, RunStatus = (int)JobStatus.已中止 }); var status = new StatusViewModel() { Status = 0, Msg = "暫停任務計劃成功", }; return JsonConvert.SerializeObject(status); } catch (Exception ex) { //MyLogger.WriteError(ex, null); var status = new StatusViewModel() { Status = -1, Msg = "暫停任務計劃失敗", }; return JsonConvert.SerializeObject(status); } } /// <summary> /// 恢復指定的任務計劃**恢復的是暫停後的任務計劃,若是是程序奔潰後 或者是進程殺死後的恢復,此方法無效 /// </summary> /// <returns></returns> public async Task<string> RunScheduleJobAsync(string jobGroup, string jobName) { try { //獲取model var sm = new ScheduleManage().GetScheduleModel(new ScheduleInfo() { JobName = jobName, JobGroup = jobGroup }); await AddScheduleJobAsync(sm); sm.RunStatus = (int)JobStatus.已啓用; //更新model new ScheduleManage().UpdateScheduleStatus(sm); scheduler = await GetSchedulerAsync(); //resumejob 恢復 await scheduler.ResumeJob(new JobKey(jobName, jobGroup)); var status = new StatusViewModel() { Status = 0, Msg = "開啓任務計劃成功", }; return JsonConvert.SerializeObject(status); } catch (Exception ex) { var status = new StatusViewModel() { Status = -1, Msg = "開啓任務計劃失敗", }; return JsonConvert.SerializeObject(status); } } }
其餘幾個文件的細節代碼我就再也不粘貼,詳細代碼會推到github上去,接下來寫一個控制器看看效果!
第四部:項目運行截圖
具體詳細的東西,也沒有說的十分清晰,具體的代碼能夠到github上去查看,
項目github地址:https://github.com/TopGuo/TB.AspNetCore.Quarzt
若是您認爲這篇文章還不錯或者有所收穫,您能夠點擊右下角的【推薦】按鈕精神支持,由於這種支持是我繼續寫做,分享的最大動力
歡迎你們關注我都個人微信 公衆號,公衆號漲粉絲人數,就是大家對個人喜好程度!