• 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="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="LogXXLog.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文件

     

    源码下载(微云)

     

     

     

     

  • 相关阅读:
    23、如何解决合并分支时的冲突
    25、不同人,修改了相同的文件,如何处理?
    18、想要将某一文件,回到指定版本时,如何进行操作?
    24、不同人想要查看版本路线,如何进行操作
    20、想要给每个版本创建一个独特标签,做所有版本标签管理时,如何进行操作
    Viper包的钩子函数
    win10远程桌面教程(修改远程桌面端口)
    python路径库pathlib应用
    pandas获取所有sheet名字
    python全屏截图
  • 原文地址:https://www.cnblogs.com/jancyxue/p/4155100.html
Copyright © 2020-2023  润新知