如何在ASP.NET Core中使用Quartz.NET安排作业

使用Web应用程序时,通常需要在后台执行某些任务。 在某些情况下,这些任务应该以预定的时间间隔执行。

Quartz.NET是流行的Java作业调度框架的开源.NET端口。 它已经使用了很长时间,并且为使用Cron表达式提供了出色的支持。 您可以在此处的早期文章中了解有关Quartz.NET的更多信息。

[ 同样在InfoWorld上:何时在C#中使用抽象类和接口 ]

本文讨论了如何在ASP.NET Core中使用Quartz.NET来调度后台作业。

若要使用本文提供的代码示例,您应该在系统中安装Visual Studio 2019。 如果您还没有副本,则可以在此处下载Visual Studio 2019 。

创建一个ASP.NET Core API项目

首先,让我们在Visual Studio中创建一个ASP.NET Core项目。 假设系统中已安装Visual Studio 2019,请按照下面概述的步骤在Visual Studio中创建一个新的ASP.NET Core项目。

  1. 启动Visual Studio IDE。
  2. 点击“创建新项目”。
  3. 在“创建新项目”窗口中,从显示的模板列表中选择“ ASP.NET Core Web应用程序”。
  4. 点击下一步。
  5. 在接下来显示的“配置新项目”窗口中,指定新项目的名称和位置。
  6. 单击创建。
  7. 在“创建新的ASP.NET Core Web应用程序”窗口中,从顶部的下拉列表中选择.NET Core作为运行时,并选择ASP.NET Core 2.2(或更高版本)。 我将在这里使用ASP.NET Core 3.0。
  8. 选择“ API”作为项目模板以创建新的ASP.NET Core API应用程序。
  9. 确保未选中“启用Docker支持”和“配置HTTPS”复选框,因为我们此处将不再使用这些功能。
  10. 确保将身份验证设置为“无身份验证”,因为我们也不会使用身份验证。
  11. 单击创建。

这将在Visual Studio中创建一个新的ASP.NET Core API项目。 在“解决方案资源管理器”窗口中选择Controllers解决方案文件夹,然后单击“添加-> Controller…”以创建一个名为DefaultController的新控制器。

接下来,要使用Quartz,您应该从NuGet安装Quartz软件包。 您可以通过Visual Studio 2019 IDE中的NuGet程序包管理器来执行此操作,也可以通过在NuGet程序包管理器控制台上执行以下命令来执行此操作:

Install-Package Quartz

Quartz.NET作业,触发器和调度程序

Quartz.NET中的三个主要概念是作业,触发器和调度程序。 作业包含执行任务或要执行的作业的代码。 作业由实现IJob接口的类表示。 触发器用于指定作业的时间表和其他详细信息。 您可以利用触发器来指定应如何执行作业。 调度程序是负责根据预定义的调度轮询和执行作业的组件。

使用Quartz.NET创建一个调度程序

应该注意的是,一个应用程序中可以有多个调度程序。 但是,为了简单起见,我们在这里仅使用一个调度程序。 以下代码段说明了如何创建调度程序实例。

var scheduler = StdSchedulerFactory.GetDefaultScheduler().GetAwaiter().GetResult();

一旦创建了调度程序,就可以在Startup.cs文件的ConfigureServices方法中使用以下代码将调度程序实例添加为单例服务。

services.AddSingleton(scheduler);

[ 同样在InfoWorld上:如何将多个参数传递给Web API控制器方法 ]

使用Quartz.NET启动和停止调度程序

要启动和停止调度程序,我们将利用托管服务。 为此,您需要创建一个实现IHostingService接口的类,如下面给出的代码片段所示。

public class CustomQuartzHostedService : IHostedService
{
        private readonly IScheduler _scheduler;
        public CustomQuartzHostedService(IScheduler scheduler)
        {
            _scheduler = scheduler;
        }
        public async Task StartAsync(CancellationToken cancellationToken)
        {
            await _scheduler?.Start(cancellationToken);
        }
        public async Task StopAsync(CancellationToken cancellationToken)
        {
            await _scheduler?.Shutdown(cancellationToken);
        }
 }

请注意,您应该使用下面给出的代码片段在ConfigureServices方法中的服务集合中注册托管服务。

services.AddHostedService();

这是更新的ConfigureServices方法,供您参考:

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers();
    var scheduler =
    StdSchedulerFactory.GetDefaultScheduler().GetAwaiter().GetResult();
    services.AddSingleton(scheduler);
    services.AddHostedService();
}

使用Quartz.NET创建工作

如前所述,作业是一个实现IJob接口并包含Execute()方法的类。 Execute()方法接受IJobExecutionContext类型的实例。

以下代码段说明了一个包含异步Execute()方法的作业类。 此方法包含与您的工作应执行的任务相对应的代码。

[DisallowConcurrentExecution]
public class NotificationJob : IJob
    {
        private readonly ILogger _logger;
        public NotificationJob(ILogger logger)
        {
            _logger = logger;
        }
        public Task Execute(IJobExecutionContext context)
        {
            _logger.LogInformation("Hello world!");
            return Task.CompletedTask;
        }
    }

使用Quartz.NET创建作业工厂

作业工厂是一个继承IJobFactory接口并实现NewJob()和ReturnJob()方法的类。 以下代码段可用于创建可以创建和返回作业实例的工厂类。

public class CustomQuartzJobFactory : IJobFactory
    {
        private readonly IServiceProvider _serviceProvider;
        public CustomQuartzJobFactory(IServiceProvider serviceProvider)
        {
            _serviceProvider = serviceProvider;
        }
        public IJob NewJob(TriggerFiredBundle triggerFiredBundle,
        IScheduler scheduler)
        {
            var jobDetail = triggerFiredBundle.JobDetail;
            return (IJob)_serviceProvider.GetService(jobDetail.JobType);
        }
        public void ReturnJob(IJob job) { }
    }

请注意,此实现没有利用作业池。 如果要使用作业池,则应更改NewJob()方法,然后实现ReturnJob()方法。

[ 同样在InfoWorld上:TypeScript与JavaScript:了解差异 ]

创建一个JobMetadata类来存储您的工作元数据

我们将使用一个自定义类来存储与作业相关的元数据,即作业ID,名称等。以下类表示作业元数据类。

public class JobMetadata
    {
        public Guid JobId { get; set; }
        public Type JobType { get; }
        public string JobName { get; }
        public string CronExpression { get; }
        public JobMetadata(Guid Id, Type jobType, string jobName,
        string cronExpression)
        {
            JobId = Id;
            JobType = jobType;
            JobName = jobName;
            CronExpression = cronExpression;
        }
    }

创建一个托管服务以启动和停止Quartz.NET调度程序

接下来,我们需要实现一个托管服务。 托管服务是一个实现IHostedService接口并启动Quartz调度程序的类。 下面的代码清单说明了自定义托管服务类。

public class CustomQuartzHostedService : IHostedService
    {
        private readonly ISchedulerFactory schedulerFactory;
        private readonly IJobFactory jobFactory;
        private readonly JobMetadata jobMetadata;
        public CustomQuartzHostedService(ISchedulerFactory
            schedulerFactory,
            JobMetadata jobMetadata,
            IJobFactory jobFactory)
        {
            this.schedulerFactory = schedulerFactory;
            this.jobMetadata = jobMetadata;
            this.jobFactory = jobFactory;
        }
        public IScheduler Scheduler { get; set; }
        public async Task StartAsync(CancellationToken cancellationToken)
        {
            Scheduler = await schedulerFactory.GetScheduler();
            Scheduler.JobFactory = jobFactory;
            var job = CreateJob(jobMetadata);
            var trigger = CreateTrigger(jobMetadata);
            await Scheduler.ScheduleJob(job, trigger, cancellationToken);
            await Scheduler.Start(cancellationToken);
        }
        public async Task StopAsync(CancellationToken cancellationToken)
        {
            await Scheduler?.Shutdown(cancellationToken);
        }
        private ITrigger CreateTrigger(JobMetadata jobMetadata)
        {
            return TriggerBuilder.Create()
            .WithIdentity(jobMetadata.JobId.ToString())
            .WithCronSchedule(jobMetadata.CronExpression)
            .WithDescription($"{jobMetadata.JobName}")
            .Build();
        }
        private IJobDetail CreateJob(JobMetadata jobMetadata)
        {
            return JobBuilder
            .Create(jobMetadata.JobType)
            .WithIdentity(jobMetadata.JobId.ToString())
            .WithDescription($"{jobMetadata.JobName}")
            .Build();
        }
    }

下面的代码片段显示了Startup类的ConfigureServices方法的完整代码。

public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddSingleton();
services.AddSingleton();
services.AddSingleton();
services.AddSingleton(new JobMetadata(Guid.NewGuid(), typeof(NotificationJob),"Notification Job", "0/10 * * * * ?"));
services.AddHostedService();
}

[ 通过InfoWorld的App Dev Report新闻通讯了解软件开发中的热门话题 ]

这就是您要做的! 当您执行应用程序时,您会发现NotificationJob类的Execute()方法每10秒运行一次。

Quartz.NET是在您的应用程序中实现调度程序的理想选择。 您可以利用Quartz.NET中的持久性功能将作业存储在SQL Server,PostgreSQL或SQLite等数据库中。

From: https://www.infoworld.com/article/3529418/how-to-schedule-jobs-using-quartznet-in-aspnet-core.html

你可能感兴趣的:(数据库,运维,java)