<PackageReference Include="Flurl" Version="2.8.2" />
<PackageReference Include="Flurl.Http" Version="2.4.2" />
IJob
作业,把设置保存到QuartzNet专有的表。当触发的时候,QuartzNet会调用我们定义好的接口,发送极光推送以及把一条通知记录保存到数据库的Noti表。首先有关配置。
namespace DD.Libs.TasksManager
{
/// <summary>
/// 极光配置
/// </summary>
public class JobSetting : IOptions<JobSetting>
{
public JobSetting Value => this;
/// <summary>
/// 执行场景任务的url
/// http://47.103.61.198:5002/api/tasks/cj/
/// </summary>
public string sceneUrl { get; set; }
/// <summary>
/// 定时任务的url
/// http://47.103.61.198:5002/api/tasks/ds/
public string timingUrl { get; set; }
/// <summary>
/// 连接字符串的一部分
/// Port=3306;Database=quartznet;Uid=root;Pwd=pass;SslMode=none
/// </summary>
public string quartz { get; set; }
/// <summary>
/// 连接字符串的一部分
/// 192.168.9.108
/// </summary>
public string server { get; set; }
}
}
在appSetting.json
中配置
"Tasks": { //场景和定时
"sceneUrl": "http://47.103.61.198:5005/api/tasks/noti/", //写字楼版QuartzNet触发发生时调用的接口
"timingUrl": "", //定时地址
"server": "47.103.61.198",
"quartz": "Port=3306;Database=ddquartz1;Uid=root;Pwd=TecheDing2019;SslMode=none"
},
接口实现:
namespace DD.Warning.WebUI.Controllers
{
/// <summary>
/// 场景和定时在这里执行
/// </summary>
[AllowAnonymous]
[Produces("application/json")]
[Route("api/tasks")]
public class TaiHeRealController : Controller
{
private readonly IMediator _mediator; //中介者
private readonly ILogger<TaiHeRealController> _logger;
public TaiHeRealController(IMediator mediator, ILogger<TaiHeRealController> logger)
{
_mediator = mediator;
_logger = logger;
}
/// <summary>
/// 场景执行
/// </summary>
/// <param name="extra"></param>
/// <returns></returns>
[HttpGet("cj/{extra}")]
public async Task<IActionResult> cj(string extra)
{
//rlq_nuode,SceneId,SceneScheduleId
string[] tempArr = extra.Split(',');
var innerCommand = new AutoTriggerSceneCommand
{
SceneId = tempArr[1],
SceneScheudleId = tempArr[2],
ConnKey=tempArr[0]
};
_logger.LogWarning($"正在触发场景:{extra}{WarningConstants.LogPlaceholder}", WarningConstants.LogTest);
await _mediator.Send(innerCommand);
return Ok();
}
}
}
定义一个IJob
namespace DD.Libs.TasksManager
{
public class SceneJob : IJob
{
private readonly IOptions<JobSetting> _settings;
public SceneJob(IOptions<JobSetting> settings)
{
_settings = settings;
}
public async Task Execute(IJobExecutionContext context)
{
//获取job上下文中传来的额外参数
string extra = context.JobDetail.JobDataMap.GetString("extra");
using(var client = new HttpClient())
{
client.Timeout = TimeSpan.FromSeconds(1200);
//"http://47.103.61.198:5002/api/tasks/cj/
string url = $"{_settings.Value.sceneUrl }{extra}";
await client.GetAsync(url);
}
}
}
}
在Startup
中注册:
#region 场景定时任务,Quartz
services.Configure<JobSetting>(Configuration.GetSection("Tasks"));
services.AddTransient<SceneJob>();
NameValueCollection props = new NameValueCollection {
{ "quartz.threadPool.threadCount","100"},
{ "quartz.jobStore.type","Quartz.Impl.AdoJobStore.JobStoreTX, Quartz"},
{ "quartz.jobStore.driverDelegateType","Quartz.Impl.AdoJobStore.StdAdoDelegate, Quartz"},
{ "quartz.jobStore.dataSource","myDS"},
{ "quartz.dataSource.myDS.connectionString",$"Server={Configuration["Tasks:server"]};{Configuration["Tasks:quartz"]}"},
//{ "quartz.dataSource.myDS.connectionString",$"server={Configuration["App:redis"]};port=3306;database=quartznet;user=root;password=lcDb_!@34%^_Mantunsci;SslMode=none"},
{ "quartz.dataSource.myDS.provider","MySql"},
{ "quartz.serializer.type","json"}
//{ "quartz.jobStore.useProperties","true"}
};
//计划工厂
var schedulerFactory = new StdSchedulerFactory(props);
services.AddSingleton<ISchedulerFactory>(schedulerFactory); //计划工厂
//job工厂
services.AddSingleton<IJobFactory, SimpleInjectorJobFactory>();//Job工厂
//帮助类
services.AddSingleton<DDJobScheduler>((ctx) => {
var tempSchedulerFactory = ctx.GetRequiredService<ISchedulerFactory>();
var tempJobFactory = ctx.GetRequiredService<IJobFactory>();
var tempScheduler = tempSchedulerFactory.GetScheduler().Result;
tempScheduler.JobFactory = tempJobFactory;
var tempJobScheduler = new DDJobScheduler(tempScheduler);
return tempJobScheduler;
});
#endregion
在请求管道中注册:
#region 场景定时任务
var scheduler = serviceProvider.GetService<DDJobScheduler>();
scheduler.Init();
#endregion
如何使用呢?
public class AddSceneSchedulesCommandHandler : IRequestHandler<AddSceneSchedulesCommand, ResponseWrapperBase>
{
private readonly DDJobScheduler _scheduler;
public AddSceneSchedulesCommandHandler(DDJobScheduler scheduler)
{
_scheduler = scheduler;
}
public async Task<ResponseWrapperBase> Handle(AddSceneSchedulesCommand request, CancellationToken cancellationToken)
{
await _scheduler.DeleteJob(delJoinName, delGroupName);
string cron = JobUtil.GetCronByTime(newSceneSchedule.Hour, newSceneSchedule.Minute, newSceneSchedule.Second, (TimingWeekEnum)newSceneSchedule.Week);
await _scheduler.AddSceneJob(joinName, groupName, cron, joinName);
return await Task.FromResult(result);
}
///
/// <summary>
/// 通知标题
/// </summary>
public string Title { get; private set; }
/// <summary>
/// 通知内容
/// </summary>
public string Content { get; private set; }
/// <summary>
/// 是否已读
/// </summary>
public string IsRead { get;private set; }
/// <summary>
/// 通知类型
/// 报警通知的Type=0
/// 延迟断电通知的Type=alert
/// </summary>
public string Type { get; private set; }
/// <summary>
/// 报警通知用的报警级别描述
/// </summary>
public string Level { get; private set; }
/// <summary>
/// 传递的主键
/// 用来点击某个通知跳转到某个地方
/// </summary>
public string ExtraId { get; private set; }
/// <summary>
/// 创建方式1
/// </summary>
/// <param name="title"></param>
/// <param name="content"></param>
public Noti(string title, string content)
{
if (string.IsNullOrEmpty(title)) throw new ArgumentNullException("title cannot be null");
if (string.IsNullOrEmpty(content)) throw new ArgumentNullException("content cannot be null");
Title = title;
Content = content;
CreateTime = DateTime.Now.ToFullTimeStr();
Id = Guid.NewGuid();
LastUpdateTime = DateTime.Now.ToFullTimeStr();
IsLogicDel = CommonConstants.LogicDelNo;
}
/// <summary>
/// 创建方式2
/// </summary>
/// <param name="title"></param>
/// <param name="content"></param>
/// <param name="type"></param>
/// <param name="extraId"></param>
public Noti(string title, string content, string type, string extraId)
{
if (string.IsNullOrEmpty(title)) throw new ArgumentNullException("title cannot be null");
if (string.IsNullOrEmpty(content)) throw new ArgumentNullException("content cannot be null");
if (string.IsNullOrEmpty(extraId)) throw new ArgumentNullException("extraId cannot be null");
Title = title;
Content = content;
Type = type;
ExtraId = extraId;
CreateTime = DateTime.Now.ToFullTimeStr();
Id = Guid.NewGuid();
LastUpdateTime = DateTime.Now.ToFullTimeStr();
IsLogicDel = CommonConstants.LogicDelNo;
}
/// <summary>
/// 设置报警级别
/// </summary>
/// <param name="level"></param>
public void SetLevel(string level)
{
Level = level;
}
/// <summary>
/// 标记已读
/// </summary>
/// <param name="regId"></param>
public void MarkRead(string regId)
{
if (string.IsNullOrEmpty(regId)) throw new ArgumentNullException("title cannot be null");
if(string.IsNullOrEmpty(IsRead))
{
IsRead = regId;
}
else
{
var currentRegIds = regId.Split(',').ToList();
currentRegIds.Add(regId);
IsRead = string.Join(',', currentRegIds);
}
}
}
//对应的仓储 private readonly INotiRepository _notiRepo;
public SomeRequestHandler(INotiRepository notiRepo) {
_notiRepo = notiRepo;
}
//大致用法 var newNoti = new Noti(“title”,“content”, “alert”, string.Empty); _notiRepo.Add(newNoti); await _notiRepo.UnitOfWork.SaveChangesAsync(cancellationToken);
- 极光推送
var request = new JiGuanPushRequest
{
platform = "all",
//audience = "all",//针对所有
audience = new Audience
{
alias = tempAlias
},
notification = new Notification
{
alert = $"{locationDesc},{kgDesc},{warningDesc}",
android = new Android
{
extras = new Extras
{
android_key1 = string.Empty,
kaiGuanId = cloudKaiGuan.Id.ToString(),
connKey = cloudKaiGuan.ConnKey,
startTime = startEndTime,
warningType = ((short)type).ToString(),
projectId = _appOptions.Value.projectid,
notiType = "0", //通知消息类型
notiId = notis.Id.ToString()
}
},
ios = new Ios
{
sound = "sound.caf",
badge = "+1",
extras = new Extras2
{
ios_key1 = string.Empty,
kaiGuanId = cloudKaiGuan.Id.ToString(),
connKey = cloudKaiGuan.ConnKey,
startTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
warningType = ((short)type).ToString(),
projectId = _appOptions.Value.projectid,
notiType = "0", //通知消息类型
notiId = notis.Id.ToString()
}
}
},
options = new JiGuangs.Options
{
apns_production = true
}
};
var response = await _appOptions.Value.jiguang
.WithHeader("Content-Type", "application/json")
.WithHeader("Authorization", "Basic M2ZhOTE0NTUzNmEwMDFmY2UwYjg3NjU5OjIxYjE0ZGM0OGZkZjRmMDk4NzZiMTg0MQ==")
.PostJsonAsync(request);
//相关Dto
public class JiGuanPushRequest
{
[JsonProperty("platform")]
public string platform { get; set; }
//[JsonProperty("audience")]
//public string audience { get; set; }
[JsonProperty("audience")]
public Audience audience { get; set; }
[JsonProperty("notification")]
public Notification notification { get; set; }
[JsonProperty("options")]
public Options options { get; set; }
}
public class Audience
{
[JsonProperty("alias")]
public List<string> alias { get; set; } = new List<string>();
}
public class Android
{
[JsonProperty("extras")]
public Extras extras { get; set; }
}
public class Extras
{
[JsonProperty("android-key1")]
public string android_key1 { get; set; }
[JsonProperty("kaiGuanId")]
public string kaiGuanId { get; set; }
[JsonProperty("warningType")]
public string warningType { get; set; }
[JsonProperty("startTime")]
public string startTime { get; set; }
[JsonProperty("connKey")]
public string connKey { get; set; }
[JsonProperty("notiType")]
public string notiType { get; set; }
[JsonProperty("projectId")]
public string projectId { get; set; }
[JsonProperty("notiId")]
public string notiId { get; set; }
}
public class Extras2
{
[JsonProperty("ios-key1")]
public string ios_key1 { get; set; }
[JsonProperty("kaiGuanId")]
public string kaiGuanId { get; set; }
[JsonProperty("warningType")]
public string warningType { get; set; }
[JsonProperty("startTime")]
public string startTime { get; set; }
[JsonProperty("connKey")]
public string connKey { get; set; }
[JsonProperty("notiType")]
public string notiType { get; set; }
[JsonProperty("projectId")]
public string projectId { get; set; }
[JsonProperty("notiId")]
public string notiId { get; set; }
}
public class Ios
{
[JsonProperty("sound")]
public string sound { get; set; }
[JsonProperty("badge")]
public string badge { get; set; }
[JsonProperty("extras")]
public Extras2 extras { get; set; }
}
public class Notification
{
[JsonProperty("alert")]
public string alert { get; set; }
[JsonProperty("android")]
public Android android { get; set; }
[JsonProperty("ios")]
public Ios ios { get; set; }
}
public class Options
{
[JsonProperty("apns_production")]
public bool apns_production { get; set; }
}
public class TempRegIdsAndAlias
{
public string RegId { get; set; }
public string Alias { get; set; }
}
```