首页 > 代码库 > Quartz.net 2.x 学习笔记03-使用反射加载定时任务

Quartz.net 2.x 学习笔记03-使用反射加载定时任务

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

 

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

 

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

 

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

 

下面可以编写代码了,在Library类库中添加一个JobBase类,3Job类,和一个Job管理类(假设分别取名:JobBase.csHelloJob.csAnotherJob.csParameterJob.csJobManage.cs

 

注:HelloJobAnotherJobParameterJob都是任务类继承自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 = 1;        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="http://www.mamicode.com/INFO" />          <arg key="showLogName" value="http://www.mamicode.com/true" />          <arg key="showDataTime" value="http://www.mamicode.com/true" />          <arg key="dateTimeFormat" value="http://www.mamicode.com/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-使用反射加载定时任务