[外包]!采用asp.net core 快速构建小型创业公司后台管理系统(四.quartz 简单配置使用)...
上一章介绍了log4net的简单配置,这一章介绍一下quartz的简单使用,下一章介绍一下我得权限使用,然后就结束
本章主要介绍:
- quartz在asp.net core中的使用
这个项目虽小,但是及其容易扩展,后面的业务直接能丢进来,使其更加丰富
废话不说开始介绍
一.基础类配置
在domain里定义IJobCenter接口
代码如下:
public interface IJobCenter{/// <summary>/// 添加定时任务/// </summary>/// <param name="m"></param>/// <returns></returns>Task<Result> AddScheduleJobAsync(TaskScheduleModel m);/// <summary>/// 暂停定时任务/// </summary>/// <param name="jobGroup"></param>/// <param name="jobName"></param>/// <returns></returns>Task<Result> StopScheduleJobAsync(string jobGroup, string jobName);/// <summary>/// 恢复定时任务/// </summary>/// <param name="jobGroup"></param>/// <param name="jobName"></param>/// <returns></returns>Task<Result> RunScheduleJobAsync(TaskScheduleModel m);}
infrastructure里实现IJobCenter
记得引入quartz的nuget
代码如下:
/// <summary>/// 任务调度中心/// </summary>public class JobCenter:IJobCenter{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<Result> AddScheduleJobAsync(TaskScheduleModel m){Result result = new Result();try{if (m != null){DateTimeOffset starRunTime = DateBuilder.NextGivenSecondDate(m.StarRunTime, 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.CronExpress).Build();await scheduler.ScheduleJob(job, trigger);await scheduler.Start();result.Data = m;return result;}return result.SetError("传入实体为空");}catch (Exception ex){Log4Net.Error($"[JobCenter_AddScheduleJobAsync]_{ex}");return result.SetError(ex.Message);}}/// <summary>/// 暂停指定任务计划/// </summary>/// <returns></returns>public async Task<Result> StopScheduleJobAsync(string jobGroup, string jobName){Result result = new Result();try{scheduler = await GetSchedulerAsync();//使任务暂停await scheduler.PauseJob(new JobKey(jobName, jobGroup)); var status = new StatusViewModel(){Status = 0,Msg = "暂停任务计划成功",};result.Data = status.GetJson();return result;}catch (Exception ex){Log4Net.Error($"[JobCenter_StopScheduleJobAsync]_{ex}");var status = new StatusViewModel(){Status = -1,Msg = "暂停任务计划失败",};result.Data = status.GetJson();return result;}}/// <summary>/// 恢复指定的任务计划**恢复的是暂停后的任务计划,如果是程序奔溃后 或者是进程杀死后的恢复,此方法无效/// </summary>/// <returns></returns>public async Task<Result> RunScheduleJobAsync(TaskScheduleModel sm){Result result = new Result();try{#region 开任务//scheduler = await GetSchedulerAsync();//DateTimeOffset starRunTime = DateBuilder.NextGivenSecondDate(sm.StarRunTime, 1);//DateTimeOffset endRunTime = DateBuilder.NextGivenSecondDate(sm.EndRunTime, 1);//IJobDetail job = JobBuilder.Create<HttpJob>()// .WithIdentity(sm.JobName, sm.JobGroup)// .Build();//ICronTrigger trigger = (ICronTrigger)TriggerBuilder.Create()// .StartAt(starRunTime)// .EndAt(endRunTime)// .WithIdentity(sm.JobName, sm.JobGroup)// .WithCronSchedule(sm.CronExpress)// .Build();//await scheduler.ScheduleJob(job, trigger);//await scheduler.Start();#endregionscheduler = await GetSchedulerAsync();//resumejob 恢复await scheduler.ResumeJob(new JobKey(sm.JobName, sm.JobGroup));var status = new StatusViewModel(){Status = 0,Msg = "恢复任务计划成功",};result.Data = status.GetJson();return result;}catch (Exception ex){Log4Net.Error($"[JobCenter_RunScheduleJobAsync]_{ex}");var status = new StatusViewModel(){Status = -1,Msg = "恢复任务计划失败",};result.Data = status.GetJson();return result;}}}
写一个JobServiceExtensions拓展,其中里面有一个AddJobSerivce,用于在startup里添加启动服务
这个拓展的主要作用是:程序启动,自动查询我的任务调度管理表,查询里面的状态是开启中的任务,并将其添加到定时任务中
表结构大致如下:
这里我们主要注意任务组和任务名,这两个何在一起,能顶一个唯一的任务,后面我们会在httpjob里根据不同的的任务组和任务名
区分他们要执行的不同的逻辑
代码很简单:如下
public class HttpJob : IJob{/// <summary>/// 通过group和name判断是要执行哪个任务 具体(任务执行逻辑)业务逻辑写后面/// </summary>/// <param name="context"></param>/// <returns></returns>public async Task Execute(IJobExecutionContext context){await Task.Run(() =>{var name = context.JobDetail.Key.Name;var group = context.JobDetail.Key.Group;if (group=="xx1"&&name=="xx2"){//do something }if (group == "xx2" && name == "xx3"){//do something also }Log4Net.Info($"执行任务_Name:{name}_Grop:{group}");});}}
在domain里新增ITaskService接口,如下
代码如下:
public interface ITaskService{//获取任务列表 Result GetTaskList();//添加任务Task<Result> AddTaskAsync(TaskScheduleModel model);//修改任务Task<Result> ModifyTaskAsync(TaskScheduleModel model);//删除任务Task<Result> DelTaskAsync(TaskScheduleModel model);//暂停任务 Result PauseTask();//开启任务 Result StartTask();}
在application 里实现这个接口
代码如下:
public class TaskService : BaseService, ITaskService{private IJobCenter jobCenter = ServiceCollectionExtension.Get<IJobCenter>();private MvcIdentity identity = (ServiceCollectionExtension.HttpContext.User.Identity as MvcIdentity);public async Task<Result> AddTaskAsync(TaskScheduleModel model){Result result = new Result();if (model == null){return result.SetError("Model 不能为空!");}if (string.IsNullOrEmpty(model.JobName)){return result.SetError("JobName 不能为空!");}if (string.IsNullOrEmpty(model.JobGroup)){return result.SetError("JobGroup 不能为空!");}if (model.StarRunTime == null){model.StarRunTime = DateTime.Now;}if (model.EndRunTime == null){model.EndRunTime = DateTime.MaxValue.AddDays(-1);}var info = await jobCenter.AddScheduleJobAsync(model);if (info.Status != 200){return result.SetError(info.Message);}base.Add(new TaskSchedule{Id = Guid.NewGuid().ToString("N"),CreateAuthr = identity.Name,CronExpress = model.CronExpress,EndRunTime = model.EndRunTime,StarRunTime = model.StarRunTime,JobGroup = model.JobGroup,JobName = model.JobName,RunStatus = model.RunStatus}, true);return result;}public async Task<Result> DelTaskAsync(TaskScheduleModel model){Result result = new Result();if (model == null){return result.SetError("Model 不能为空!");}if (string.IsNullOrEmpty(model.JobName)){return result.SetError("JobName 不能为空!");}if (string.IsNullOrEmpty(model.JobGroup)){return result.SetError("JobGroup 不能为空!");}//searchvar taskInfo = base.Single<TaskSchedule>(t => t.Id.Equals(model.Id));var info = await jobCenter.StopScheduleJobAsync(model.JobGroup, model.JobName);if (!info.Status.Equals(200)){return result.SetError(info.Message);}//delbase.Delete(taskInfo, true);return result;}public Result GetTaskList(){Result result = new Result();var query = base.Where<TaskSchedule>(t => !t.RunStatus.Equals(TaskJobStatus.JobHasDel)).Select(t => new{t.Id,t.JobGroup,t.JobName,t.RunStatus,t.StarRunTime,t.UpdateTime,t.CronExpress,t.EndRunTime,t.CreateTime}).ToList();List<TaskScheduleModel> _list = new List<TaskScheduleModel>();query.ForEach(t =>{_list.Add(new TaskScheduleModel(){Id = t.Id,JobGroup = t.JobGroup,JobName = t.JobName,_RunStatus = ((TaskJobStatus)t.RunStatus).GetString(),StarRunTime = t.StarRunTime,UpdateTime = t.UpdateTime,CronExpress = t.CronExpress,EndRunTime = t.EndRunTime,CreateTime = t.CreateTime});});result.Data = _list;return result;}public async Task<Result> ModifyTaskAsync(TaskScheduleModel model){Result result = new Result();if (model == null){return result.SetError("Model 不能为空!");}if (string.IsNullOrEmpty(model.JobName)){return result.SetError("JobName 不能为空!");}if (string.IsNullOrEmpty(model.JobGroup)){return result.SetError("JobGroup 不能为空!");}if (model.StarRunTime == null){model.StarRunTime = DateTime.Now;}if (model.EndRunTime == null){model.EndRunTime = DateTime.MaxValue.AddDays(-1);}//modifyvar taskInfo = base.Single<TaskSchedule>(t => t.Id.Equals(model.Id));if (taskInfo == null){return result.SetError("无此任务!");}//cronif (!taskInfo.CronExpress.Equals(model.CronExpress)){taskInfo.CronExpress = model.CronExpress;var stopInfo = await jobCenter.StopScheduleJobAsync(model.JobGroup, model.JobName);if (!stopInfo.Status.Equals(200)){return result.SetError(stopInfo.Message);}var info = await jobCenter.AddScheduleJobAsync(model);if (!stopInfo.Status.Equals(200)){return result.SetError(info.Message);}}//状态if (!taskInfo.RunStatus.Equals(model.RunStatus)){taskInfo.RunStatus = model.RunStatus;if (model.RunStatus != (int)TaskJobStatus.PauseJob){var stopInfo = await jobCenter.StopScheduleJobAsync(model.JobGroup, model.JobName);if (!stopInfo.Status.Equals(200)){return result.SetError(stopInfo.Message);}var info = await jobCenter.AddScheduleJobAsync(model);if (!stopInfo.Status.Equals(200)){return result.SetError(info.Message);}}else{var stopInfo = await jobCenter.StopScheduleJobAsync(model.JobGroup, model.JobName);if (!stopInfo.Status.Equals(200)){return result.SetError(stopInfo.Message);}}}// taskInfo.CreateAuthr = identity.Name;taskInfo.UpdateTime = DateTime.Now;taskInfo.EndRunTime = model.EndRunTime;taskInfo.StarRunTime = model.StarRunTime;taskInfo.JobGroup = model.JobGroup;taskInfo.JobName = model.JobName;base.Update(taskInfo, true);return result;}public Result PauseTask(){throw new NotImplementedException();}public Result StartTask(){throw new NotImplementedException();}}
View Code
接着我们构建web页面
在website里创建taskinfo控制器
代码很简单只是做了一个跳转
创建视图
代码如下:
@{ViewData["title"] = "定时任务管理"; } <div class="row search"><div class="form-inline"><input type="text" class="form-control" placeholder="任务名称" ng-model="search.username" /></div><button class="btn btn-primary" type="button" ng-click="pagechanged(true)">搜索</button><button class="btn btn-primary" type="button" ng-click="addTask()">添加任务</button><button class="btn btn-primary" type="button" csv-header="getHeader()" ng-csv="_getCsv()" filename="taskList.csv" add-bom="true">导出</button> </div> @*弹出框*@ <div class="modal fade in" id="addmodel" tabindex="-1" role="dialog" data-backdrop="static" aria-labelledby="mymodallabel"><div class="modal-dialog modal-lg" role="document" style="height:100%"><div class="modal-content"><div class="modal-header"><button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span><span class="sr-only">close</span></button><h4>计划任务管理</h4></div><div class="modal-body" ng-form="mymodel"><div class="row"><div class="form-group col-sm-6"><label class="control-label col-sm-4">任务组:</label><div class="col-sm-8"><input type="text" class="form-control" ng-model="task.jobGroup" required placeholder="任务组" /></div></div><div class="form-group col-sm-6"><label class="control-label col-sm-4">任务名称:</label><div class="col-sm-8"><input type="text" class="form-control" ng-model="task.jobName" required placeholder="任务名称" /></div></div><div class="form-group col-sm-6"><label class="control-label col-sm-4">CronExpress:</label><div class="col-sm-8"><input type="text" class="form-control" ng-model="task.cronExpress" required placeholder="CronExpress" /></div></div><div class="form-group col-sm-6"><label class="control-label col-sm-4">运行状态:</label><div class="col-sm-8"><select class="form-control" required ng-model="task.runStatus">@*<option value="1">全部</option>*@<option value="1" selected>执行任务中</option><option value="2">暂停任务中</option><option value="4">任务关闭</option></select></div></div><div class="form-group col-sm-6"><label class="control-label col-sm-4">开始时间:</label><div class="col-sm-8"><input type="text" class="form-control mydatetimepicker" ng-model="task.starRunTime" ng-max-date="task.starRunTime||defaultDate" placeholder="开始日期" /></div></div><div class="form-group col-sm-6"><label class="control-label col-sm-4">结束时间:</label><div class="col-sm-8"><input type="text" class="form-control mydatetimepicker" ng-model="task.endRunTime" ng-min-date="task.starRunTime" ng-max-date="defaultDate" placeholder="结束日期" /></div></div></div></div><div class="modal-footer"><button type="button" class="btn btn-success" ng-disabled="mymodel.$invalid" ng-click="saveTask()">保 存</button></div></div></div> </div><table class="table table-hover table-condensed table-bordered" style="width:auto;"><thead><tr style="height: 35px;"><th>任务组</th><th>任务</th><th>CronExpress</th><th>开始时间</th><th>结束时间</th><th>运行状态</th><th>创建时间</th><th>修改时间</th><th>操作</th></tr></thead><tbody class="wait-loaded"><tr ng-repeat="m in list track by m.id"><td>{{m.jobGroup}}</td><td>{{m.jobName}}</td><td>{{m.cronExpress}}</td><td>{{m.starRunTime}}</td><td>{{m.endRunTime}}</td><td>{{m._RunStatus}}</td><td>{{m.createTime}}</td><td>{{m.updateTime}}</td><td><button class="btn btn-success" ng-click="edit(m)">编辑</button><button class="btn btn-danger" ng-click="delete(m)">删除</button></td></tr></tbody> </table> <div class="mypager wait-loaded"><ul uib-pagination total-items="search.recordcount" items-per-page="search.pagesize" ng-change="pagechanged()" ng-model="search.pageindex" max-size="7"class="pagination-sm" boundary-links="true" num-pages="search.numpages" boundary-link-numbers="true" first-text="首页" last-text="末页" previous-text="上一页" next-text="下一页"></ul><div class="recordcount">共 {{search.recordcount}} 条</div> </div> @section scripts{<script type="text/javascript">$angular.add(function ($scope, $query, $timeout, $sce) {$scope.getHeader = function () { return ["任务组", "任务", "CronExpress", "开始时间", "结束时间", "运行状态", "创建时间", "修改时间"] };$scope._getCsv = function () {var model = _.cloneDeep($scope.search);model.pageSize = 10000000;var promise = $query.post("/webapi/GetTaskList", model, function (response) {var objList = angular.fromJson(response.data);var getArray = [];_.forEach(objList, function (item) {getArray.push({"jobGroup": item.jobGroup,"jobName": item.jobName,"cronExpress": item.cronExpress,"starRunTime": item.starRunTime,"endRunTime": item.endRunTime,"_RunStatus": item._RunStatus,"createTime": item.createTime,"updateTime": item.updateTime});});return getArray;});return promise;};$scope.search = { pageindex: 1, pagesize: 10, gender: "-1", order: 1, status: "-1" };$scope.setorder = function (index) {if (index == math.abs($scope.search.order)) {index = -$scope.search.order;}$scope.search.order = index;$scope.pagechanged(true);};//查询$scope.pagechanged = function (reindex) {if (reindex) {$scope.search.pageindex = 1;}$query.post("/webapi/GetTaskList", $scope.search, function (response) {if (response.status === 200) {$scope.list = response.data;$scope.search.recordcount = response.recordcount;} else {$alert(response.message);}});};$scope.pagechanged();//添加任务$scope.addTask = function () {$("#addmodel").modal("show");$scope.task = { id: -1 };};//保存$scope.saveTask = function () {$query.post("/webapi/AddTaskAsync", $scope.task, function (response) {$("#addmodel").modal("hide");$scope.pagechanged();});};$scope.edit = function (m) {$("#addmodel").modal("show");m.id = m.id;$scope.task = m;}//删除类型$scope.delete = function (m) {m.id = m.id;$scope.task = m;$Confirm("你确认删除吗?该操作不可恢复!", function () {$query.post("/webapi/DelTaskAsync", $scope.task, function (response) {$scope.pagechanged();});});}});</script> }
View Code
之后效果就出来了
这个table会调用一个webapi接口获取数据
这个webapi里我们直接调用我们改才ITaskService里分装的方法
这里代码如下:
#region 计划任务模块[HttpPost]public Result GetTaskList(){return _taskService.GetTaskList();}[HttpPost]public async Task<Result> AddTaskAsync([FromBody]TaskScheduleModel model){if (model != null && !string.IsNullOrEmpty(model.Id)&&!model.Id.Equals("-1")){return await _taskService.ModifyTaskAsync(model);}return await _taskService.AddTaskAsync(model);}public async Task<Result> DelTaskAsync([FromBody]TaskScheduleModel model){return await _taskService.DelTaskAsync(model);}#endregion
二.运行测试
换得添加服务哦
算了,这个运行测试截图不好说明,明天录一个视频说明一下,今天就到这里
下一章主要说一下权限这块的东西,本来想着今天就写完的,但是有点困了,
此文章献给我做一年半asp.net core开发的青春岁月,晚安!
[外包]!采用asp.net core 快速构建小型创业公司后台管理系统(四.quartz 简单配置使用)...相关推荐
- ASP.NET Core WebApi构建API接口服务实战演练
一.ASP.NET Core WebApi课程介绍 人生苦短,我用.NET Core!提到Api接口,一般会想到以前用到的WebService和WCF服务,这三个技术都是用来创建服务接口,只不过Web ...
- 【笔记目录1】【jessetalk 】ASP.NET Core快速入门_学习笔记汇总
当前标签: ASP.NET Core快速入门 共2页: 1 2 下一页 任务50:Identity MVC:DbContextSeed初始化 GASA 2019-03-02 14:09 阅读:16 ...
- asp.Net Core免费开源分布式异常日志收集框架Exceptionless安装配置以及简单使用图文教程...
最近在学习张善友老师的NanoFabric 框架的时了解到Exceptionless : https://exceptionless.com/ !因此学习了一下这个开源框架!下面对Exceptionl ...
- 零基础快速开发全栈后台管理系统(Vue3+ElementPlus+Koa2)—项目概述篇(一)
零基础快速开发全栈后台管理系统(Vue3+ElementPlus+Koa2)-项目概述篇(一) 一.项目开发总体框架 二.项目开发流程 三.项目技术选型
- ASP.NET Core 快速入门
ASP.NET Core 是一个由微软创建的,用于构建 web 应用.API.微服务 的 web 框架.通过本文的学习就能快速的入门ASP.NET Core,对大家的学习或者工作具有一定的参考学习价值 ...
- ASP.NET Core快速入门(第4章:ASP.NET Core HTTP介绍)--学习笔记
点击蓝字关注我们 课程链接:http://video.jessetalk.cn/course/explore 良心课程,大家一起来学习哈! 任务22:课程介绍 1.HTTP 处理过程 2.WebHos ...
- 为什么 web 开发人员需要迁移到. NET Core, 并使用 ASP.NET Core MVC 构建 web 和 API
2018 .NET开发者调查报告: .NET Core 是怎么样的状态,这里我们看到了还有非常多的.net开发人员还在观望,本文给大家一个建议.这仅代表我的个人意见, 我有充分的理由推荐.net 程序 ...
- WTM:ASP.NET Core快速开发利器!
不少程序员朋友应该都有这个想法,接接私活,赚赚外快,但是从零开发一套系统并不容易,今天给大家推荐一款开箱即用的通用后台管理系统. 一个能够让程序猿快速开发的炒鸡脚手架,采用.NET Core开源框架! ...
- ASP.NET Core快速入门(第3章:依赖注入)--学习笔记
点击蓝字关注我们 课程链接:http://video.jessetalk.cn/course/explore 良心课程,大家一起来学习哈! 任务16:介绍 1.依赖注入概念详解 从UML和软件建模来理 ...
最新文章
- html文档表示表格的标记,【单选题】在HTML文档中用于表示表格的标记对是( )...
- 【微信开发】微信开发 之 开启开发模式
- 微信腾讯会议进行视频面试,如何使用腾讯会议进行视频面试?
- ORACLE数据库实现自增的方式
- Midway Serverless 2.0,一体化让前端研发再次提效
- WinDbg学习笔记(一)--认识WinDbg
- tomcat中设置Java 客户端程序的http(https)访问代理
- 密码学研究-加密解密
- 什么是数据治理的方法论
- 只知道CS224N?斯坦福最新推出NLU公开课CS224U
- 研究多个基因间相互作用的频域方法
- 你知道吗?世界上绝美神奇的25条路
- python网课答案查询_网课答案查询助手v1.0 官方版
- 服务器备案全流程超级详细
- 【AI视野·今日CV 计算机视觉论文速览 第228期】Tue, 29 Jun 2021
- 电视台工作计算机管理,电视台工作岗位有哪些
- 树洞程序php,Anonymous – 秘密 PHP树洞程序
- 服务器显示器白屏,电脑显示器白屏的原因以及处理方法
- 北京:一个大学生每年要花多少钱
- 摸鱼还是学习?来看看这些网站吧!