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

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

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

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

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

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

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

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

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

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

-- ----------------------------
-- 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包

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

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

 

打开PM,执行数据库反向工程命令,从数据库生成model实体

Scaffold-DbContext "Server=你的服务器地址;Database=你的数据库;User=数据库用户名;Password=你的数据库密码;" "Pomelo.EntityFrameworkCore.MySql" -OutputDir Entity

 **2.1.1 建议不要选用,防坑!

 

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

将链接字符串换成你自己的,我们又新添加了一个service文件夹和一个Enum文件夹

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

其中,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上去,接下来写一个控制器看看效果!

第四部:项目运行截图

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

 

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

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

 

 

具体详细的东西,也没有说的十分清晰,具体的代码可以到github上去查看,

项目github地址:https://github.com/TopGuo/TB.AspNetCore.Quarzt

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

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

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

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/101555.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 日语自动词和他动词是什么意思_日语自动词他动词总结

    日语自动词和他动词是什么意思_日语自动词他动词总结http://coffeejp.com/bbs/thread-182243-1-1.html自动词:强调自发的行为他动词:强调他人驱使的行为拿到两个动词后按照它们的构词形式可以进行区分,基本可以分为4种方法(1)两个动词都以「る」结尾时:看「る」前的那个假名(汉字除外),如果是「あ」段假名,一般是自动词;如果是「え」段假名,一般是他动词(2)两个动词一个以「る」结尾,另一个不是以「る」结尾…

    2025年7月3日
    3
  • ch340转485电路图_ch340c芯片手册

    ch340转485电路图_ch340c芯片手册CH340可以实现USB转TTL串口电路,但是CH340芯片上不能直接出来RS485电平信号,所以要通过电平转换芯片来实现。由于RS485一般用半双工通信,所以需要一个使能信号来控制RS485收发器的方向。从支持RS485的功能来讲CH340系列分为有TNOW引脚(如CH340B、CH340T和CH340E等)和无TNOW引脚(如CH340C/CH340K/CH340N等)两种。没有TNOW引脚的CH340实现RS485信号收发需要外加一个反相器,原理图如下:有TNOW引脚的CH340B可以省去反相

    2022年5月3日
    354
  • 幸福课第11讲_笔记

    幸福课第11讲_笔记11例行公事1.身体反馈假说2.没有更多的自律3.认知重建4.总结:如何成为成功人士,专家5.日记知道我们为什么要考试吗?—为了让你主动去整合我们之前学过的东西,这个课每节之间有联系的,你要去总结身体反馈假说理论:你在和你自己交流,通过伪造行为上的笑等–你的思想也和其保持一致实验:内向男144分钟聊天—(异性在男生不知觉该实验的情况下,主动谈笑风生12分钟x6个x2次…

    2022年7月18日
    15
  • Laravel框架加载出错require(): open_basedir restriction in effect

    Laravel框架加载出错require(): open_basedir restriction in effect

    2022年2月14日
    46
  • Java 9 逆天的十大新特性

    Java 9 逆天的十大新特性

    2021年5月25日
    178
  • html+css实现漂亮的透明登录页面,HTML实现炫酷登录页面

    html+css实现漂亮的透明登录页面,HTML实现炫酷登录页面承蒙各位小伙伴的支持,鄙人有幸入围了《CSDN2020博客之星》的前200名,现在进入投票环节,如果我平时写的文章和分享对你有用的话,请每天点击一下这个链接,投上你们宝贵的一票吧!谢谢!❤️每一票都是我坚持的动力和力量!https://bss.csdn.net/m/topic/blog_star2020/detail?username=qq_23853743作者:AlbertYang,软件设计师,Java工程师,前端工程师,爱阅读,爱思考,爱编程,爱自由,信奉终生学习,每天学习一点点,就是领.

    2022年4月30日
    342

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号