将定时任务信息存储在XML文件中,使用反射加载定时任务

首先新建一个MVC的空站点,使用NuGet添加对Quartz.net和Common.Logging.Log4Net1213的引用,同时使用NuGet管理器控制台执行命令更新log4net,PM> update-package log4net

接着在解决方案中添加一个类库Library项目

类库项目也添加对Quartz.net的引用

下面可以编写代码了,在Library类库中添加一个JobBase类,3个Job类,和一个Job管理类(假设分别取名:JobBase.cs,HelloJob.cs,AnotherJob.cs,ParameterJob.cs,JobManage.cs)

注:HelloJob、AnotherJob、ParameterJob都是任务类继承自JobBase并实现IJob接口

它们的代码分别如下:

1、JobBase.cs

using Common.Logging;

namespace JobLibrary
{
public class JobBase
{
/// <summary>
/// JOB状态日志
/// </summary>
protected internal static readonly ILog jobStatus = LogManager.GetLogger("JobLogAppender"); /// <summary>
/// 服务错误日志
/// </summary>
protected internal static readonly ILog serviceErrorLog = LogManager.GetLogger("JobLogAppender");
}
}

折叠展开

2、HelloJob.cs

using Quartz;

namespace JobLibrary
{
public class HelloJob:JobBase,IJob
{
public void Execute(IJobExecutionContext context)
{
try
{
MyExecMethod();
}
catch (Exception ex)
{
serviceErrorLog.Info(string.Concat("HelloJob执行出错:", ex.StackTrace));
}
} public void MyExecMethod()
{
jobStatus.Info("我正在执行HelloJob的代码,此为测试,只是写日志");
}
}
}

折叠展开

3、AnotherJob.cs

using Quartz;

namespace JobLibrary
{
public class AnotherJob:JobBase,IJob
{
public void Execute(IJobExecutionContext context)
{
try
{
DoSomething();
}
catch (Exception ex)
{
serviceErrorLog.Info(string.Concat("AnotherJob执行出错:", ex.StackTrace));
}
} public void DoSomething()
{
jobStatus.Info("我正在执行AnotherJob的代码,此为测试,只是写日志");
}
}
}

折叠展开

4、ParameterJob.cs (传参数到Job中)

using Quartz;

namespace JobLibrary
{
public class ParameterJob:JobBase,IJob
{
private static int a = ; public void Execute(IJobExecutionContext context)
{
try
{
if (!context.JobDetail.JobDataMap.Contains("a")) //判断是否有a参数
{
context.JobDetail.JobDataMap.Add("a", a);
}
else
{
context.JobDetail.JobDataMap["a"] = a;
} DoSomething();
jobStatus.Info("a=" + a); //打印a的值
a++;
}
catch (Exception ex)
{
serviceErrorLog.Info(string.Concat("ParameterJob执行出错:", ex.StackTrace));
}
} public void DoSomething()
{
jobStatus.Info("我正在执行ParameterJob的代码,此为测试,只是写日志");
}
}
}

折叠展开

5、JobManage.cs

说明:JobManage相当于一个助手类,本来应该和上面的任务类分开单独放在另一类库中,

为了不增加额外的代码就放在一起了(因为使用反射加载Job,相当于所有的任务和Web应用程序是可以隔离开的)

using Common.Logging;
using Quartz;
using Quartz.Impl;
using System.Xml.Linq;
using System.IO;
using Quartz.Impl.Triggers;
using System.Reflection; namespace JobLibrary
{
public class JobManage
{
private static ISchedulerFactory sf = new StdSchedulerFactory();
private static IScheduler scheduler;
static readonly ILog errorLog = LogManager.GetLogger("JobLogAppender"); //开启定时器
public static void StartScheduleFromConfig()
{
string currentDir = AppDomain.CurrentDomain.BaseDirectory;
try
{
string dllPath = Path.Combine(currentDir, "JobScheduler.config"); //定时任务信息的配置文件
XDocument xDoc = XDocument.Load(dllPath);
var jobScheduler = from x in xDoc.Descendants("JobScheduler") select x; var jobs = jobScheduler.Elements("Job");
XElement jobDetailXElement, triggerXElement; scheduler = sf.GetScheduler(); //StdSchedulerFactory工厂取得一个默认的调度器 CronTriggerImpl cronTrigger; foreach (var job in jobs)
{
//加载程序集joblibaray (反射加载应用程序bin目录下的JobLibrary.dll)
Assembly ass = Assembly.LoadFrom(Path.Combine(currentDir + "\\bin\\", job.Element("DllName").Value)); jobDetailXElement = job.Element("JobDetail"); //Job的Detail信息
triggerXElement = job.Element("Trigger"); //Job的触发器信息 JobDetailImpl jobDetail = new JobDetailImpl(jobDetailXElement.Attribute("job").Value,
jobDetailXElement.Attribute("group").Value,
ass.GetType(jobDetailXElement.Attribute("jobtype").Value)); if (triggerXElement.Attribute("type").Value.Equals("CronTrigger"))
{
cronTrigger = new CronTriggerImpl(triggerXElement.Attribute("name").Value,
triggerXElement.Attribute("group").Value,
triggerXElement.Attribute("expression").Value);
scheduler.ScheduleJob(jobDetail, cronTrigger);
}
}
//开启定时器
scheduler.Start();
}
catch (Exception e)
{
errorLog.Error(e.StackTrace);
}
} //关闭定时器
public static void ShutDown()
{
if (scheduler != null && !scheduler.IsShutdown)
{
scheduler.Shutdown();
}
} /**
* 修改任务的执行周期
*/
public static void ModifyJobTime(string jobKey,string jobGroup,string triggerKey,string triggerGroup, String time)
{
try
{
//获取trigger
TriggerKey triKey = new TriggerKey(triggerKey, triggerGroup);
ITrigger trigger = scheduler.GetTrigger(triKey); //表达式调度构造器
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.CronSchedule(time); //按新的cronExpression表达式重新构建trigger
trigger = trigger.GetTriggerBuilder().WithIdentity(triggerKey).WithSchedule(scheduleBuilder).Build(); //按新的trigger重新设置job执行
scheduler.RescheduleJob(triKey, trigger);
}
catch (Exception e)
{
errorLog.Error(e.StackTrace);
}
}
}
}

折叠展开

接下来和02笔记一样:

1、Web应用程序添加对JobLibrary的引用

2、配置好Web.config文件

<configSections>
<!--配置Common.Logging节点-->
<sectionGroup name="common">
<section name="logging" type="Common.Logging.ConfigurationSectionHandler, Common.Logging" />
</sectionGroup>
<!--Log4net-->
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
</configSections>
<common>
<logging>
<!--1.此Adapter只输出到控制台,如果是用的控制台,用这个输出-->
<!--
<factoryAdapter type="Common.Logging.Simple.ConsoleOutLoggerFactoryAdapter, Common.Logging">
<arg key="level" value="INFO" />
<arg key="showLogName" value="true" />
<arg key="showDataTime" value="true" />
<arg key="dateTimeFormat" value="yyyy/MM/dd HH:mm:ss:fff" />
</factoryAdapter>-->
<!--2.此Adapter只输出到Log4.net的配置文件所指定的地方-->
<factoryAdapter type="Common.Logging.Log4Net.Log4NetLoggerFactoryAdapter, Common.Logging.Log4Net1213">
<!--FILE,FILE-WATCH,INLINE,EXTERNAL-->
<arg key="configType" value="FILE" />
<arg key="configFile" value="~/log4net.config" />
<!-- 指定log4net的配置文件名称 -->
<arg key="level" value="Warn" />
</factoryAdapter>
</logging>
</common>

折叠展开

3、增加log4net.config配置文件

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
</configSections>
<appSettings>
</appSettings>
<log4net>
<!--定义输出到文件中-->
<appender name="JobLogAppender" type="log4net.Appender.RollingFileAppender">
<!--输出日志文件的路径-->
<file value="Log\XXLog.log" />
<!--输出日志时自动向后追加-->
<appendToFile value="true" />
<!--防止多线程时不能写Log,官方说线程非安全,但实际使用时,本地测试正常,部署后有不能写日志的情况-->
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
<!--置为true,当前最新日志文件名永远为file节中的名字-->
<staticLogFileName value="false" />
<!--日志以大小作为备份样式,还有一种方式是Date(日期)-->
<rollingStyle value="size" />
<countDirection value="-1" />
<!--单个日志的最大容量,(可用的单位:KB|MB|GB)不要使用小数,否则会一直写入当前日志-->
<maximumFileSize value="1MB" />
<!--日志最大个数,都是最新的-->
<maxSizeRollBackups value="10" />
<datePattern value='"."yyyy-MM-dd".log"' />
<layout type="log4net.Layout.PatternLayout">
<!--每条日志末尾的文字说明-->
<footer value="**************************************************************" />
<!--输出格式-->
<!--样例:2008-03-26 13:42:32,111 [10] INFO Log4NetDemo.MainClass - info-->
<conversionPattern value="%newline%d{yyyy/MM/dd,HH:mm:ss.fff},[%-5level] Message:%message%newline" />
</layout>
</appender>
<root>
<!--文件形式记录日志-->
<appender-ref ref="JobLogAppender" />
<level value="INFO"></level>
</root>
</log4net>
</configuration>

折叠展开

4、添加JobScheduler.config任务的配置文件

<?xml version="1.0" encoding="utf-8" ?>
<JobScheduler>
<Job Description="作业1">
<DllName>JobLibrary.dll</DllName>
<JobDetail job="HelloJob" group="HelloGroup" jobtype="JobLibrary.HelloJob" />
<Trigger name="HelloJob" group="HelloGroup" type="CronTrigger" expression="0/10 * * * * ?" />
</Job>
<Job Description="作业2">
<DllName>JobLibrary.dll</DllName>
<JobDetail job="Another" group="AnotherGroup" jobtype="JobLibrary.AnotherJob" />
<Trigger name="Another" group="AnotherGroup" type="CronTrigger" expression="0/5 * * * * ?" />
</Job>
<Job Description="作业3">
<DllName>JobLibrary.dll</DllName>
<JobDetail job="Parameter" group="ParameterGroup" jobtype="JobLibrary.ParameterJob" />
<Trigger name="Parameter" group="ParameterGroup" type="CronTrigger" expression="0/3 * * * * ?" />
</Job>
</JobScheduler>

折叠展开

5、添加HomeController以前Index方法的视图

程序最后的目录结构:

最后修改Global.asax文件代码:

using JobLibrary;

namespace Quartz003
{
// 注意: 有关启用 IIS6 或 IIS7 经典模式的说明,
// 请访问 http://go.microsoft.com/?LinkId=9394801
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas(); WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes); //启动定时任务
JobManage.StartScheduleFromConfig();
} protected void Application_End(object sender, EventArgs e)
{
//关闭定时任务
JobManage.ShutDown();
}
}
}

折叠展开

编译运行应用程序,找到应用程序目录Log文件夹下的XXLog.log文件

源码下载(微云)

Quartz.net 2.x 学习笔记03-使用反射加载定时任务的更多相关文章

  1. [置顶] iOS学习笔记47——图片异步加载之EGOImageLoading

    上次在<iOS学习笔记46——图片异步加载之SDWebImage>中介绍过一个开源的图片异步加载库,今天来介绍另外一个功能类似的EGOImageLoading,看名字知道,之前的一篇学习笔 ...

  2. Flutter学习笔记(19)--加载本地图片

    如需转载,请注明出处:Flutter学习笔记(19)--加载本地图片 上一篇博客正好用到了本地的图片,记录一下用法: 首先新建一个文件夹,这个文件夹要跟目录下 然后在pubspec.yaml里面声明出 ...

  3. XV6学习笔记(1) : 启动与加载

    XV6学习笔记(1) 1. 启动与加载 首先我们先来分析pc的启动.其实这个都是老生常谈了,但是还是很重要的(也不知道面试官考不考这玩意), 1. 启动的第一件事-bios 首先启动的第一件事就是运行 ...

  4. [OpenCV学习笔记3][图像的加载+修改+显示+保存]

    正式进入OpenCV学习了,前面开始的都是一些环境搭建和准备工作,对一些数据结构的认识主要是Mat类的认识: [1.学习目标] 图像的加载:imread() 图像的修改:cvtColor() 图像的显 ...

  5. vue.js学习笔记(二):如何加载本地json文件

    在项目开发的过程中,因为无法和后台的数据做交互,所以我们可以自建一个假数据文件(如data.json)到项目文件夹中,这样我们就可以模仿后台的数据进行开发.但是,如何在一个vue.js 项目中引入本地 ...

  6. 【OpenCV学习笔记之一】图像加载,修改及保存

    加载图像(用cv::imread)imread功能是加载图像文件成为一个Mat对象 其中第一个参数表示图像文件名称第二个参数 表示加载的图像是什么类型 支持常见的三个参数值IMREAD_UNCHANG ...

  7. WMS学习笔记:1.尝试加载WMS

    1.首先找一个可用的WMS栅格地图服务:http://demo.cubewerx.com/demo/cubeserv/cubeserv.cgi 获取GetCapabilities: http://de ...

  8. Android学习笔记_51_转android 加载大图片防止内存溢出

    首先来还原一下堆内存溢出的错误.首先在SD卡上放一张照片,分辨率为(3776 X 2520),大小为3.88MB,是我自己用相机拍的一张照片.应用的布局很简单,一个Button一个ImageView, ...

  9. Android学习笔记_36_ListView数据异步加载与AsyncTask

    一.界面布局文件: 1.加入sdcard写入和网络权限: <!-- 访问internet权限 --> <uses-permission android:name="andr ...

随机推荐

  1. C语言查找算法之顺序查找、二分查找(折半查找)

    C语言查找算法之顺序查找.二分查找(折半查找),最近考试要用到,网上也有很多例子,我觉得还是自己写的看得懂一些. 顺序查找 /*顺序查找 顺序查找是在一个已知无(或有序)序队列中找出与给定关键字相同的 ...

  2. PermutationsUnique,求全排列,去重

    问题描述:给定一个数组,数组里面有重复元素,求全排列. 算法分析:和上一道题一样,只不过要去重. import java.util.ArrayList; import java.util.HashSe ...

  3. C-RAN

    无线接入网(RAN)是移动运营商赖以生存的重要资产.传统的无线接入网具有以下特点: 1. 每一个基站连接若干个固定数量的扇区天线,并覆盖小片区域,每个基站只能处理本小区收发信号: 2. 系统的容量是干 ...

  4. Maven添加Oracle驱动及依赖

    oracle驱动先去官网下载,下载下来后,需要安装到maven本地仓库,然后再pom中添加依赖. 1下载oracle驱动包 ojdbc6-11.2.0.3.jar 2命令行安装到maven仓库 mvn ...

  5. app下载——js设备判断

    摘自:今日头条<!doctype html> <html lang="en"> <head> <meta charset="UT ...

  6. php超级全局变量和魔术变量

    php超级全局变量和魔术变量 一.总结 一句话总结: 1.两者的书写形式非常不一样,超级全局变量是$_大写变量名 的形式,魔术变量是 __大写变量名的形式__ 2.两者的应用范围不一样,超级全局变量是 ...

  7. 【scala】匿名函数和闭包

    函数的类型和值 Scala是一种纯面向对象的语言,每个值都是对象.Java是一种不全面向对象的语言. Scala也是一种函数式语言,其函数也能当成值来使用.Java则是指令试编程. 但是Scala同时 ...

  8. Activity传递参数——传递复杂数据(Bunble包)

    一.新建一个空的工程 二.在主界面中添加一个按钮 三.新建一个空的activity,并命名为TheAty 四.修改MainActivity.java中的onCreate函数 protected voi ...

  9. Drools7.0.0.Final Unsupported major.minor version 52.0异常

    异常信息 在使用Drools7.0.0.Final版本进行开发过程中,出现以下异常: java.lang.UnsupportedClassVersionError: org/kie/api/KieSe ...

  10. 使用 DocFX 生成 .Net/Unity项目文档

    孙广东  2017.5.27 http://blog.csdn.NET/u010019717 微软开源全新的文档生成工具DocFX   类似JSDoc或Sphinx     如何使用看 : http: ...