基于Asp.Net Core 5.0依赖Quartz.Net框架编写的任务调度web管理平台
源码地址: https://github.com/246850/Calamus.TaskScheduler
演示地址:http://47.101.47.193:1063/
1、Quartz.NET框架核心类
IScheduler:调度者
IJobDetail:任务
ITrigger:触发器
JobKey:任务/触发器标识
JobDataMap:数据包
2、邮件通知(FluentEmail类库)
_fluentEmail.To(to).Subject(subject).Body(body, true).SendAsync();
3、Quartz.NET宿主方式,依靠IHostedService后台服务执行
internal class QuartzHostedService : IHostedService
{
private readonly ISchedulerFactory schedulerFactory;
private readonly IOptions<QuartzHostedServiceOptions> options;
private IScheduler scheduler = null!; public QuartzHostedService(
ISchedulerFactory schedulerFactory,
IOptions<QuartzHostedServiceOptions> options)
{
this.schedulerFactory = schedulerFactory;
this.options = options;
} public async Task StartAsync(CancellationToken cancellationToken)
{
scheduler = await schedulerFactory.GetScheduler(cancellationToken);
await scheduler.Start(cancellationToken);
} public Task StopAsync(CancellationToken cancellationToken)
{
return scheduler.Shutdown(options.Value.WaitForJobsToComplete, cancellationToken);
}
}
4.Asp.Net Core 5.0集成
安装依赖包
Quartz
Quartz.AspNetCore
Quartz.Plugins.TimeZoneConverter
Quartz.Serialization.Json
FluentEmail.Core
FluentEmail.Smtp
Startup
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews(options =>
{
options.Filters.Add<GatewayResultFilterAttribute>(); // 通用执行结果包装处理过滤器
options.Filters.Add<GlobalExceptionFilterAttribute>(); // 全局异常过滤器
})
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.Converters.Add(new DateTimeConverter()); // 日期格式化
})
.AddFluentValidation(config => // 请求模型参数验证
{
config.RunDefaultMvcValidationAfterFluentValidationExecutes = true; // false : 禁止默认模型验证
config.ValidatorOptions.CascadeMode = CascadeMode.Stop; // 不级联验证,第一个规则错误就停止
config.RegisterValidatorsFromAssemblyContaining<JobCreateOrUpdateValidator>();
});
services.AddHostedService<NLogHostService>(); // NLog 关闭服务
services.AddDistributedMemoryCache(); // 分布式缓存接口
services.AddSingleton(HtmlEncoder.Create(UnicodeRanges.All));// 解决中文乱码
services.AddHttpClient(); // IHttpClientFactory IConfigurationSection quartzConfiguration = Configuration.GetSection("Quartz"); // Quartz配置节点 /***********Quartz.NET*********/
services.AddTransient<HttpJob>(); // 注册job至容器,必须步骤
services.AddQuartz(config =>
{
config.UseTimeZoneConverter();
// 使用MicrosoftDependencyInjectionJobFactory工厂类从 容器 中创建job实例
config.UseMicrosoftDependencyInjectionJobFactory(options =>
{
options.AllowDefaultConstructor = false; // 禁止使用无参构建函数创建 job
options.CreateScope = false;
});
config.UseDefaultThreadPool(options =>
{
options.MaxConcurrency = 10; // 最大并发执行线程数
});
config.UsePersistentStore(options =>
{
options.UseProperties = false;
//options.UseBinarySerializer(); // 二进制序列化
options.UseJsonSerializer(); // json序列化
options.UseMySql(ado =>
{
ado.ConnectionString = quartzConfiguration["Database"];
ado.TablePrefix = quartzConfiguration["TablePrefix"]; // 默认值 QRTZ_
ado.ConnectionStringName = "Quartz.net";
});
}); // 监听器
config.AddSchedulerListener<DefaultSchedulerListener>();
config.AddJobListener<DefaultJobListener>();
config.AddTriggerListener<DefaultTriggerListener>(); // 启动NLog日志文件清除job
config.ScheduleJob<ClearNLogJob>(trigger =>
{
trigger.WithIdentity(NLogJobKey.NameKey, NLogJobKey.GroupKey).StartNow()
.WithCronSchedule("0 0 0 1/3 * ? ", cron => cron.WithMisfireHandlingInstructionFireAndProceed()); // 从每月1日开始,每3天执行一次
}, job =>
{
job.WithIdentity(NLogJobKey.NameKey, NLogJobKey.GroupKey)
.StoreDurably(false) // 是否持久化, 无关联触发器时是否移除,false:移除
.RequestRecovery() // 重启后是否恢复任务
.WithDescription("每3天清空NLog日志文件");
});
});
// IHostedService宿主启动 Quartz服务 services.AddSingleton<IHostedService, QuartzHostedService>()
services.AddQuartzServer(options =>
{
// when shutting down we want jobs to complete gracefully
options.WaitForJobsToComplete = true; // 等待任务执行完,再退出
}); /***********FluentEmail*********/
// 为了将邮件通知配置在job data上, 不使用自带的service注册方式
//services.AddFluentEmail(quartzConfiguration["Smtp:UserName"], "Quartz.NET任务调度通知")
// .AddRazorRenderer()
// .AddSmtpSender(quartzConfiguration["Smtp:Host"], Convert.ToInt32(quartzConfiguration["Smtp:Port"]), quartzConfiguration["Smtp:UserName"], quartzConfiguration["Smtp:Password"]);
services.AddTransient<IFluentEmail>(serviceProvider =>
{
IScheduler scheduler = serviceProvider.GetRequiredService<ISchedulerFactory>().GetScheduler().Result; JobKey key = new JobKey(EmailJobKeys.NameKey, EmailJobKeys.GroupKey);
if (!scheduler.CheckExists(key).Result)
{
JobDataMap dataMap = new JobDataMap();
dataMap.Put(EmailJobKeys.Host, "smtp.qq.com");
dataMap.Put(EmailJobKeys.Port, 587); // 465端口一直尝试不通过,奇怪
dataMap.Put(EmailJobKeys.UserName, "390915549@qq.com"); // 作者qq,欢迎骚扰
dataMap.Put(EmailJobKeys.Password, "cirxjtemuzxycagf");
dataMap.Put(EmailJobKeys.To, string.Empty); // 接收者邮件支持多个,以 ; 隔开
dataMap.Put(EmailJobKeys.NickName, "Quartz.NET任务调度通知");
dataMap.Put(EmailJobKeys.CacheExpiry, 30); // 默认30分钟内只通知一次
IJobDetail job = JobBuilder.Create<HttpJob>()
.StoreDurably(true)
.RequestRecovery()
.WithDescription("邮件通知配置Job,切勿删除")
.WithIdentity(key)
.UsingJobData(dataMap)
.Build();
scheduler.AddJob(job, true); // 初始化邮件通知配置
} IJobDetail emailJob = scheduler.GetJobDetail(key).Result;
IFluentEmail fluentEmail = new Email(new ReplaceRenderer(),
new SmtpSender(new SmtpClient(emailJob.JobDataMap.GetString(EmailJobKeys.Host), emailJob.JobDataMap.GetInt(EmailJobKeys.Port))
{
EnableSsl = true,
Credentials = new NetworkCredential(emailJob.JobDataMap.GetString(EmailJobKeys.UserName),
emailJob.JobDataMap.GetString(EmailJobKeys.Password))
}),
emailJob.JobDataMap.GetString(EmailJobKeys.UserName),
emailJob.JobDataMap.GetString(EmailJobKeys.NickName));
return fluentEmail;
}); IocEngine.Instance.Init(services); // 实在没办法才弄个静态容器获取service, 监听器里无法通过构造函数 注入 ISchedulerFactory, IFluentEmail, 猜测应该是循环引用了
}
5、谢谢观看,拜拜
基于Asp.Net Core 5.0依赖Quartz.Net框架编写的任务调度web管理平台的更多相关文章
- 用VSCode开发一个基于asp.net core 2.0/sql server linux(docker)/ng5/bs4的项目(1)
最近使用vscode比较多. 学习了一下如何在mac上使用vscode开发asp.netcore项目. 这里是我写的关于vscode的一篇文章: https://www.cnblogs.com/cgz ...
- [译]基于ASP.NET Core 3.0的ABP v0.21已发布
基于ASP.NET Core 3.0的ABP v0.21已发布 在微软发布仅仅一个小时后, 基于ASP.NET Core 3.0的ABP v0.21也紧跟着发布了. v0.21没有新功能.它只是升级到 ...
- Asp.Net Core 2.0 项目实战(3)NCMVC角色权限管理前端UI预览及下载
Asp.Net Core 2.0 项目实战(1) NCMVC开源下载了 Asp.Net Core 2.0 项目实战(2)NCMVC一个基于Net Core2.0搭建的角色权限管理开发框架 Asp.Ne ...
- 基于ASP.NET Core 3.0快速搭建Razor Pages Web应用
前言 虽然说学习新的开发框架是一项巨大的投资,但是作为一个开发人员,不断学习新的技术并快速上手是我们应该掌握的技能,甚至是一个.NET Framework开发人员,学习.NET Core 新框架可以更 ...
- 基于ASP.NET Core 6.0的整洁架构
大家好,我是张飞洪,感谢您的阅读,我会不定期和你分享学习心得,希望我的文章能成为你成长路上的垫脚石,让我们一起精进. 本节将介绍基于ASP.NET Core的整洁架构的设计理念,同时基于理论落地的代码 ...
- 打造静态分析器(二)基于Asp.Net Core 3.0的AspectCore组件检测
上一篇,我们打造了一个简单的分析器,但是我们实际使用分析器就是为了对项目做分析检测,增加一些非语法的自检的 比如Asp.Net Core 3.0的替换依赖注入检测 设计分析 我们创建一个默认的Asp. ...
- 用VSCode开发一个基于asp.net core 2.0/sql server linux(docker)/ng5/bs4的项目(2)
第一部分: http://www.cnblogs.com/cgzl/p/8478993.html 为Domain Model添加约束 前一部分, 我们已经把数据库创建出来了. 那么我们先看看这个数据库 ...
- [译]ASP.NET Core 2.0 依赖注入
问题 如何使用 ASP.NET Core 服务容器进行依赖注入? 答案 创建一个服务 public interface IGreetingService { string Greet(string t ...
- 基于ASP.Net Core开发一套通用后台框架记录-(项目的搭建)
写在前面 本系列博客是本人在学习的过程中搭建学习的记录,如果对你有所帮助那再好不过.如果您有发现错误,请告知我,我会第一时间修改. 前期我不会公开源码,我想是一点点敲代码,不然复制.粘贴那就没意思了. ...
随机推荐
- 云原生网络代理(MOSN)的进化之路
本文系云原生应用最佳实践杭州站活动演讲稿整理.杭州站活动邀请了 Apache APISIX 项目 VP 温铭.又拍云平台开发部高级工程师莫红波.蚂蚁金服技术专家王发康.有赞中间件开发工程师张超,分享云 ...
- js上 七、表达式
(1).什么是表达式 任何有值的内容都是表达式 一个表达式会产生一个值,它可以放在任何需要一个值的地方,比如a=3中的3就是一个表达式,a=3整体也可以作为一个表达式. 常见表达式有如下几种: ü 原 ...
- Spring MVC整合 freemarker
1.什么是Spring MVC? Spring MVC是一种基于Java的实现了Web MVC设计模式的请求驱动类型的轻量级Web框架,即使用了MVC架构模式的思想,将Web层进行职责解耦,基于请求驱 ...
- yum提示错误: error: rpmdb: BDB0113 Thread/process 9866/140290246137664 failed:
错误如下: 解决办法:重新构建rpm数据库
- Python利用openpyxl带格式统计数据(1)- 处理excel数据
统计数据的随笔写了两篇了,再来一篇,这是第三篇,前面第一篇是用xlwt写excel数据,第二篇是用xlwt写mysql数据.先贴要处理的数据截图: 再贴最终要求的统计格式截图: 第三贴代码: 1 '' ...
- windows Server 2016安装Sqlserver远程连接的坑
如果要连接远程服务器 首先打开防火墙端口1433 新建入站规则 然后 如果没启用 就启用 然后重启服务就行 如果还是不行 进去属性 修改三处 然后重启服务
- C盘满了删除C盘文件
还有很多文件在C:\Users\lock\AppData 比如C:\Users\lock\AppData\Local\Temp 临时文件 C:\Users\lock\AppData\Roaming\ ...
- winform 跨线程 调用控件
public delegate void rtbCallBack(string txt); public void rtbAddText(string txt) { if (this.rtb.Invo ...
- ES6语法:class类,从了解到使用
前期提要: JavaScript 语言中,在使用类之前,生成实例对象的传统方法是通过使用构造函数. 一.构造函数: 定义:通过 new 函数名 来实例化对象的函数叫构造函数. 主要功能:为初 ...
- 关于eclipse反编译插件不起作用问题的解决
1.首先我的eclipse版本是 Version: Photon Release (4.8.0),小伙伴们可以通过 help>>About eclipse IDE 来查看自己的eclips ...