• Asp.Net Core 使用Quartz基于界面画接口管理做定时任务


    今天抽出一点点时间来造一个小轮子,是关于定时任务这块的。

    这篇文章主要从一下几点介绍:

    1. 创建数据库管理表
    2. 创建web项目
    3. 引入quarzt nuget 包
    4. 写具体配置操作,实现定时任务处理

    第一步:创建一个空web项目,引入quarzt nuget 包

    创建TB.AspNetCore.Quartz web项目和TB.AspNetCore.Data 类库,在web项目中引入Quartz nuget包

    第二部:数据库创建一张管理表

    -- ----------------------------
    -- 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文件夹

    其中,BaseService 里封装了针对数据操作的基本crud,quartz里封装了关于定时任务的配置,enum里枚举了任务状态,具体代码如下

    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

    如果您认为这篇文章还不错或者有所收获,您可以点击右下角的【推荐】按钮精神支持,因为这种支持是我继续写作,分享的最大动力

    欢迎大家关注我都我的微信 公众号,公众号涨粉丝人数,就是你们对我的喜爱程度!

     

  • 相关阅读:
    Java IO流-NIO简介
    Java IO流-Properties
    Java IO流-序列化流和反序列化流
    Codeforces Round #371 (Div. 1) C
    bzoj 2326 矩阵快速幂
    IndiaHacks 2016
    HDU
    Educational Codeforces Round 51 (Rated for Div. 2) F
    Codeforces Round #345 (Div. 1) D
    Codeforces Round #300 E
  • 原文地址:https://www.cnblogs.com/gdsblog/p/9286779.html
Copyright © 2020-2023  润新知