1.简单介绍

Quarz.Net中采用插件式来实现配置文件配置,通过XMLSchedulingDataProcessor类进行Xml数据处理

默认配置文件命名:quart_jobs.xml

public const string QuartzXmlFileName = "quartz_jobs.xml";

2.创建配置

首先安装扩展程序:Liquid XML Objects(基于XML的xsd文件创建数据模型)

 新建quartz_jobs.xml文件,选择XML=>Schemas 

 Add

 quartz_jobs.xml

<?xml version="1.0" encoding="utf-8" ?>
<job-scheduling-data xmlns="http://quartznet.sourceforge.net/JobSchedulingData">
<processing-directives>
<overwrite-existing-data>true</overwrite-existing-data>
</processing-directives> <schedule>
<job>
<name>myJob</name>
<group>aaron</group>
<description>这是Xml定义的Job</description>
<job-type>Quartz_Demo.MyJob,Quartz_Demo</job-type>
<durable>true</durable>
<recover>true</recover>
<job-data-map>
<entry>
<key>myKey</key>
<value>myValue</value>
</entry>
</job-data-map>
</job>
<trigger>
<simple>
<name>myTrigger</name>
<description>这是Xml定义的Trigger</description>
<job-name>myJob</job-name>
<job-group>aaron</job-group>
<repeat-count>-1</repeat-count>
<repeat-interval>1000</repeat-interval>
</simple>
</trigger>
</schedule>
</job-scheduling-data>

安装Quartz.Plugins包

编写代码

            var assemblyName = typeof(Quartz.Plugin.Xml.XMLSchedulingDataProcessorPlugin).AssemblyQualifiedName;

            var scheduler= await SchedulerBuilder.Create().UseXmlSchedulingConfiguration((options)=>{
options.SetProperty("quartz.plugin.xml.fileNames", "quartz_jobs.xml");
options.SetProperty("quartz.plugin.xml.scanInterval", "");
options.SetProperty("quartz.threadPool.threadCount", "");
}).Build(); //System.Collections.Specialized.NameValueCollection collection = new System.Collections.Specialized.NameValueCollection(); //collection.Add("quartz.plugin.xml.type", assemblyName); //collection.Add("quartz.plugin.xml.fileNames","quartz_jobs.xml"); //collection.Add("quartz.plugin.xml.scanInterval", "10"); //var factory = new StdSchedulerFactory(collection); //var scheduler = await factory.GetScheduler(); LogProvider.SetCurrentLogProvider(new ConsoleLogProvider()); await scheduler.Start(); var metaData=await scheduler.GetMetaData(); Console.WriteLine(metaData.ThreadPoolSize);

自定义LogPrivider

    public class ConsoleLogProvider : ILogProvider
{
public Logger GetLogger(string name)
{
Logger loger = (logLevel, messageFunc, exception, formatParameters) =>
{
if (logLevel >= LogLevel.Debug && messageFunc != null)
{
Console.WriteLine("[" + DateTime.Now.ToLongTimeString() + "] [" + logLevel + "] " + messageFunc(), formatParameters);
}
return true;
}; return loger;
} public IDisposable OpenMappedContext(string key, object value, bool destructure = false)
{
return null;
} public IDisposable OpenNestedContext(string message)
{
return null;
}
}

运行图

 源码解析

 foreach (jobdetailType jobDetailType in jobNodes)
{
string jobName = jobDetailType.name.TrimEmptyToNull();
string jobGroup = jobDetailType.group.TrimEmptyToNull();
string jobDescription = jobDetailType.description.TrimEmptyToNull();
string jobTypeName = jobDetailType.jobtype.TrimEmptyToNull();
bool jobDurability = jobDetailType.durable;
bool jobRecoveryRequested = jobDetailType.recover; Type jobType = TypeLoadHelper.LoadType(jobTypeName); IJobDetail jobDetail = JobBuilder.Create(jobType)
.WithIdentity(jobName, jobGroup)
.WithDescription(jobDescription)
.StoreDurably(jobDurability)
.RequestRecovery(jobRecoveryRequested)
.Build(); if (jobDetailType.jobdatamap != null && jobDetailType.jobdatamap.entry != null)
{
foreach (entryType entry in jobDetailType.jobdatamap.entry)
{
string key = entry.key.TrimEmptyToNull();
string value = entry.value.TrimEmptyToNull();
jobDetail.JobDataMap.Add(key, value);
}
} if (Log.IsDebugEnabled())
{
Log.Debug("Parsed job definition: " + jobDetail);
} AddJobToSchedule(jobDetail);
} //
// Extract Trigger definitions...
// List<triggerType> triggerEntries = new List<triggerType>();
if (data.schedule != null)
{
foreach (var schedule in data.schedule)
{
if (schedule != null && schedule.trigger != null)
{
triggerEntries.AddRange(schedule.trigger);
}
}
} Log.Debug("Found " + triggerEntries.Count + " trigger definitions."); foreach (triggerType triggerNode in triggerEntries)
{
string triggerName = triggerNode.Item.name.TrimEmptyToNull();
string triggerGroup = triggerNode.Item.group.TrimEmptyToNull();
string triggerDescription = triggerNode.Item.description.TrimEmptyToNull();
string triggerCalendarRef = triggerNode.Item.calendarname.TrimEmptyToNull();
string triggerJobName = triggerNode.Item.jobname.TrimEmptyToNull();
string triggerJobGroup = triggerNode.Item.jobgroup.TrimEmptyToNull(); int triggerPriority = TriggerConstants.DefaultPriority;
if (!triggerNode.Item.priority.IsNullOrWhiteSpace())
{
triggerPriority = Convert.ToInt32(triggerNode.Item.priority);
} DateTimeOffset triggerStartTime = SystemTime.UtcNow();
if (triggerNode.Item.Item != null)
{
if (triggerNode.Item.Item is DateTime time)
{
triggerStartTime = new DateTimeOffset(time);
}
else
{
triggerStartTime = triggerStartTime.AddSeconds(Convert.ToInt32(triggerNode.Item.Item));
}
} DateTime? triggerEndTime = triggerNode.Item.endtimeSpecified ? triggerNode.Item.endtime : (DateTime?) null; IScheduleBuilder sched; if (triggerNode.Item is simpleTriggerType simpleTrigger)
{
string repeatCountString = simpleTrigger.repeatcount.TrimEmptyToNull();
string repeatIntervalString = simpleTrigger.repeatinterval.TrimEmptyToNull(); int repeatCount = ParseSimpleTriggerRepeatCount(repeatCountString);
TimeSpan repeatInterval = repeatIntervalString == null ? TimeSpan.Zero : TimeSpan.FromMilliseconds(Convert.ToInt64(repeatIntervalString)); sched = SimpleScheduleBuilder.Create()
.WithInterval(repeatInterval)
.WithRepeatCount(repeatCount); if (!simpleTrigger.misfireinstruction.IsNullOrWhiteSpace())
{
((SimpleScheduleBuilder) sched).WithMisfireHandlingInstruction(ReadMisfireInstructionFromString(simpleTrigger.misfireinstruction));
}
}
else if (triggerNode.Item is cronTriggerType)
{
cronTriggerType cronTrigger = (cronTriggerType) triggerNode.Item;
string cronExpression = cronTrigger.cronexpression.TrimEmptyToNull();
string timezoneString = cronTrigger.timezone.TrimEmptyToNull(); TimeZoneInfo tz = timezoneString != null ? TimeZoneUtil.FindTimeZoneById(timezoneString) : null;
sched = CronScheduleBuilder.CronSchedule(cronExpression)
.InTimeZone(tz); if (!cronTrigger.misfireinstruction.IsNullOrWhiteSpace())
{
((CronScheduleBuilder) sched).WithMisfireHandlingInstruction(ReadMisfireInstructionFromString(cronTrigger.misfireinstruction));
}
}
else if (triggerNode.Item is calendarIntervalTriggerType)
{
calendarIntervalTriggerType calendarIntervalTrigger = (calendarIntervalTriggerType) triggerNode.Item;
string repeatIntervalString = calendarIntervalTrigger.repeatinterval.TrimEmptyToNull(); IntervalUnit intervalUnit = ParseDateIntervalTriggerIntervalUnit(calendarIntervalTrigger.repeatintervalunit.TrimEmptyToNull());
int repeatInterval = repeatIntervalString == null ? : Convert.ToInt32(repeatIntervalString); sched = CalendarIntervalScheduleBuilder.Create()
.WithInterval(repeatInterval, intervalUnit); if (!calendarIntervalTrigger.misfireinstruction.IsNullOrWhiteSpace())
{
((CalendarIntervalScheduleBuilder) sched).WithMisfireHandlingInstruction(ReadMisfireInstructionFromString(calendarIntervalTrigger.misfireinstruction));
}
}
else
{
throw new SchedulerConfigException("Unknown trigger type in XML configuration");
} IMutableTrigger trigger = (IMutableTrigger) TriggerBuilder.Create()
.WithIdentity(triggerName, triggerGroup)
.WithDescription(triggerDescription)
.ForJob(triggerJobName, triggerJobGroup)
.StartAt(triggerStartTime)
.EndAt(triggerEndTime)
.WithPriority(triggerPriority)
.ModifiedByCalendar(triggerCalendarRef)
.WithSchedule(sched)
.Build(); if (triggerNode.Item.jobdatamap != null && triggerNode.Item.jobdatamap.entry != null)
{
foreach (entryType entry in triggerNode.Item.jobdatamap.entry)
{
string key = entry.key.TrimEmptyToNull();
string value = entry.value.TrimEmptyToNull();
trigger.JobDataMap.Add(key, value);
}
} if (Log.IsDebugEnabled())
{
Log.Debug("Parsed trigger definition: " + trigger);
} AddTriggerToSchedule(trigger);
}

Quartz.Net系列(十六):通过Plugins模式使用Xml方式配置Job和Trigger和自定义LogPrivider的更多相关文章

  1. S3C2416裸机开发系列十六_sd卡驱动实现

    S3C2416裸机开发系列十六 sd卡驱动实现 象棋小子    1048272975 SD卡(Secure Digital Memory Card)具有体积小.容量大.传输数据快.可插拔.安全性好等长 ...

  2. MVVM模式解析和在WPF中的实现(六) 用依赖注入的方式配置ViewModel并注册消息

    MVVM模式解析和在WPF中的实现(六) 用依赖注入的方式配置ViewModel并注册消息 系列目录: MVVM模式解析和在WPF中的实现(一)MVVM模式简介 MVVM模式解析和在WPF中的实现(二 ...

  3. Spring系列之aAOP AOP是什么?+xml方式实现aop+注解方式实现aop

    Spring系列之aop aop是什么?+xml方式实现aop+注解方式实现aop 什么是AOP? AOP为Aspect Oriented Programming 的缩写,意识为面向切面的编程,是通过 ...

  4. 学习ASP.NET Core Razor 编程系列十六——排序

    学习ASP.NET Core Razor 编程系列目录 学习ASP.NET Core Razor 编程系列一 学习ASP.NET Core Razor 编程系列二——添加一个实体 学习ASP.NET ...

  5. 为什么不让用join?《死磕MySQL系列 十六》

    大家好,我是咔咔 不期速成,日拱一卒 在平时开发工作中join的使用频率是非常高的,很多SQL优化博文也让把子查询改为join从而提升性能,但部分公司的DBA又不让用,那么使用join到底有什么问题呢 ...

  6. Spring Boot2 系列教程(十六)定时任务的两种实现方式

    在 Spring + SpringMVC 环境中,一般来说,要实现定时任务,我们有两中方案,一种是使用 Spring 自带的定时任务处理器 @Scheduled 注解,另一种就是使用第三方框架 Qua ...

  7. 十六、Spring Boot 部署与服务配置

    spring Boot 其默认是集成web容器的,启动方式由像普通Java程序一样,main函数入口启动.其内置Tomcat容器或Jetty容器,具体由配置来决定(默认Tomcat).当然你也可以将项 ...

  8. SpringBoot填坑系列---XML方式配置数据库

    本次只是简单的运用SpringBoot搭建框架,对其原理并不做深入的探究 1.POM文件 <?xml version="1.0" encoding="UTF-8&q ...

  9. webpack4 系列教程(十六):开发模式和生产模式·实战

    好文章 https://www.jianshu.com/p/f2d30d02b719

随机推荐

  1. 【Java入门】JDK安装和环境变量配置(Win7版)

    系统环境:Windows7 x64 安装JDK和JRE版本:1.8.0_191 1.下载JDK安装包 Oracle官网下载网址:https://www.oracle.com/technetwork/j ...

  2. 数据库语言sql

    数据库语言SQL SQL的形式 交互式SQL 一般DBMS都提供联机交互工具 用户可直接键入SQL命令对数据库进行操作 由DBMS来进行解释 嵌入式SQL 能将SQL语句嵌入到高级语言(宿主语言) 使 ...

  3. 对 JsonConvert 的认识太肤浅了,终于还是遇到了问题

    一:背景 1. 讲故事 在开始本文之前,真的好想做个问卷调查,到底有多少人和我一样,对 JsonConvert 的认识只局限在 SerializeObject 和 DeserializeObject ...

  4. 手把手教你使用Python抓取QQ音乐数据(第一弹)

    [一.项目目标] 获取 QQ 音乐指定歌手单曲排行指定页数的歌曲的歌名.专辑名.播放链接. 由浅入深,层层递进,非常适合刚入门的同学练手. [二.需要的库] 主要涉及的库有:requests.json ...

  5. redis高级命令1

    设置name的过期时间是20秒 redis默认是16个数据库,默认是将数据存储在第0个数据库中 因为默认是0,当你选择其他数据的时候,是没有值的

  6. cookie,session,jwt,token,oauth2联系和区别

    为啥有这么多的东西? 由于互联网在刚开始设计的时候是展现静态网页为主,没有现在这么多的交互和互动,所以被设计为了无状态,随用随走的简单模式.随着互联网的发展,各种具有和用户交互功能的网站出现,要求用户 ...

  7. jvm入门及理解(六)——垃圾回收与算法

    一.jvm垃圾回收要做的事情 哪些内存需要回收 什么时候回收 怎么回收 二.如何判断对象已经死亡,或者说确定为垃圾 引用计数法: 给对象中添加一个引用计数器,每当有一个地方引用它时,计数器的值就加1: ...

  8. 入门大数据---通过Yarn搭建MapReduce和应用实例

    上一篇中我们了解了MapReduce和Yarn的基本概念,接下来带领大家搭建下Mapreduce-HA的框架. 结构图如下: 开始搭建: 一.配置环境 注:可以现在一台计算机上进行配置,然后分发给其它 ...

  9. SQL运行内幕:从执行原理看调优的本质

    相信大家看过无数的MySQL调优经验贴了,会告诉你各种调优手段,如: 避免 select *: join字段走索引: 慎用in和not in,用exists取代in: 避免在where子句中对字段进行 ...

  10. vue全家桶(2.7)

    3.11.1.vue-router中的全局钩子函数 在vue-router中,路由发生变化,我们可以做一些事情,例如:可以决定是否进入导航,可以决定跳转到哪里,官方文档中又叫做导航守卫 首先来看一个全 ...