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
随机推荐
- MyBatis 实体类属性与表字段不一致
原文链接:https://blog.csdn.net/zx48822821/java/article/details/79050735 因为数据库一般设置为表的字段不区分大小写,所以数据库中表的字段通 ...
- PyCharm远程连接服务器简明教程
转自本人知乎(https://zhuanlan.zhihu.com/p/149040742) 由于实验室的GPU都是放在远程服务器上,因此一直使用MobaXterm利用SSH远程跑实验,但是MobaX ...
- JavaWeb网上图书商城完整项目--day02-9.提交注册表单功能之servlet层实现
1.当用户在界面提交注册提交的时候,我们在UerServlet来实现具体的业务方法 标准demo: 1CommonUtils CommonUtils类就两个方法: lString uuid():生成长 ...
- 数据库char varchar nchar nvarchar,编码Unicode,UTF8,GBK等,Sql语句中文前为什么加N(一次线上数据存储乱码排查)
背景 公司有一个数据处理线,上面的数据经过不同环境处理,然后上线到正式库.其中一个环节需要将数据进行处理然后导入到另外一个库(Sql Server).这个处理的程序是老大用python写的,处理完后进 ...
- java多线程并发执行demo,主线程阻塞
其中有四个知识点我单独罗列了出来,属于多线程编程中需要知道的知识: 知识点1:X,T为泛型,为什么要用泛型,泛型和Object的区别请看:https://www.cnblogs.com/xiaoxio ...
- Ubuntu图形界面root登录出现“sorry, that didn't work please try again”
ssh登录主机执行下vim /etc/pam.d/gdm-autologin 注释行 "auth requied pam_succeed_if.so user != root quiet s ...
- vue的生命函数周期以及钩子函数的详解
首先我们先附上官网的图 图中展现出的是vue整个生命周期以及钩子函数 1- beforeCreate(创建前) 2- created(创建完成) 3- beforeMount(挂载前) 4- mo ...
- Python基础语法一
所有内容都在代码上,有相关代码注释 # #代表注释 # 区分大小写.以回车换行结束 # 多行编写可以使用反斜杠 \ # 缩进代表一个代码块 #数值 #int类型可以使用下划线分割 c=123_456_ ...
- 自定义Springboot全局异常类
一.简要说明 如何实现网上文章基本是随便一搜就可以很快找到, 这里不再赘述. 二.Spring-web和Spring-webmvc 通过idea查看到两个注解位于 spring-web-5.2.2.R ...
- mac下创建安卓应用 hello-world
教程 https://www.jianshu.com/p/bf77cb5ce70b 需要注意的地方 jdk目录查找 jdk目录拷贝到tool目录下面(jdk可以拷贝,没有其他牵扯) https://w ...