WebAPI中的定时处理-使用Quartz.Net
借鉴:
https://blog.csdn.net/lordwish/article/details/78926252
在最近的一篇文章中讲到了如何在web API中实现定时处理,采用的是比较原始的Timer定时器,功能简单,无法胜任复杂任务。本次就着重介绍一下定时任务框架Quartz.Net。
Quartz.Net来源于Java中的Quartz框架,后来有了.Net版本就加了后缀.Net以示区别。Quartz.Net可以实现诸如定时发送邮件、定时处理数据、定时轮询数据库等计划任务,只需要几句代码,不需要Windows计划任务也能实现诸如“每天早上8:00发送邮件”、“每隔半个小时查询一次库存”之类的目的。
安装Quartz.Net
Quartz.Net的安装可以说非常简单,使用NuGet管理器是非常方便的。打开Asp.Net项目,我这里用的是WebApi做的例子(当然用MVC、WPF等也是可以的),打开Nuget管理器,查找Quartz.Net,点击安装。
安装完成后会发现项目自动添加了三个类库的引用,分别是Common.Logging、Common.Logging.Core、Quartz,其中Quartz是我们需要用到的核心类库,其余两个是日志相关的类库。
Quartz.Net使用示例
这里我将采用上篇的定时发送邮件的示例来说明Quartz.Net,目标是每半个小时发送一封邮件。
发送邮件方法
public async Task<int> Auto()
{
int num = 0;
try
{
MailModel model = new MailModel()
{
ReceiverAddress = "",//收件人地址
ReceiverName = "",//收件人姓名
Title = "",//邮件标题
Content = "",//邮件内容
SenderAddress = "",//发件人地址
SenderName = "",//发件人姓名
SenderPassword = ""//发件人密码
};
bool result = MailHelper.SendMail(model);
}
catch (Exception)
{
num = -1;
}
return await Task.FromResult(num);
}
创建发送邮件的任务
Quzrtz中有Job的概念,Job就是我们所讲的任务。
using Quartz;
using Quartz.Impl;
public class TimeJob : IJob
{
public void Execute(IJobExecutionContext context)
{
//具体的方法
Auto();
}
}
创建类TimeJob并继承Quzrtz中的接口IJob,实现接口IJob中的方法Execute,在Execute方法中可以创建具体的方法。
创建任务调度器
public class JobScheduler
{
public static void Start()
{
//调度器工厂
ISchedulerFactory factory = new StdSchedulerFactory();
//调度器
IScheduler scheduler = factory.GetScheduler();
scheduler.GetJobGroupNames();
/*-------------计划任务代码实现------------------*/
//创建任务
IJobDetail job = JobBuilder.Create<TimeJob>().Build();
//创建触发器
ITrigger trigger = TriggerBuilder.Create().WithIdentity("TimeTrigger", "TimeGroup").WithSimpleSchedule(t => t.WithIntervalInMinutes(30).RepeatForever()).Build();
//添加任务及触发器至调度器中
scheduler.ScheduleJob(job, trigger);
/*-------------计划任务代码实现------------------*/
//启动
scheduler.Start();
}
}
创建任务调度器类JobScheduler,把上面的定时发送邮件任务TimeJob和触发器添加到任务调度器中。任务Job就是具体要做的事情,触发器Trigger就是任务要执行的时机。可以创建多个Job任务和多个Trigger触发器加入到调度器中。
启动计划任务
任务调度器已经完成了,下步要做的就是在程序启动时开启任务调度器了。在项目的Global.asax.cs中进行如下配置
public class WebApiApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
//注册定时任务
Helpers.JobScheduler.Start();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
}
使用配置文件实现计划任务
上面就是一个简单的定时任务示例,但是还有一点不足之处,那就是触发器的配置是在代码中写的,如果我们想由原来的半个小时发一次改成一个小时发一次,就需要改代码、编译、发布,显然太麻烦,有没有更好的方式呢?幸运的是Quartz.Net可以通过XML配置文件实现定时任务。仍然是上面发邮件的例子,我们使用配置文件来实现。
修改Web.config文件
修改项目配置文件Web.config,在configSections节点下添加子节点,对应的添加Quartz的基本配置。在最后一行的“key=”quartz.plugin.xml.fileNames” value=”~/quartz_jobs.xml” ”,表示Quertz的任务调度计划。
<configSections>
<!--Quartz-->
<section name="quartz" type="System.Configuration.NameValueSectionHandler"/>
</configSections>
<!--Quartz配置-->
<quartz>
<add key="quartz.scheduler.instanceName" value="ExampleDefaultQuartzScheduler"/>
<add key="quartz.threadPool.type" value="Quartz.Simpl.SimpleThreadPool, Quartz"/>
<add key="quartz.threadPool.threadCount" value="10"/>
<add key="quartz.threadPool.threadPriority" value="2"/>
<add key="quartz.jobStore.misfireThreshold" value="60000"/>
<add key="quartz.jobStore.type" value="Quartz.Simpl.RAMJobStore, Quartz"/>
<!--******************************Plugin配置*********************************************-->
<add key="quartz.plugin.xml.type" value="Quartz.Plugin.Xml.XMLSchedulingDataProcessorPlugin, Quartz" />
<add key="quartz.plugin.xml.fileNames" value="~/quartz_jobs.xml"/>
</quartz>
添加quzrtz_jobs.xml
对应上面提到的配置文件中文件路径“key=”quartz.plugin.xml.fileNames” value=”~/quartz_jobs.xml” ”,在项目目录下添加文件quartz_jobs.xml,项目启动是会从此文件中读取任务计划来执行,具体内容如下:
<job-scheduling-data xmlns="http://quartznet.sourceforge.net/JobSchedulingData" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0">
<processing-directives>
<overwrite-existing-data>true</overwrite-existing-data>
</processing-directives>
<schedule>
<!--开始执行一个调度-->
<!--任务,可添加多个-->
<job>
<!--任务名称【必填】:同一group中多个job的name名不能相同-->
<name>TimeJob</name>
<!--任务所属分组【选填】-->
<group>Timer</group>
<!--任务描述【选填】-->
<description>定时任务</description>
<!--任务类型【必填】:实现IJob接口完整命名空间的类名,程序集名-->
<job-type>WebAPI.Helpers.TimeJob, WebAPI</job-type>
<durable>true</durable>
<recover>false</recover>
</job>
<!--触发器,可添加多个-->
<trigger>
<!--simple:简单触发器类型,cron:复杂触发器类型【推荐】-->
<cron>
<!--触发器名称【必填】:同一group中多个trigger的name不能相同-->
<name>TimeTrigger</name>
<!--触发器组【选填】-->
<group>Timer</group>
<!--触发器描述【选填】-->
<description>每隔半小时推送未处理报警信息</description>
<!--要调度的任务名称【必填】:必须和对应job节点中的name相同-->
<job-name>TimeJob</job-name>
<!--要调度的任务的所属分组【选填】:必须和对应job节点中的group相同-->
<job-group>Timer</job-group>
<cron-expression>0 */30 * * * ?</cron-expression>
</cron>
</trigger>
<!--结束一个调度-->
</schedule>
</job-scheduling-data>
修改调度器类
配置文件修改完成后,再对调度器类进行相应修改,只需要将创建任务、触发器的代码去掉即可,如下:
public class JobScheduler
{
public static void Start()
{
//调度器工厂
ISchedulerFactory factory = new StdSchedulerFactory();
//调度器
IScheduler scheduler = factory.GetScheduler();
scheduler.GetJobGroupNames();
//启动
scheduler.Start();
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
Quartz.Net使用进阶
上面就是我们使用Quartz实现的简单定时任务,如果要实现更复杂的任务调度,强烈推荐使用cron复杂任务触发器。cron复杂任务触发器支持使用cron表达式自定义任务调度,理解了cron表达式的结构和用法,实现各种定制性的任务调度就不会有太大问题了。cron表达式由“秒分时日月星期年”共7段构成,其中“年”是可选的。Quartz官方文档提供的cron表达式的相关说明。
cron表达式说明
字段名 | 是否必填 | 取值范围 | 允许特殊字符 |
---|---|---|---|
秒 | 必填 | 0-59 | ,-*/ |
分 | 必填 | 0-59 | ,-*/ |
时 | 必填 | 0-23 | ,-*/ |
日 | 必填 | 1-31 | ,-*?/LW |
月 | 必填 | 1-12或JAN-DEC | ,-*/ |
星期 | 必填 | 1-7或SUN-SAT | ,-*?/LW |
年 | 非必填 | 空,1970-2099 | ,-*/ |
cron特殊字符说明
特殊字符 | 说明 |
---|---|
* | 表示“每”,比如每小时、每分钟、每日、每年 |
? | 表示不指定具体的值,只能出现在日、星期中 |
- | 表示范围,比如时字段中10-12表示10点、11点、12点 |
, | 表示列举,比如“MON,WED,FRI”表示周一、周三和周五 |
/ | 表示增量,比如在秒字段中“0/15”表示从0秒开始每次增加15秒,也就是15、30、45秒 |
L | 表示最后的,只能出现在日、星期字段中,表示一个月的最后一天、一个星期的最后一天 |
W | 表示工作日,指距离给定日期最近的工作日 |
# | 表示一个月的第几个星期几,比如“6#3”表示每个月的第三个周五 |
cron表达式示例
表达式 | 含义 |
---|---|
0 0 12 * * ? | 每天12点 |
0 15 10 ? * * | 每天10:15 |
0 15 10 * * ? | 每天10:15 |
0 15 10 * * ? * | 每天10:15 |
0 15 10 * * ? | 2005年每天10:15 |
0 * 14 * * ? | 每天14:00到14:59期间的每一分钟 |
0 0/5 14 * * ? | 每天14:00到14:55期间的每5分钟 |
0 0/5 14,18 * * ? | 每天14:00到14:55和18:00到18:55期间的每5分钟 |
0 0-5 14 * * ? | 每天14:00到14:05期间的每一分钟 |
0 10,44 14 ? 3 WED | 每年三月的星期三的14:10和14:44 |
0 15 10 ? * MON-FRI | 周一到周五的10:15 |
0 15 10 15 * ? | 每月15日的10:15 |
0 15 10 L * ? | 每月最后一天的10:15 |
0 15 10 L-2 * ? | 每月倒数第二天的10:15 |
0 15 10 ? * 6L | 每月最后一个周五的10:15 |
0 15 10 ? * 6L 2002-2005 | 从2002年至2005年期间每月最后一个周五的10:15 |
0 15 10 ? * 6#3 | 每月第三个周五的10:15 |
0 0 12 1/5 * ? | 从每月第一天开始,每隔5天的12:00 |
0 11 11 11 11 ? | 每年11月11日11:11 |
Quartz定时任务日志
通过日志记录定时计划的执行情况是很有用的,Quartz自身提供的Common.Logging来记录日志,我们也可以结合Log4net或者Nlog来实现定时任务的运行日志,当然也可以保存到数据库中,具体方法本文不再详细说明。
以上就是关于Quartz.Net开源计划调度框架的简单说明,更详细的内容请参考Quartz的官网
WebAPI中的定时处理-使用Quartz.Net的更多相关文章
- 引用:WebAPI中的定时处理-使用Quartz.Net
引用: https://blog.csdn.net/lordwish/article/details/78926252 主要是给自己做个记录,不用到处找,这篇文章写的很全,推荐 文中:在项目的Glob ...
- 定时调度框架Quartz随笔
最近项目中的定时批处理用到了quartz定时任务,在此记录下quartz的配置吧,一个小demo仅供参考,也方便自己今后复习! 下面直接来步骤吧! 一.首先,要搭起能让quartz正常运行的环境,至少 ...
- Spring中实现定时调度
1, 内容简介 所谓的定时调度,是指在无人值守的时候系统可以在某一时刻执行某些特定的功能采用的一种机制,对于传统的开发而言,定时调度的操作分为两种形式: 定时触发:到某一时间点上执行某些处理操作: ...
- 定时处理组件---Quartz.net
1.认识任务调度 所谓任务调度,就是以将业务区块任务化(即抽象成每一个独立的任务,执行每个任务便完成某种业务的需求).比如,我们有一个订单系统,现在有这样的一个需求,就是需要在某一时间点去扫描数据库, ...
- [源码分析] 定时任务调度框架 Quartz 之 故障切换
[源码分析] 定时任务调度框架 Quartz 之 故障切换 目录 [源码分析] 定时任务调度框架 Quartz 之 故障切换 0x00 摘要 0x01 基础概念 1.1 分布式 1.1.1 功能方面 ...
- Autofac - MVC/WebApi中的应用
Autofac前面写了那么多篇, 其实就是为了今天这一篇, Autofac在MVC和WebApi中的应用. 一.目录结构 先看一下我的目录结构吧, 搭了个非常简单的架构, IOC(web), IBLL ...
- WebAPI中无法获取Session对象的解决办法
在MVC的WebApi中默认是没有开启Session会话支持的.需要在Global中重写Init方法来指定会话需要支持的类型 public override void Init() { PostAut ...
- webapi 中的本地登录
WebApi 身份验证方式 asp.net WebApi 中有三种身份验证方式 个人用户账户.用户可以在网站注册,也可以使用 google, facebook 等外部服务登录. 工作和学校账户.使用活 ...
- webapi 中使用 protobuf
相比json来说,好处是速度更快,带宽占用更小.其效果大致等于json+Gzip. 在webapi中使用protobuf的方法为: 引用nuget包 Install-Package protobuf- ...
随机推荐
- Linux下利用Ant调用Jmeter脚本生成HTML测试报告
今天我们学习如何利用Ant调用Jmeter脚本,并将生成的 jtl 文件转换为 HTML 格式的测试报告. 准备工作 需要在Linux上提前安装好 JDK. Jmeter 和 Ant. 1,JDK(可 ...
- idea实现svn拉分支和合并分支的教程
原文地址:https://blog.csdn.net/qq_27471405/article/details/78498260 今天测试了一下svn拉分支和合并分支的教程,决定分享给大家 拉分支教程: ...
- 第一章001-003课程介绍、计算机网络概述、Internet概述
计算机网络概述 课程安排: 第一章:概述 第二章:物理层 第三章:数据链路层 第四章:网络层 第五章:运输层 第六章:应用层 第七章:网络安全 第八章:因特网上的音频/视频服务 第九章:无线网络 第十 ...
- Dynamics 365 CRM 在 Connected Field Service 中部署 IoT Central (一)- 配置 IoT Central和IoT alert
今天这个系列给大家带来怎样在connected field service中部署IoT Central 并且做连接. 首先, 这里提供微软官方的tutorial的链接https://docs.micr ...
- Linux Centos7 在桌面添加快捷方式
当时,刚刚安装好centos7,又下载好了jb家的软件,但是每一次都要用命令行才能运 我想要的是下面的效果,那是我后来才研究出来的 我看到了自动生成的为什么可以用,我的打开了源文件研究了一下 第一,先 ...
- CSS-11-外边距
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- js解析json时报:Unexpected token s in JSON at position 0
原因肯定是返回的json格式有问题 最有可能是后台在程序执行过程中,输出了某些调试信息等等,这些输出的字符串和json拼接成了新的字符串来解析,这时就会报错: 比如我在入口文件里var_dump了__ ...
- 使用typescript改造koa开发框架
强类型的 TypeScript 开发体验和维护项目上相比 JavaScript 有着明显的优势,那么对常用的脚手架进行改造也就势在必行了. 接下来开始对基于 koa 框架的 node 后端脚手架进行改 ...
- Maven: 每次更新Maven Project ,JAVA 版本都变为1.5
由于Maven默认编译环境是JAVA 1.5 ,所以我们需要在pom.xml指定编译插件版本号,这样就可以保证更新Maven project版本不变. <!-- java编译插件 --> ...
- python学习Day05--字典
[主要内容] 1. dict 用大括号{} 括起来. 内部使用key:value的形式来保存数据 {'jay':'周杰伦', "jj":'林俊杰'} 注意:字典的key必须是可哈希 ...