zoukankan      html  css  js  c++  java
  • Topshelf+Quartz在.Net Core框架下的实现

      在我们日常开发工作中,经常会运用到Quartz+Topshelf组件的组合来开发一些定时任务。那么在.Net Core下如何去使用呢?我自己尝试搭建了一个测试项目,过程中遇到了以下一些问题:

    • Quartz 配置文件及版本问题。我们知道Quartz有2个配置文件,quartz.config和quartz.job.xml。前者负责组件初始化配置,后者负责job和triggle的配置。刚开始我是直接把framework下的配置文件直接拿过来用的,启动直接报错。主要问题在quartz.config
      quartz.plugin.xml.type = Quartz.Plugin.Xml.XMLSchedulingDataProcessorPlugin, Quartz
      

      这一段上。原因Quartz最新版本已经将Plugin模块单独剥离出一个独立的DLL,这里的引用也要变化。需要Nuget上下载Quartz.Plugins组件,并将上一段改成

      quartz.plugin.xml.type = Quartz.Plugin.Xml.XMLSchedulingDataProcessorPlugin, Quartz.Plugins
      
    • DI问题。为了贴合.Net Core DI精神,我们也要来实现Console程序的DI功能。第一个问题是Job如何DI?首先我们需要自己去实现JobFactory

          public class NewJobFactory : IJobFactory
          {
              private readonly IServiceProvider _serviceProvider;
      
              public NewJobFactory(IServiceProvider serviceProvider)
              {
                  _serviceProvider = serviceProvider;
              }
              public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
              {
                  return _serviceProvider.GetService(bundle.JobDetail.JobType) as IJob;
              }
      
              public void ReturnJob(IJob job)
              {
                  var disposable = job as IDisposable;
                  disposable?.Dispose();
              }
          }
      

        注入方式

      IServiceCollection services = new ServiceCollection();
      services.AddScoped<IJobFactory, NewJobFactory>();
      services.AddSingleton(service =>
      {
           var scheduler = StdSchedulerFactory.GetDefaultScheduler().Result;
           scheduler.JobFactory = service.GetService<IJobFactory>();
           return scheduler;
      });
    • Console程序的配置文件获取以及注入问题。众所周知,.Net Core下建立的Console程序就是一块白板,什么都没有。配置文件我们还得自己去建一个.json文件。并且需要自己从Nuget上下载的组件包(见后面项目结构截图)。加载方式如下
    •         private IConfiguration ConfigureConfiguration()
              {            
                  //配置文件
                  var builder = new ConfigurationBuilder()
                      .SetBasePath(Directory.GetCurrentDirectory())
                      .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);
                  return builder.Build();
              }
      

        注入方式如下

                  if (configuration != null)
                  {
                      //iconfiguration注入
                      services.AddSingleton<IConfiguration>(configuration);
                  }
      
                  //自定义 option方式注入
                  services.Configure<AppSetting>(configuration);
      

        这样就可以在后续的类代码中 直接通过DI方式获取IConfiguration对象或者你自己的Option对象了

      贴上完整代码。

      Program.cs

            static void Main(string[] args)
            {
                HostFactory.Run(x =>
                {
                    x.Service<ServiceRunner>();
                    x.SetDescription("gt.dotnetcore.consolesample");
                    x.SetDisplayName("gt.dotnetcore.consolesample");
                    x.SetServiceName("gt.dotnetcore.consolesample");
    
                    x.StartAutomatically();
                });
            }
    

      ServiceRunner.cs 启动的核心

        public class ServiceRunner : ServiceControl
        {
            //private readonly IScheduler _scheduler;
    
            private IServiceProvider _serviceProvider;
            public ServiceRunner()
            {
                var configurationRoot = ConfigureConfiguration();
                _serviceProvider = ConfigureServices(configurationRoot);
            }
    
            private IConfiguration ConfigureConfiguration()
            {            
                //配置文件
                var builder = new ConfigurationBuilder()
                    .SetBasePath(Directory.GetCurrentDirectory())
                    .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);
                return builder.Build();
            }
            private IServiceProvider ConfigureServices(IConfiguration configuration)
            {
                //依赖注入
                IServiceCollection services = new ServiceCollection();
                //后续需要使用log的话,这里需要注入
                services.AddTransient<ILoggerFactory, LoggerFactory>();
                services.AddTransient<ITest, TestBiz>();
                services.AddScoped<IJobFactory, NewJobFactory>();
                if (configuration != null)
                {
                    //iconfiguration注入
                    services.AddSingleton<IConfiguration>(configuration);
                }
    
                //自定义 option方式注入
                services.Configure<AppSetting>(configuration);
                //这里注意Job的注入方式,不要强制指定IJob实现方式!!
                services.AddScoped<TestJob>();
                services.AddScoped<Test2Job>();
                services.AddSingleton(service =>
                {
                    var scheduler = StdSchedulerFactory.GetDefaultScheduler().Result;
                    scheduler.JobFactory = service.GetService<IJobFactory>();
                    return scheduler;
                });
                //构建容器
                return services.BuildServiceProvider();
            }
    
            public bool Start(HostControl hostControl)
            {
                var scheduler = _serviceProvider.GetService(typeof(IScheduler)) as IScheduler;
                scheduler.Start();
                return true;
            }
    
            public bool Stop(HostControl hostControl)
            {
                var scheduler = _serviceProvider.GetService(typeof(IScheduler)) as IScheduler;
                scheduler.Shutdown(true);
                return true;
            }
        }
    

      Test2Job.cs

        public class Test2Job : IJob
        {
            private ITest _testService;
            private AppSetting _appsetting;
            private IConfiguration _configuration;
    
            public Test2Job(ITest testService, IOptionsMonitor<AppSetting> appSettingAccessor, IConfiguration configuration)
            {
                _testService = testService;
                _appsetting = appSettingAccessor.CurrentValue;
                _configuration = configuration;
            }
            public Task Execute(IJobExecutionContext context)
            {
                Console.WriteLine($"job2222222222222 started:{_appsetting.TestCN}");
                var t = _testService.Dowork(1);
                t.Wait();
                Console.WriteLine($"job2222222222222 ended:{_configuration["TestCN"]}");
    
                return Task.CompletedTask;
            }
        }
    

      

      项目结构截图

    附项目源码 https://gitee.com/gt1987/gt.dotnetcore

  • 相关阅读:
    git常用指令 github版本回退 reset
    三门问题 概率论
    如何高效的学习高等数学
    数据库6 关系代数(relational algebra) 函数依赖(functional dependency)
    数据库5 索引 动态哈希(Dynamic Hashing)
    数据库4 3层结构(Three Level Architecture) DBA DML DDL DCL DQL
    梦想开始的地方
    java String字符串转对象实体类
    java 生成图片验证码
    java 对象之间相同属性进行赋值
  • 原文地址:https://www.cnblogs.com/gt1987/p/11806053.html
Copyright © 2011-2022 走看看