但是,我们这儿要加点内容。我们把Quartz的托管服务做成一个通用实现,来调度任意的作业。因此,我们创建一个简单的DTO,并使用它来定义一个给定作业类型的时间器调度:
public class JobSchedule{
public JobSchedule(Type jobType, string cronExpression)
{
JobType = jobType;
CronExpression = cronExpression;
}
public Type JobType { get; }
public string CronExpression { get; }
}
在这个类中,JobType是一个作业的类型,例如本例子中的DemoJob。CronExpression是一个Cron的表达式。
Cron表达式允许复杂的计时器调度,所以可以设置规则,比如每个月的5号和20号,在早上8点到10点之间每半小时触发一次。
关于Quartz.NET的Cron表达式,可以在这儿查到。
注意:不同操作系统使用的Cron表达式有一定的区别,写表达式的时候一定要注意这一点。
然后,我们把作业添加到Startup.ConfigureServices()中:
public void ConfigureServices(IServiceCollection services){
services.AddControllers();
services.AddSingleton<IJobFactory, SingletonJobFactory>();
services.AddSingleton<ISchedulerFactory, StdSchedulerFactory>();
services.AddSingleton<DemoJob>();
services.AddSingleton(new JobSchedule(
jobType: typeof(DemoJob),
cronExpression: "0/5 * * * * ?")); // 每5秒运行一次
}
这段代码向DI添加了四个单例对象:
SingletonJobFactory,第四节的类,用于创建作业实例;
ISchedulerFactory的一个实现,是内置的StdSchedulerFactory,用于处理调度和管理作业;
DemoJob作业本身;
DemoJob的一个JobSchedule实例,该实例具有每5秒运行一次的Cron表达式。
现在,主要代码已经完成,就差Quartz托管服务了。
六、创建Quartz托管服务QuartzHostedService是自己创建的Quartz托管服务,继承于IHostedService,用于设置Quartz调度器,并在后台启动它。
先看一下完整的代码:
public class QuartzHostedService : IHostedService{
private readonly ISchedulerFactory _schedulerFactory;
private readonly IJobFactory _jobFactory;
private readonly IEnumerable<JobSchedule> _jobSchedules;
public QuartzHostedService(ISchedulerFactory schedulerFactory, IJobFactory jobFactory, IEnumerable<JobSchedule> jobSchedules)
{
_schedulerFactory = schedulerFactory;
_jobSchedules = jobSchedules;
_jobFactory = jobFactory;
}
public IScheduler Scheduler { get; set; }
public async Task StartAsync(CancellationToken cancellationToken)
{
Scheduler = await _schedulerFactory.GetScheduler(cancellationToken);
Scheduler.JobFactory = _jobFactory;
foreach (var jobSchedule in _jobSchedules)
{
var job = CreateJob(jobSchedule);
var trigger = CreateTrigger(jobSchedule);
await Scheduler.ScheduleJob(job, trigger, cancellationToken);
}
await Scheduler.Start(cancellationToken);
}
public async Task StopAsync(CancellationToken cancellationToken)
{
await Scheduler?.Shutdown(cancellationToken);
}
private ITrigger CreateTrigger(JobSchedule schedule)
{
return TriggerBuilder
.Create()
.WithIdentity($"{schedule.JobType.FullName}.trigger")
.WithCronSchedule(schedule.CronExpression)
.WithDescription(schedule.CronExpression)
.Build();
}
private IJobDetail CreateJob(JobSchedule schedule)
{
var jobType = schedule.JobType;
return JobBuilder
.Create(jobType)
.WithIdentity(jobType.FullName)
.WithDescription(jobType.Name)
.Build();
}
}
解释一下这段代码: