Quartz.Net系列(十六):通过Plugins模式使用Xml方式配置Job和Trigger和自定义LogPrivider
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的更多相关文章
- S3C2416裸机开发系列十六_sd卡驱动实现
S3C2416裸机开发系列十六 sd卡驱动实现 象棋小子 1048272975 SD卡(Secure Digital Memory Card)具有体积小.容量大.传输数据快.可插拔.安全性好等长 ...
- MVVM模式解析和在WPF中的实现(六) 用依赖注入的方式配置ViewModel并注册消息
MVVM模式解析和在WPF中的实现(六) 用依赖注入的方式配置ViewModel并注册消息 系列目录: MVVM模式解析和在WPF中的实现(一)MVVM模式简介 MVVM模式解析和在WPF中的实现(二 ...
- Spring系列之aAOP AOP是什么?+xml方式实现aop+注解方式实现aop
Spring系列之aop aop是什么?+xml方式实现aop+注解方式实现aop 什么是AOP? AOP为Aspect Oriented Programming 的缩写,意识为面向切面的编程,是通过 ...
- 学习ASP.NET Core Razor 编程系列十六——排序
学习ASP.NET Core Razor 编程系列目录 学习ASP.NET Core Razor 编程系列一 学习ASP.NET Core Razor 编程系列二——添加一个实体 学习ASP.NET ...
- 为什么不让用join?《死磕MySQL系列 十六》
大家好,我是咔咔 不期速成,日拱一卒 在平时开发工作中join的使用频率是非常高的,很多SQL优化博文也让把子查询改为join从而提升性能,但部分公司的DBA又不让用,那么使用join到底有什么问题呢 ...
- Spring Boot2 系列教程(十六)定时任务的两种实现方式
在 Spring + SpringMVC 环境中,一般来说,要实现定时任务,我们有两中方案,一种是使用 Spring 自带的定时任务处理器 @Scheduled 注解,另一种就是使用第三方框架 Qua ...
- 十六、Spring Boot 部署与服务配置
spring Boot 其默认是集成web容器的,启动方式由像普通Java程序一样,main函数入口启动.其内置Tomcat容器或Jetty容器,具体由配置来决定(默认Tomcat).当然你也可以将项 ...
- SpringBoot填坑系列---XML方式配置数据库
本次只是简单的运用SpringBoot搭建框架,对其原理并不做深入的探究 1.POM文件 <?xml version="1.0" encoding="UTF-8&q ...
- webpack4 系列教程(十六):开发模式和生产模式·实战
好文章 https://www.jianshu.com/p/f2d30d02b719
随机推荐
- foreach 集合又抛经典异常了,这次一定要刨根问底
一:背景 1. 讲故事 最近同事在写一段业务逻辑的时候,程序跑起来总是报:集合已修改:可能无法执行枚举操作,硬是没有找到什么情况下会导致这个异常产生,就让我来找一下bug,其实这个异常在座的每个程序员 ...
- WPF入门(2)——依赖属性
今天我们说说依赖属性 什么是依赖属性? 当然,学术定义依旧Please Baidu:https://baike.baidu.com/item/%E4%BE%9D%E8%B5%96%E5%B1%9E%E ...
- 【Python爬虫】HTTP基础和urllib库、requests库的使用
引言: 一个网络爬虫的编写主要可以分为三个部分: 1.获取网页 2.提取信息 3.分析信息 本文主要介绍第一部分,如何用Python内置的库urllib和第三方库requests库来完成网页的获取.阅 ...
- Beta冲刺--项目测试
这个作业属于哪个课程 软件工程 (福州大学至诚学院 - 计算机工程系) 这个作业要求在哪里 Beta 冲刺 这个作业的目标 Beta冲刺--项目测试 作业正文 如下 其他参考文献 ... Beta冲刺 ...
- 并发编程-CPU执行volatile原理探讨-可见性与原子性的深入理解
volatile的定义 Java语言规范第3版中对volatile的定义如下:Java编程语言允许线程访问共享变量,为了确保共享变量能被准确和一致地更新,线程应该确保通过排他锁单独获得这个变量.Jav ...
- .net core 静态类获取appsettings
注入获取 通过IConfiguration直接获取的方法官方文档里就有,可以直接看这里 如:appsettings.json { "Position": { "Title ...
- 入门大数据---Hbase是什么?
一.Hbase是什么? Hbase属于NoSql的一种. NoSql数据库分为如下几类: Key-Value类型数据库 这类数据库主要会使用到一个哈希表,这个表有一个特定的键和一个指针指向特定的数据. ...
- 入门大数据---Redis集群分布式学习
Redis是什么? 官方介绍: Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库.缓存和消息中间件. 它支持多种类型的数据结构,如 字符串(strings), 散列( ...
- 重学 Java 设计模式:实战中介者模式「按照Mybaits原理手写ORM框架,给JDBC方式操作数据库增加中介者场景」
作者:小傅哥 博客:https://bugstack.cn - 原创系列专题文章 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 同龄人的差距是从什么时候拉开的 同样的幼儿园.同样的小学.一样 ...
- could not resolve property(无法解析属性)
could not resolve property(无法解析属性) 顾名思义在写hql语句的时候,属性写错了! 请检查大小写,是实体类的,不是数据库表的! 一个一个检查,仔细看!