diff --git a/Yi.Abp.Net8/Yi.Abp.sln b/Yi.Abp.Net8/Yi.Abp.sln
index 19d7412b..f84b1031 100644
--- a/Yi.Abp.Net8/Yi.Abp.sln
+++ b/Yi.Abp.Net8/Yi.Abp.sln
@@ -170,6 +170,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Yi.Framework.DigitalCollect
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Yi.Framework.WeChat.MiniProgram", "framework\Yi.Framework.WeChat.MiniProgram\Yi.Framework.WeChat.MiniProgram.csproj", "{81CEA2ED-917B-41D8-BE0D-39A785B050C0}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Yi.Framework.BackgroundWorkers.Hangfire", "framework\Yi.Framework.BackgroundWorkers.Hangfire\Yi.Framework.BackgroundWorkers.Hangfire.csproj", "{862CA181-BEE6-4870-82D2-B662E527ED8C}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -428,6 +430,10 @@ Global
{81CEA2ED-917B-41D8-BE0D-39A785B050C0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{81CEA2ED-917B-41D8-BE0D-39A785B050C0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{81CEA2ED-917B-41D8-BE0D-39A785B050C0}.Release|Any CPU.Build.0 = Release|Any CPU
+ {862CA181-BEE6-4870-82D2-B662E527ED8C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {862CA181-BEE6-4870-82D2-B662E527ED8C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {862CA181-BEE6-4870-82D2-B662E527ED8C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {862CA181-BEE6-4870-82D2-B662E527ED8C}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -504,6 +510,7 @@ Global
{FFEC9DA6-1A13-480A-AE9E-2BF8763D3061} = {B8F76A6B-2EEB-4E64-9F26-D84584E16B9C}
{4CE6E4AE-0BA4-4984-A4F1-A9A414B1BB8F} = {B8F76A6B-2EEB-4E64-9F26-D84584E16B9C}
{81CEA2ED-917B-41D8-BE0D-39A785B050C0} = {77B949E9-530E-45A5-9657-20F7D5C6875C}
+ {862CA181-BEE6-4870-82D2-B662E527ED8C} = {77B949E9-530E-45A5-9657-20F7D5C6875C}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {23D6FBC9-C970-4641-BC1E-2AEA59F51C18}
diff --git a/Yi.Abp.Net8/framework/Yi.Framework.BackgroundWorkers.Hangfire/Yi.Framework.BackgroundWorkers.Hangfire.csproj b/Yi.Abp.Net8/framework/Yi.Framework.BackgroundWorkers.Hangfire/Yi.Framework.BackgroundWorkers.Hangfire.csproj
new file mode 100644
index 00000000..ee6c5ed7
--- /dev/null
+++ b/Yi.Abp.Net8/framework/Yi.Framework.BackgroundWorkers.Hangfire/Yi.Framework.BackgroundWorkers.Hangfire.csproj
@@ -0,0 +1,17 @@
+
+
+
+
+
+ net8.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
diff --git a/Yi.Abp.Net8/framework/Yi.Framework.BackgroundWorkers.Hangfire/YiFrameworkBackgroundWorkersHangfireModule.cs b/Yi.Abp.Net8/framework/Yi.Framework.BackgroundWorkers.Hangfire/YiFrameworkBackgroundWorkersHangfireModule.cs
new file mode 100644
index 00000000..b4aae0c3
--- /dev/null
+++ b/Yi.Abp.Net8/framework/Yi.Framework.BackgroundWorkers.Hangfire/YiFrameworkBackgroundWorkersHangfireModule.cs
@@ -0,0 +1,27 @@
+using Microsoft.Extensions.DependencyInjection;
+using Volo.Abp.BackgroundWorkers;
+using Volo.Abp.BackgroundWorkers.Hangfire;
+
+namespace Yi.Framework.BackgroundWorkers.Hangfire;
+
+[DependsOn(typeof(AbpBackgroundWorkersHangfireModule))]
+public class YiFrameworkBackgroundWorkersHangfireModule:AbpModule
+{
+ public override void PreConfigureServices(ServiceConfigurationContext context)
+ {
+ context.Services.AddConventionalRegistrar(new YiHangfireConventionalRegistrar());
+ }
+
+ public override async Task OnApplicationInitializationAsync(ApplicationInitializationContext context)
+ {
+ //定时任务自动注入,Abp默认只有在Quartz才实现
+ var backgroundWorkerManager = context.ServiceProvider.GetRequiredService();
+ var works = context.ServiceProvider.GetServices();
+
+ foreach (var work in works)
+ {
+ await backgroundWorkerManager.AddAsync(work);
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/Yi.Abp.Net8/framework/Yi.Framework.BackgroundWorkers.Hangfire/YiHangfireConventionalRegistrar.cs b/Yi.Abp.Net8/framework/Yi.Framework.BackgroundWorkers.Hangfire/YiHangfireConventionalRegistrar.cs
new file mode 100644
index 00000000..f8f99bad
--- /dev/null
+++ b/Yi.Abp.Net8/framework/Yi.Framework.BackgroundWorkers.Hangfire/YiHangfireConventionalRegistrar.cs
@@ -0,0 +1,20 @@
+using Volo.Abp.BackgroundWorkers.Hangfire;
+using Volo.Abp.DependencyInjection;
+
+namespace Yi.Framework.BackgroundWorkers.Hangfire;
+
+public class YiHangfireConventionalRegistrar : DefaultConventionalRegistrar
+{
+ protected override bool IsConventionalRegistrationDisabled(Type type)
+ {
+ return !typeof(IHangfireBackgroundWorker).IsAssignableFrom(type) || base.IsConventionalRegistrationDisabled(type);
+ }
+
+ protected override List GetExposedServiceTypes(Type type)
+ {
+ return new List()
+ {
+ typeof(IHangfireBackgroundWorker)
+ };
+ }
+}
diff --git a/Yi.Abp.Net8/module/bbs/Yi.Framework.Bbs.Application/Jobs/AccessLogCacheJob.cs b/Yi.Abp.Net8/module/bbs/Yi.Framework.Bbs.Application/Jobs/AccessLogCacheJob.cs
index ddedea02..63b3b4d0 100644
--- a/Yi.Abp.Net8/module/bbs/Yi.Framework.Bbs.Application/Jobs/AccessLogCacheJob.cs
+++ b/Yi.Abp.Net8/module/bbs/Yi.Framework.Bbs.Application/Jobs/AccessLogCacheJob.cs
@@ -1,8 +1,8 @@
using FreeRedis;
+using Hangfire;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Options;
-using Quartz;
-using Volo.Abp.BackgroundWorkers.Quartz;
+using Volo.Abp.BackgroundWorkers.Hangfire;
using Volo.Abp.Caching;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Entities;
@@ -15,23 +15,27 @@ using Yi.Framework.SqlSugarCore.Abstractions;
namespace Yi.Framework.Bbs.Application.Jobs;
-public class AccessLogCacheJob : QuartzBackgroundWorkerBase
+public class AccessLogCacheJob : HangfireBackgroundWorkerBase
{
private readonly ILocalEventBus _localEventBus;
public AccessLogCacheJob(ILocalEventBus localEventBus)
{
_localEventBus = localEventBus;
- JobDetail = JobBuilder.Create().WithIdentity(nameof(AccessLogCacheJob))
- .Build();
+ RecurringJobId = "访问日志写入缓存";
+ //每10秒执行一次,将本地缓存转入redis,防止丢数据
+ CronExpression = "*/10 * * * * *";
+ //
+ // JobDetail = JobBuilder.Create().WithIdentity(nameof(AccessLogCacheJob))
+ // .Build();
//每10秒执行一次,将本地缓存转入redis,防止丢数据
- Trigger = TriggerBuilder.Create().WithIdentity(nameof(AccessLogCacheJob))
- .WithSimpleSchedule((schedule) => { schedule.WithInterval(TimeSpan.FromSeconds(10)).RepeatForever(); })
- .Build();
+ // Trigger = TriggerBuilder.Create().WithIdentity(nameof(AccessLogCacheJob))
+ // .WithSimpleSchedule((schedule) => { schedule.WithInterval(TimeSpan.FromSeconds(10)).RepeatForever();; })
+ // .Build();
}
-
- public override async Task Execute(IJobExecutionContext context)
+
+ public override async Task DoWorkAsync(CancellationToken cancellationToken = new CancellationToken())
{
await _localEventBus.PublishAsync(new AccessLogResetArgs());
}
diff --git a/Yi.Abp.Net8/module/bbs/Yi.Framework.Bbs.Application/Jobs/AccessLogStoreJob.cs b/Yi.Abp.Net8/module/bbs/Yi.Framework.Bbs.Application/Jobs/AccessLogStoreJob.cs
index 66cc24d5..8fb30491 100644
--- a/Yi.Abp.Net8/module/bbs/Yi.Framework.Bbs.Application/Jobs/AccessLogStoreJob.cs
+++ b/Yi.Abp.Net8/module/bbs/Yi.Framework.Bbs.Application/Jobs/AccessLogStoreJob.cs
@@ -1,11 +1,9 @@
using FreeRedis;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Options;
-using Quartz;
-using Volo.Abp.BackgroundWorkers.Quartz;
+using Volo.Abp.BackgroundWorkers.Hangfire;
using Volo.Abp.Caching;
using Volo.Abp.DependencyInjection;
-using Volo.Abp.Domain.Entities;
using Yi.Framework.Bbs.Domain.Entities;
using Yi.Framework.Bbs.Domain.Shared.Caches;
using Yi.Framework.Bbs.Domain.Shared.Enums;
@@ -13,7 +11,7 @@ using Yi.Framework.SqlSugarCore.Abstractions;
namespace Yi.Framework.Bbs.Application.Jobs;
-public class AccessLogStoreJob : QuartzBackgroundWorkerBase
+public class AccessLogStoreJob : HangfireBackgroundWorkerBase
{
private readonly ISqlSugarRepository _repository;
@@ -45,18 +43,23 @@ public class AccessLogStoreJob : QuartzBackgroundWorkerBase
public AccessLogStoreJob(ISqlSugarRepository repository)
{
_repository = repository;
- JobDetail = JobBuilder.Create().WithIdentity(nameof(AccessLogStoreJob))
- .Build();
+
+ RecurringJobId = "访问日志写入数据库";
//每分钟执行一次
- Trigger = TriggerBuilder.Create().WithIdentity(nameof(AccessLogStoreJob))
- .WithCronSchedule("0 * * * * ?")
- .Build();
+ CronExpression = "0 * * * * ?";
+ // JobDetail = JobBuilder.Create().WithIdentity(nameof(AccessLogStoreJob))
+ // .Build();
+ // //每分钟执行一次
+ // Trigger = TriggerBuilder.Create().WithIdentity(nameof(AccessLogStoreJob))
+ // .WithCronSchedule("0 * * * * ?")
+ // .Build();
}
+
- public override async Task Execute(IJobExecutionContext context)
+ public override async Task DoWorkAsync(CancellationToken cancellationToken = new CancellationToken())
{
if (EnableRedisCache)
{
diff --git a/Yi.Abp.Net8/module/bbs/Yi.Framework.Bbs.Application/Jobs/AssignmentExpireTimeOutJob.cs b/Yi.Abp.Net8/module/bbs/Yi.Framework.Bbs.Application/Jobs/AssignmentExpireTimeOutJob.cs
index 937fb689..1238c979 100644
--- a/Yi.Abp.Net8/module/bbs/Yi.Framework.Bbs.Application/Jobs/AssignmentExpireTimeOutJob.cs
+++ b/Yi.Abp.Net8/module/bbs/Yi.Framework.Bbs.Application/Jobs/AssignmentExpireTimeOutJob.cs
@@ -1,5 +1,4 @@
-using Quartz;
-using Volo.Abp.BackgroundWorkers.Quartz;
+using Volo.Abp.BackgroundWorkers.Hangfire;
using Yi.Framework.Bbs.Domain.Managers;
namespace Yi.Framework.Bbs.Application.Jobs;
@@ -7,20 +6,25 @@ namespace Yi.Framework.Bbs.Application.Jobs;
///
/// 每日任务job
///
-public class AssignmentExpireTimeOutJob : QuartzBackgroundWorkerBase
+public class AssignmentExpireTimeOutJob : HangfireBackgroundWorkerBase
{
private readonly AssignmentManager _assignmentManager;
public AssignmentExpireTimeOutJob(AssignmentManager assignmentManager)
{
_assignmentManager = assignmentManager;
- JobDetail = JobBuilder.Create().WithIdentity(nameof(AssignmentExpireTimeOutJob)).Build();
- //每个小时整点执行一次
- Trigger = TriggerBuilder.Create().WithIdentity(nameof(AssignmentExpireTimeOutJob)).WithCronSchedule("0 0 * * * ?")
- .Build();
+
+ RecurringJobId = "每日任务系统超时检测";
+ //每分钟执行一次
+ CronExpression = "0 * * * * ?";
+ //
+ // JobDetail = JobBuilder.Create().WithIdentity(nameof(AssignmentExpireTimeOutJob)).Build();
+ // //每个小时整点执行一次
+ // Trigger = TriggerBuilder.Create().WithIdentity(nameof(AssignmentExpireTimeOutJob)).WithCronSchedule("0 0 * * * ?")
+ // .Build();
}
-
- public override async Task Execute(IJobExecutionContext context)
+
+ public override async Task DoWorkAsync(CancellationToken cancellationToken = new CancellationToken())
{
await _assignmentManager.ExpireTimeoutAsync();
}
diff --git a/Yi.Abp.Net8/module/bbs/Yi.Framework.Bbs.Application/Jobs/InterestRecordsJob.cs b/Yi.Abp.Net8/module/bbs/Yi.Framework.Bbs.Application/Jobs/InterestRecordsJob.cs
index 80837a9e..85bfafdd 100644
--- a/Yi.Abp.Net8/module/bbs/Yi.Framework.Bbs.Application/Jobs/InterestRecordsJob.cs
+++ b/Yi.Abp.Net8/module/bbs/Yi.Framework.Bbs.Application/Jobs/InterestRecordsJob.cs
@@ -1,20 +1,24 @@
-using Quartz;
-using Volo.Abp.BackgroundWorkers.Quartz;
+using Volo.Abp.BackgroundWorkers.Hangfire;
using Yi.Framework.Bbs.Domain.Managers;
namespace Yi.Framework.Bbs.Application.Jobs
{
- public class InterestRecordsJob : QuartzBackgroundWorkerBase
+ public class InterestRecordsJob : HangfireBackgroundWorkerBase
{
private BankManager _bankManager;
public InterestRecordsJob(BankManager bankManager)
{
_bankManager = bankManager;
- JobDetail = JobBuilder.Create().WithIdentity(nameof(InterestRecordsJob)).Build();
-
+
+ RecurringJobId = "银行利息积分刷新";
//每个小时整点执行一次
-
- Trigger = TriggerBuilder.Create().WithIdentity(nameof(InterestRecordsJob)).WithCronSchedule("0 0 * * * ?").Build();
+ CronExpression = "0 0 * * * ?";
+
+ // JobDetail = JobBuilder.Create().WithIdentity(nameof(InterestRecordsJob)).Build();
+ //
+ // //每个小时整点执行一次
+ //
+ // Trigger = TriggerBuilder.Create().WithIdentity(nameof(InterestRecordsJob)).WithCronSchedule("0 0 * * * ?").Build();
//测试
// Trigger = TriggerBuilder.Create().WithIdentity(nameof(InterestRecordsJob))
@@ -23,7 +27,8 @@ namespace Yi.Framework.Bbs.Application.Jobs
// .RepeatForever())
//.Build();
}
- public override async Task Execute(IJobExecutionContext context)
+
+ public override async Task DoWorkAsync(CancellationToken cancellationToken = new CancellationToken())
{
//创建一个记录,莫得了
await _bankManager.GetCurrentInterestRate();
diff --git a/Yi.Abp.Net8/module/bbs/Yi.Framework.Bbs.Application/Services/BbsUserInfoService.cs b/Yi.Abp.Net8/module/bbs/Yi.Framework.Bbs.Application/Services/BbsUserInfoService.cs
index 0e93ced2..91c0c739 100644
--- a/Yi.Abp.Net8/module/bbs/Yi.Framework.Bbs.Application/Services/BbsUserInfoService.cs
+++ b/Yi.Abp.Net8/module/bbs/Yi.Framework.Bbs.Application/Services/BbsUserInfoService.cs
@@ -27,13 +27,19 @@ namespace Yi.Framework.Bbs.Application.Services
var userEntity = await _bbsUserManager._userRepository.GetFirstAsync(x => x.UserName == userNameOrUserId);
if (userEntity == null)
{
- throw new Volo.Abp.UserFriendlyException("该用户不存在");
+ throw new UserFriendlyException("该用户不存在");
}
userId= userEntity.Id;
}
var output =await _bbsUserManager.GetBbsUserInfoAsync(userId);
-
+
+ //不是自己
+ if (CurrentUser.Id != output.Id)
+ {
+ output.Phone = null;
+ output.Email=null;
+ }
return output!;
}
}
diff --git a/Yi.Abp.Net8/module/bbs/Yi.Framework.Bbs.Application/Services/Forum/CommentService.cs b/Yi.Abp.Net8/module/bbs/Yi.Framework.Bbs.Application/Services/Forum/CommentService.cs
index 52db5120..b8926f13 100644
--- a/Yi.Abp.Net8/module/bbs/Yi.Framework.Bbs.Application/Services/Forum/CommentService.cs
+++ b/Yi.Abp.Net8/module/bbs/Yi.Framework.Bbs.Application/Services/Forum/CommentService.cs
@@ -136,6 +136,11 @@ namespace Yi.Framework.Bbs.Application.Services.Forum
[Authorize]
public override async Task CreateAsync(CommentCreateInputVo input)
{
+ if (input.Content.Length<=6)
+ {
+ throw new UserFriendlyException("评论长度至少大于6");
+ }
+
var discuess = await _discussRepository.GetFirstAsync(x => x.Id == input.DiscussId);
if (discuess is null)
{
diff --git a/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Application/Jobs/BackupDataBaseJob.cs b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Application/Jobs/BackupDataBaseJob.cs
index 7db58b06..88398f87 100644
--- a/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Application/Jobs/BackupDataBaseJob.cs
+++ b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Application/Jobs/BackupDataBaseJob.cs
@@ -6,16 +6,14 @@ using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
-using Quartz;
-using Quartz.Logging;
-using Volo.Abp.BackgroundWorkers.Quartz;
+using Volo.Abp.BackgroundWorkers.Hangfire;
using Volo.Abp.Domain.Repositories;
using Yi.Framework.Rbac.Domain.Shared.Options;
using Yi.Framework.SqlSugarCore.Abstractions;
namespace Yi.Framework.Rbac.Application.Jobs
{
- public class BackupDataBaseJob : QuartzBackgroundWorkerBase
+ public class BackupDataBaseJob: HangfireBackgroundWorkerBase
{
private ISqlSugarDbContext _dbContext;
private IOptions _options;
@@ -24,13 +22,12 @@ namespace Yi.Framework.Rbac.Application.Jobs
_options = options;
_dbContext = dbContext;
- JobDetail = JobBuilder.Create().WithIdentity(nameof(BackupDataBaseJob)).Build();
-
+
+ RecurringJobId = "数据库备份";
//每天00点与24点进行备份
- Trigger = TriggerBuilder.Create().WithIdentity(nameof(BackupDataBaseJob)).WithCronSchedule("0 0 0,12 * * ? ").Build();
- //Trigger = TriggerBuilder.Create().WithIdentity(nameof(BackupDataBaseJob)).WithSimpleSchedule(x=>x.WithIntervalInSeconds(10)).Build();
+ CronExpression = "0 0 0,12 * * ? ";
}
- public override Task Execute(IJobExecutionContext context)
+ public override Task DoWorkAsync(CancellationToken cancellationToken = new CancellationToken())
{
if (_options.Value.EnableDataBaseBackup)
{
diff --git a/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Application/Services/Monitor/TaskService.cs b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Application/Services/Monitor/TaskService.cs
deleted file mode 100644
index ab857fb6..00000000
--- a/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Application/Services/Monitor/TaskService.cs
+++ /dev/null
@@ -1,220 +0,0 @@
-using System.Reflection;
-using Mapster;
-using Microsoft.AspNetCore.Mvc;
-using Quartz;
-using Quartz.Impl.Matchers;
-using Volo.Abp;
-using Volo.Abp.Application.Dtos;
-using Volo.Abp.Application.Services;
-using Volo.Abp.Timing;
-using Yi.Framework.Rbac.Application.Contracts.Dtos.Task;
-using Yi.Framework.Rbac.Application.Contracts.IServices;
-using Yi.Framework.Rbac.Domain.Shared.Enums;
-
-namespace Yi.Framework.Rbac.Application.Services.Monitor
-{
- public class TaskService : ApplicationService, ITaskService
- {
- private readonly ISchedulerFactory _schedulerFactory;
- private readonly IClock _clock;
- public TaskService(ISchedulerFactory schedulerFactory, IClock clock)
- {
- _clock = clock;
- _schedulerFactory = schedulerFactory;
- }
-
-
- ///
- /// 单查job
- ///
- ///
- ///
- [HttpGet("task/{jobId}")]
- public async Task GetAsync([FromRoute] string jobId)
- {
- var scheduler = await _schedulerFactory.GetScheduler();
-
- var jobDetail = await scheduler.GetJobDetail(new JobKey(jobId));
- var trigger = (await scheduler.GetTriggersOfJob(new JobKey(jobId))).First();
- //状态
- var state = await scheduler.GetTriggerState(trigger.Key);
-
-
- var output = new TaskGetOutput
- {
- JobId = jobDetail.Key.Name,
- GroupName = jobDetail.Key.Group,
- JobType = jobDetail.JobType.Name,
- Properties = Newtonsoft.Json.JsonConvert.SerializeObject(jobDetail.JobDataMap),
- Concurrent = !jobDetail.ConcurrentExecutionDisallowed,
- Description = jobDetail.Description,
- LastRunTime = _clock.Normalize(trigger.GetPreviousFireTimeUtc()?.DateTime ?? DateTime.MinValue),
- NextRunTime = _clock.Normalize(trigger.GetNextFireTimeUtc()?.DateTime ?? DateTime.MinValue),
- AssemblyName = jobDetail.JobType.Assembly.GetName().Name,
- Status = state.ToString()
- };
-
- if (trigger is ISimpleTrigger simple)
- {
- output.TriggerArgs = Math.Round(simple.RepeatInterval.TotalMinutes, 2).ToString() + "分钟";
- output.Type = JobTypeEnum.Millisecond;
- output.Millisecond = simple.RepeatInterval.TotalMilliseconds;
- }
- else if (trigger is ICronTrigger cron)
- {
- output.TriggerArgs = cron.CronExpressionString!;
- output.Type = JobTypeEnum.Cron;
- output.Cron = cron.CronExpressionString;
- }
- return output;
- }
-
- ///
- /// 多查job
- ///
- ///
- public async Task> GetListAsync([FromQuery] TaskGetListInput input)
- {
- var items = new List();
-
- var scheduler = await _schedulerFactory.GetScheduler();
-
- var groups = await scheduler.GetJobGroupNames();
-
- foreach (var groupName in groups)
- {
- foreach (var jobKey in await scheduler.GetJobKeys(GroupMatcher.GroupEquals(groupName)))
- {
- string jobName = jobKey.Name;
- string jobGroup = jobKey.Group;
- var triggers = (await scheduler.GetTriggersOfJob(jobKey)).First();
- items.Add(await GetAsync(jobName));
- }
- }
-
-
- var output = items.Skip((input.SkipCount - 1) * input.MaxResultCount).Take(input.MaxResultCount)
- .OrderByDescending(x => x.LastRunTime)
- .ToList();
- return new PagedResultDto(items.Count(), output.Adapt>());
- }
-
- ///
- /// 创建job
- ///
- ///
- ///
- public async Task CreateAsync(TaskCreateInput input)
- {
- var scheduler = await _schedulerFactory.GetScheduler();
-
- //设置启动时执行一次,然后最大只执行一次
-
-
- //jobBuilder
- var jobClassType = Assembly.Load(input.AssemblyName).GetTypes().Where(x => x.Name == input.JobType).FirstOrDefault();
-
- if (jobClassType is null)
- {
- throw new UserFriendlyException($"程序集:{input.AssemblyName},{input.JobType} 不存在");
- }
-
- var jobBuilder = JobBuilder.Create(jobClassType).WithIdentity(new JobKey(input.JobId, input.GroupName))
- .WithDescription(input.Description);
- if (!input.Concurrent)
- {
- jobBuilder.DisallowConcurrentExecution();
- }
-
- //triggerBuilder
- TriggerBuilder triggerBuilder = null;
- switch (input.Type)
- {
- case JobTypeEnum.Cron:
- triggerBuilder =
- TriggerBuilder.Create()
- .WithCronSchedule(input.Cron);
-
-
-
-
- break;
- case JobTypeEnum.Millisecond:
- triggerBuilder =
- TriggerBuilder.Create().StartNow()
- .WithSimpleSchedule(x => x
- .WithInterval(TimeSpan.FromMilliseconds(input.Millisecond ?? 10000))
- .RepeatForever()
- );
- break;
- }
-
- //作业计划,单个jobBuilder与多个triggerBuilder组合
- await scheduler.ScheduleJob(jobBuilder.Build(), triggerBuilder.Build());
- }
-
- ///
- /// 移除job
- ///
- ///
- ///
- public async Task DeleteAsync(IEnumerable id)
- {
- var scheduler = await _schedulerFactory.GetScheduler();
- await scheduler.DeleteJobs(id.Select(x => new JobKey(x)).ToList());
- }
-
- ///
- /// 暂停job
- ///
- ///
- ///
- [HttpPut]
- public async Task PauseAsync(string jobId)
- {
- var scheduler = await _schedulerFactory.GetScheduler();
- await scheduler.PauseJob(new JobKey(jobId));
- }
-
- ///
- /// 开始job
- ///
- ///
- ///
- [HttpPut]
- public async Task StartAsync(string jobId)
- {
- var scheduler = await _schedulerFactory.GetScheduler();
- await scheduler.ResumeJob(new JobKey(jobId));
- }
-
- ///
- /// 更新job
- ///
- ///
- ///
- ///
- public async Task UpdateAsync(string id, TaskUpdateInput input)
- {
- await DeleteAsync(new List() { id });
- await CreateAsync(input.Adapt());
- }
-
- [HttpPost("task/run-once/{id}")]
- public async Task RunOnceAsync([FromRoute] string id)
- {
- var scheduler = await _schedulerFactory.GetScheduler();
- var jobDetail = await scheduler.GetJobDetail(new JobKey(id));
-
- var jobBuilder = JobBuilder.Create(jobDetail.JobType).WithIdentity(new JobKey(Guid.NewGuid().ToString()));
- //设置启动时执行一次,然后最大只执行一次
- var trigger = TriggerBuilder.Create().WithIdentity(Guid.NewGuid().ToString()).StartNow()
- .WithSimpleSchedule(x => x
- .WithIntervalInHours(1)
- .WithRepeatCount(1))
- .Build();
-
- await scheduler.ScheduleJob(jobBuilder.Build(), trigger);
- }
- }
-}
diff --git a/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Application/Yi.Framework.Rbac.Application.csproj b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Application/Yi.Framework.Rbac.Application.csproj
index b9536345..81a3a0d9 100644
--- a/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Application/Yi.Framework.Rbac.Application.csproj
+++ b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Application/Yi.Framework.Rbac.Application.csproj
@@ -10,13 +10,15 @@
-
+
+
+
diff --git a/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Application/YiFrameworkRbacApplicationModule.cs b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Application/YiFrameworkRbacApplicationModule.cs
index 13d07949..c06f32cd 100644
--- a/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Application/YiFrameworkRbacApplicationModule.cs
+++ b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Application/YiFrameworkRbacApplicationModule.cs
@@ -2,7 +2,7 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp;
using Volo.Abp.BackgroundWorkers;
-using Volo.Abp.BackgroundWorkers.Quartz;
+using Volo.Abp.BackgroundWorkers.Hangfire;
using Volo.Abp.Modularity;
using Yi.Framework.Ddd.Application;
using Yi.Framework.Rbac.Application.Contracts;
@@ -16,8 +16,7 @@ namespace Yi.Framework.Rbac.Application
typeof(YiFrameworkRbacDomainModule),
- typeof(YiFrameworkDddApplicationModule),
- typeof(AbpBackgroundWorkersQuartzModule)
+ typeof(YiFrameworkDddApplicationModule)
)]
public class YiFrameworkRbacApplicationModule : AbpModule
{
@@ -28,7 +27,6 @@ namespace Yi.Framework.Rbac.Application
service.AddCaptcha(options =>
{
options.CaptchaType = CaptchaType.ARITHMETIC;
-
});
}
diff --git a/Yi.Abp.Net8/src/Yi.Abp.Application/Jobs/DemoResetJob.cs b/Yi.Abp.Net8/src/Yi.Abp.Application/Jobs/DemoResetJob.cs
new file mode 100644
index 00000000..86c60a08
--- /dev/null
+++ b/Yi.Abp.Net8/src/Yi.Abp.Application/Jobs/DemoResetJob.cs
@@ -0,0 +1,53 @@
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.Logging;
+using Volo.Abp.BackgroundWorkers.Hangfire;
+using Volo.Abp.Data;
+using Yi.Framework.Rbac.Domain.Entities;
+using Yi.Framework.SqlSugarCore.Abstractions;
+
+namespace Yi.Abp.Application.Jobs
+{
+ public class DemoResetJob : HangfireBackgroundWorkerBase
+ {
+ private ISqlSugarDbContext _dbContext;
+ private ILogger _logger => LoggerFactory.CreateLogger();
+ private IDataSeeder _dataSeeder;
+ private IConfiguration _configuration;
+ public DemoResetJob(ISqlSugarDbContext dbContext, IDataSeeder dataSeeder, IConfiguration configuration)
+ {
+ _dbContext = dbContext;
+ RecurringJobId = "重置demo环境";
+ //每天1点和13点进行重置demo环境
+ CronExpression = "0 0 1,13 * * ?";
+
+ _dataSeeder = dataSeeder;
+ _configuration = configuration;
+ }
+
+ public override async Task DoWorkAsync(CancellationToken cancellationToken = new CancellationToken())
+ {
+ //开启演示环境重置功能
+ if (_configuration.GetSection("EnableDemoReset").Get())
+ {
+ //定时任务,非常简单
+ _logger.LogWarning("演示环境正在还原!");
+ var db = _dbContext.SqlSugarClient.CopyNew();
+ db.DbMaintenance.TruncateTable();
+ db.DbMaintenance.TruncateTable();
+ db.DbMaintenance.TruncateTable();
+ db.DbMaintenance.TruncateTable();
+ db.DbMaintenance.TruncateTable();
+ db.DbMaintenance.TruncateTable();
+ db.DbMaintenance.TruncateTable();
+ db.DbMaintenance.TruncateTable();
+ db.DbMaintenance.TruncateTable();
+
+ //删除种子数据
+ await _dataSeeder.SeedAsync();
+ _logger.LogWarning("演示环境还原成功!");
+
+ }
+
+ }
+ }
+}
diff --git a/Yi.Abp.Net8/src/Yi.Abp.Application/Jobs/TestJob.cs b/Yi.Abp.Net8/src/Yi.Abp.Application/Jobs/TestJob.cs
index e0b68065..9c098146 100644
--- a/Yi.Abp.Net8/src/Yi.Abp.Application/Jobs/TestJob.cs
+++ b/Yi.Abp.Net8/src/Yi.Abp.Application/Jobs/TestJob.cs
@@ -1,6 +1,6 @@
-using Quartz;
+using Hangfire;
using SqlSugar;
-using Volo.Abp.BackgroundWorkers.Quartz;
+using Volo.Abp.BackgroundWorkers.Hangfire;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Uow;
using Yi.Framework.Rbac.Domain.Entities;
@@ -11,26 +11,21 @@ namespace Yi.Abp.Application.Jobs
///
/// 定时任务
///
- public class TestJob : QuartzBackgroundWorkerBase
+ public class TestJob : HangfireBackgroundWorkerBase
{
private ISqlSugarRepository _repository;
public TestJob(ISqlSugarRepository repository)
{
_repository = repository;
- JobDetail = JobBuilder.Create().WithIdentity(nameof(TestJob)).Build();
- Trigger = TriggerBuilder.Create().WithIdentity(nameof(TestJob)).StartNow()
- .WithSimpleSchedule(x => x
- .WithIntervalInSeconds(1000 * 60)
- .RepeatForever())
- .Build();
+ RecurringJobId = "测试";
+ //每天一次
+ CronExpression = Cron.Daily();
}
- public override async Task Execute(IJobExecutionContext context)
+ public override Task DoWorkAsync(CancellationToken cancellationToken = new CancellationToken())
{
//定时任务,非常简单
Console.WriteLine("你好,世界");
- // var eneities= await _repository.GetListAsync();
- //var entities= await _sqlSugarClient.Queryable().ToListAsync();
- //await Console.Out.WriteLineAsync(entities.Count().ToString());
+ return Task.CompletedTask;
}
}
}
diff --git a/Yi.Abp.Net8/src/Yi.Abp.Application/Yi.Abp.Application.csproj b/Yi.Abp.Net8/src/Yi.Abp.Application/Yi.Abp.Application.csproj
index 1e3004b7..b63ee650 100644
--- a/Yi.Abp.Net8/src/Yi.Abp.Application/Yi.Abp.Application.csproj
+++ b/Yi.Abp.Net8/src/Yi.Abp.Application/Yi.Abp.Application.csproj
@@ -3,6 +3,7 @@
+
diff --git a/Yi.Abp.Net8/src/Yi.Abp.Application/YiAbpApplicationModule.cs b/Yi.Abp.Net8/src/Yi.Abp.Application/YiAbpApplicationModule.cs
index 10a5ec75..679cfa36 100644
--- a/Yi.Abp.Net8/src/Yi.Abp.Application/YiAbpApplicationModule.cs
+++ b/Yi.Abp.Net8/src/Yi.Abp.Application/YiAbpApplicationModule.cs
@@ -1,6 +1,7 @@
using Volo.Abp.SettingManagement;
using Yi.Abp.Application.Contracts;
using Yi.Abp.Domain;
+using Yi.Framework.BackgroundWorkers.Hangfire;
using Yi.Framework.Bbs.Application;
using Yi.Framework.ChatHub.Application;
using Yi.Framework.CodeGen.Application;
@@ -25,7 +26,8 @@ namespace Yi.Abp.Application
typeof(YiFrameworkCodeGenApplicationModule),
typeof (YiFrameworkSettingManagementApplicationModule),
- typeof(YiFrameworkDddApplicationModule)
+ typeof(YiFrameworkDddApplicationModule),
+ typeof(YiFrameworkBackgroundWorkersHangfireModule)
)]
public class YiAbpApplicationModule : AbpModule
{
diff --git a/Yi.Abp.Net8/src/Yi.Abp.Web/Yi.Abp.Web.csproj b/Yi.Abp.Net8/src/Yi.Abp.Web/Yi.Abp.Web.csproj
index f50d8a24..2623b61f 100644
--- a/Yi.Abp.Net8/src/Yi.Abp.Web/Yi.Abp.Web.csproj
+++ b/Yi.Abp.Net8/src/Yi.Abp.Web/Yi.Abp.Web.csproj
@@ -8,6 +8,8 @@
+
+
diff --git a/Yi.Abp.Net8/src/Yi.Abp.Web/YiAbpWebModule.cs b/Yi.Abp.Net8/src/Yi.Abp.Web/YiAbpWebModule.cs
index f1ab5ae7..bcce54e0 100644
--- a/Yi.Abp.Net8/src/Yi.Abp.Web/YiAbpWebModule.cs
+++ b/Yi.Abp.Net8/src/Yi.Abp.Web/YiAbpWebModule.cs
@@ -3,6 +3,9 @@ using System.Text;
using System.Text.Json.Serialization;
using System.Text.Json.Serialization.Metadata;
using System.Threading.RateLimiting;
+using Hangfire;
+using Hangfire.MemoryStorage;
+using Hangfire.Redis.StackExchange;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.Mvc;
@@ -12,20 +15,21 @@ using Microsoft.AspNetCore.StaticFiles;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using Microsoft.OpenApi.Models;
-using Newtonsoft.Json.Converters;
+using StackExchange.Redis;
+using Volo.Abp.AspNetCore.Auditing;
using Volo.Abp.AspNetCore.Authentication.JwtBearer;
using Volo.Abp.AspNetCore.ExceptionHandling;
using Volo.Abp.AspNetCore.MultiTenancy;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc.AntiForgery;
-using Volo.Abp.AspNetCore.Mvc.ExceptionHandling;
using Volo.Abp.AspNetCore.Serilog;
using Volo.Abp.AspNetCore.VirtualFileSystem;
using Volo.Abp.Auditing;
using Volo.Abp.Autofac;
+using Volo.Abp.BackgroundJobs.Hangfire;
+using Volo.Abp.BackgroundWorkers;
+using Volo.Abp.BackgroundWorkers.Hangfire;
using Volo.Abp.Caching;
-using Volo.Abp.Json;
-using Volo.Abp.Json.SystemTextJson;
using Volo.Abp.MultiTenancy;
using Volo.Abp.Swashbuckle;
using Yi.Abp.Application;
@@ -36,7 +40,7 @@ using Yi.Framework.AspNetCore.Authentication.OAuth.Gitee;
using Yi.Framework.AspNetCore.Authentication.OAuth.QQ;
using Yi.Framework.AspNetCore.Microsoft.AspNetCore.Builder;
using Yi.Framework.AspNetCore.Microsoft.Extensions.DependencyInjection;
-using Yi.Framework.AspNetCore.UnifyResult;
+using Yi.Framework.BackgroundWorkers.Hangfire;
using Yi.Framework.Bbs.Application;
using Yi.Framework.Bbs.Application.Extensions;
using Yi.Framework.ChatHub.Application;
@@ -60,6 +64,8 @@ namespace Yi.Abp.Web
typeof(AbpSwashbuckleModule),
typeof(AbpAspNetCoreSerilogModule),
typeof(AbpAuditingModule),
+ typeof(YiFrameworkBackgroundWorkersHangfireModule),
+ typeof(AbpBackgroundJobsHangfireModule),
typeof(AbpAspNetCoreAuthenticationJwtBearerModule),
typeof(YiFrameworkAspNetCoreModule),
typeof(YiFrameworkAspNetCoreAuthenticationOAuthModule)
@@ -73,21 +79,26 @@ namespace Yi.Abp.Web
var configuration = context.Services.GetConfiguration();
var host = context.Services.GetHostingEnvironment();
var service = context.Services;
+
//请求日志
Configure(optios =>
{
//默认关闭,开启会有大量的审计日志
optios.IsEnabled = true;
- //审计日志过滤器,符合条件的才记录
- optios.AlwaysLogSelectors.Add(x => Task.FromResult(x.Url is null?true:!x.Url.StartsWith("/api/app/file/")));
});
-
+ //忽略审计日志路径
+ Configure(options =>
+ {
+ options.IgnoredUrls.Add("/api/app/file/");
+ options.IgnoredUrls.Add("/hangfire");
+ });
+
//采用furion格式的规范化api,默认不开启,使用abp优雅的方式
- //你没看错。。。
- //service.AddFurionUnifyResultApi();
+ //你没看错。。。
+ //service.AddFurionUnifyResultApi();
- //配置错误处理显示详情
- Configure(options => { options.SendExceptionsDetailsToClients = true; });
+ //配置错误处理显示详情
+ Configure(options => { options.SendExceptionsDetailsToClients = true; });
//动态Api
Configure(options =>
@@ -110,181 +121,203 @@ namespace Yi.Abp.Web
options.ConventionalControllers.ConventionalControllerSettings.ForEach(x => x.RootPath = "api/app");
});
- //【NewtonsoftJson严重问题!!!!!逆天】设置api格式,留给后人铭记
- // service.AddControllers().AddNewtonsoftJson(options =>
- // {
- // options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss";
- // options.SerializerSettings.Converters.Add(new StringEnumConverter());
- // });
-
- //请使用微软的,注意abp date又包了一层,采用DefaultJsonTypeInfoResolver统一覆盖
- Configure(options =>
- {
- options.JsonSerializerOptions.TypeInfoResolver = new DefaultJsonTypeInfoResolver();
- options.JsonSerializerOptions.Converters.Add(new DatetimeJsonConverter());
- options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
- });
+ //【NewtonsoftJson严重问题!!!!!逆天】设置api格式,留给后人铭记
+ // service.AddControllers().AddNewtonsoftJson(options =>
+ // {
+ // options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss";
+ // options.SerializerSettings.Converters.Add(new StringEnumConverter());
+ // });
- //设置缓存不要过期,默认滑动20分钟
- Configure(cacheOptions =>
- {
- cacheOptions.GlobalCacheEntryOptions.SlidingExpiration = null;
- //缓存key前缀
- cacheOptions.KeyPrefix = "Yi:";
- });
-
-
- Configure(options => { options.AutoValidate = false; });
-
- //Swagger
- context.Services.AddYiSwaggerGen(options =>
- {
- options.SwaggerDoc("default",
- new OpenApiInfo { Title = "Yi.Framework.Abp", Version = "v1", Description = "集大成者" });
- });
-
- //跨域
- context.Services.AddCors(options =>
- {
- options.AddPolicy(DefaultCorsPolicyName, builder =>
+ //请使用微软的,注意abp date又包了一层,采用DefaultJsonTypeInfoResolver统一覆盖
+ Configure(options =>
{
- builder
- .WithOrigins(
- configuration["App:CorsOrigins"]!
- .Split(";", StringSplitOptions.RemoveEmptyEntries)
- .Select(o => o.RemovePostFix("/"))
- .ToArray()
- )
- .WithAbpExposedHeaders()
- .SetIsOriginAllowedToAllowWildcardSubdomains()
- .AllowAnyHeader()
- .AllowAnyMethod()
- .AllowCredentials();
+ options.JsonSerializerOptions.TypeInfoResolver = new DefaultJsonTypeInfoResolver();
+ options.JsonSerializerOptions.Converters.Add(new DatetimeJsonConverter());
+ options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
});
- });
- //配置多租户
- Configure(options =>
- {
- //基于cookie jwt不好用,有坑
- options.TenantResolvers.Clear();
- options.TenantResolvers.Add(new HeaderTenantResolveContributor());
- //options.TenantResolvers.Add(new HeaderTenantResolveContributor());
- //options.TenantResolvers.Add(new CookieTenantResolveContributor());
-
- //options.TenantResolvers.RemoveAll(x => x.Name == CookieTenantResolveContributor.ContributorName);
- });
-
- //速率限制
- //每60秒限制100个请求,滑块添加,分6段
- service.AddRateLimiter(_ =>
- {
- _.RejectionStatusCode = StatusCodes.Status429TooManyRequests;
- _.OnRejected = (context, _) =>
+ //设置缓存不要过期,默认滑动20分钟
+ Configure(cacheOptions =>
{
- if (context.Lease.TryGetMetadata(MetadataName.RetryAfter, out var retryAfter))
+ cacheOptions.GlobalCacheEntryOptions.SlidingExpiration = null;
+ //缓存key前缀
+ cacheOptions.KeyPrefix = "Yi:";
+ });
+
+
+ Configure(options => { options.AutoValidate = false; });
+
+ //Swagger
+ context.Services.AddYiSwaggerGen(options =>
+ {
+ options.SwaggerDoc("default",
+ new OpenApiInfo { Title = "Yi.Framework.Abp", Version = "v1", Description = "集大成者" });
+ });
+
+ //跨域
+ context.Services.AddCors(options =>
+ {
+ options.AddPolicy(DefaultCorsPolicyName, builder =>
{
- context.HttpContext.Response.Headers.RetryAfter =
- ((int)retryAfter.TotalSeconds).ToString(NumberFormatInfo.InvariantInfo);
+ builder
+ .WithOrigins(
+ configuration["App:CorsOrigins"]!
+ .Split(";", StringSplitOptions.RemoveEmptyEntries)
+ .Select(o => o.RemovePostFix("/"))
+ .ToArray()
+ )
+ .WithAbpExposedHeaders()
+ .SetIsOriginAllowedToAllowWildcardSubdomains()
+ .AllowAnyHeader()
+ .AllowAnyMethod()
+ .AllowCredentials();
+ });
+ });
+
+ //配置多租户
+ Configure(options =>
+ {
+ //基于cookie jwt不好用,有坑
+ options.TenantResolvers.Clear();
+ options.TenantResolvers.Add(new HeaderTenantResolveContributor());
+ //options.TenantResolvers.Add(new HeaderTenantResolveContributor());
+ //options.TenantResolvers.Add(new CookieTenantResolveContributor());
+ //options.TenantResolvers.RemoveAll(x => x.Name == CookieTenantResolveContributor.ContributorName);
+ });
+
+ //配置Hangfire定时任务存储,开启redis后,优先使用redis
+ var redisConfiguration = configuration["Redis:Configuration"];
+ var redisEnabled = configuration["Redis:IsEnabled"];
+ context.Services.AddHangfire(config =>
+ {
+ if (redisEnabled.IsNullOrEmpty() || bool.Parse(redisEnabled))
+ {
+ config.UseRedisStorage(
+ ConnectionMultiplexer.Connect(redisConfiguration),
+ new RedisStorageOptions()
+ {
+ InvisibilityTimeout = TimeSpan.FromHours(1), //JOB允许执行1小时
+ Prefix = "Yi:HangfireJob:"
+ }).WithJobExpirationTimeout(TimeSpan.FromHours(1));
}
-
- context.HttpContext.Response.StatusCode = StatusCodes.Status429TooManyRequests;
- context.HttpContext.Response.WriteAsync("Too many requests. Please try again later.");
-
- return new ValueTask();
- };
-
- //全局使用,链式表达式
- _.GlobalLimiter = PartitionedRateLimiter.CreateChained(
- PartitionedRateLimiter.Create(httpContext =>
+ else
{
- var userAgent = httpContext.Request.Headers.UserAgent.ToString();
+ config.UseMemoryStorage();
+ }
+ });
- return RateLimitPartition.GetSlidingWindowLimiter
- (userAgent, _ =>
- new SlidingWindowRateLimiterOptions
- {
- PermitLimit = 1000,
- Window = TimeSpan.FromSeconds(60),
- SegmentsPerWindow = 6,
- QueueProcessingOrder = QueueProcessingOrder.OldestFirst
- });
- }));
- });
-
-
- //jwt鉴权
- var jwtOptions = configuration.GetSection(nameof(JwtOptions)).Get();
- var refreshJwtOptions = configuration.GetSection(nameof(RefreshJwtOptions)).Get();
-
- context.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
- .AddJwtBearer(options =>
+ //速率限制
+ //每60秒限制100个请求,滑块添加,分6段
+ service.AddRateLimiter(_ =>
{
- options.TokenValidationParameters = new TokenValidationParameters
+ _.RejectionStatusCode = StatusCodes.Status429TooManyRequests;
+ _.OnRejected = (context, _) =>
{
- ClockSkew = TimeSpan.Zero,
- ValidateIssuerSigningKey = true,
- ValidIssuer = jwtOptions.Issuer,
- ValidAudience = jwtOptions.Audience,
- IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtOptions.SecurityKey))
- };
- options.Events = new JwtBearerEvents
- {
- OnMessageReceived = context =>
+ if (context.Lease.TryGetMetadata(MetadataName.RetryAfter, out var retryAfter))
{
- var accessToken = context.Request.Query["access_token"];
- if (!string.IsNullOrEmpty(accessToken))
- {
- context.Token = accessToken;
- }
-
- return Task.CompletedTask;
+ context.HttpContext.Response.Headers.RetryAfter =
+ ((int)retryAfter.TotalSeconds).ToString(NumberFormatInfo.InvariantInfo);
}
+
+ context.HttpContext.Response.StatusCode = StatusCodes.Status429TooManyRequests;
+ context.HttpContext.Response.WriteAsync("Too many requests. Please try again later.");
+
+ return new ValueTask();
};
- })
- .AddJwtBearer(TokenTypeConst.Refresh, options =>
- {
- options.TokenValidationParameters = new TokenValidationParameters
- {
- ClockSkew = TimeSpan.Zero,
- ValidateIssuerSigningKey = true,
- ValidIssuer = refreshJwtOptions.Issuer,
- ValidAudience = refreshJwtOptions.Audience,
- IssuerSigningKey =
- new SymmetricSecurityKey(Encoding.UTF8.GetBytes(refreshJwtOptions.SecurityKey))
- };
- options.Events = new JwtBearerEvents
- {
- OnMessageReceived = context =>
+
+ //全局使用,链式表达式
+ _.GlobalLimiter = PartitionedRateLimiter.CreateChained(
+ PartitionedRateLimiter.Create(httpContext =>
{
- var refresh_token = context.Request.Headers["refresh_token"];
- if (!string.IsNullOrEmpty(refresh_token))
+ var userAgent = httpContext.Request.Headers.UserAgent.ToString();
+
+ return RateLimitPartition.GetSlidingWindowLimiter
+ (userAgent, _ =>
+ new SlidingWindowRateLimiterOptions
+ {
+ PermitLimit = 1000,
+ Window = TimeSpan.FromSeconds(60),
+ SegmentsPerWindow = 6,
+ QueueProcessingOrder = QueueProcessingOrder.OldestFirst
+ });
+ }));
+ });
+
+
+ //jwt鉴权
+ var jwtOptions = configuration.GetSection(nameof(JwtOptions)).Get();
+ var refreshJwtOptions = configuration.GetSection(nameof(RefreshJwtOptions)).Get();
+
+ context.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
+ .AddJwtBearer(options =>
+ {
+ options.TokenValidationParameters = new TokenValidationParameters
+ {
+ ClockSkew = TimeSpan.Zero,
+ ValidateIssuerSigningKey = true,
+ ValidIssuer = jwtOptions.Issuer,
+ ValidAudience = jwtOptions.Audience,
+ IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtOptions.SecurityKey))
+ };
+ options.Events = new JwtBearerEvents
+ {
+ OnMessageReceived = context =>
{
- context.Token = refresh_token;
+ var accessToken = context.Request.Query["access_token"];
+ if (!string.IsNullOrEmpty(accessToken))
+ {
+ context.Token = accessToken;
+ }
+
return Task.CompletedTask;
}
-
- var refreshToken = context.Request.Query["refresh_token"];
- if (!string.IsNullOrEmpty(refreshToken))
+ };
+ })
+ .AddJwtBearer(TokenTypeConst.Refresh, options =>
+ {
+ options.TokenValidationParameters = new TokenValidationParameters
+ {
+ ClockSkew = TimeSpan.Zero,
+ ValidateIssuerSigningKey = true,
+ ValidIssuer = refreshJwtOptions.Issuer,
+ ValidAudience = refreshJwtOptions.Audience,
+ IssuerSigningKey =
+ new SymmetricSecurityKey(Encoding.UTF8.GetBytes(refreshJwtOptions.SecurityKey))
+ };
+ options.Events = new JwtBearerEvents
+ {
+ OnMessageReceived = context =>
{
- context.Token = refreshToken;
+ var refresh_token = context.Request.Headers["refresh_token"];
+ if (!string.IsNullOrEmpty(refresh_token))
+ {
+ context.Token = refresh_token;
+ return Task.CompletedTask;
+ }
+
+ var refreshToken = context.Request.Query["refresh_token"];
+ if (!string.IsNullOrEmpty(refreshToken))
+ {
+ context.Token = refreshToken;
+ }
+
+ return Task.CompletedTask;
}
+ };
+ })
+ .AddQQ(options => { configuration.GetSection("OAuth:QQ").Bind(options); })
+ .AddGitee(options => { configuration.GetSection("OAuth:Gitee").Bind(options); });
- return Task.CompletedTask;
- }
- };
- })
- .AddQQ(options => { configuration.GetSection("OAuth:QQ").Bind(options); })
- .AddGitee(options => { configuration.GetSection("OAuth:Gitee").Bind(options); });
+ //授权
+ context.Services.AddAuthorization();
- //授权
- context.Services.AddAuthorization();
-
- return Task.CompletedTask;
- }
+
+
+ return Task.CompletedTask;
+ }
- public override Task OnApplicationInitializationAsync(ApplicationInitializationContext context)
+ public override async Task OnApplicationInitializationAsync(ApplicationInitializationContext context)
{
var service = context.ServiceProvider;
var env = context.GetEnvironment();
@@ -349,11 +382,15 @@ namespace Yi.Abp.Web
//日志记录
app.UseAbpSerilogEnrichers();
+
+ //Hangfire定时任务面板,可配置授权
+ app.UseAbpHangfireDashboard("/hangfire", options =>
+ {
+ // options.AsyncAuthorization = new[] { new AbpHangfireAuthorizationFilter() };
+ });
//终节点
app.UseConfiguredEndpoints();
-
- return Task.CompletedTask;
}
}
}
\ No newline at end of file
diff --git a/Yi.Abp.Net8/test/Yi.Framework.Rbac.Test/YiFrameworkRbacTestModule.cs b/Yi.Abp.Net8/test/Yi.Framework.Rbac.Test/YiFrameworkRbacTestModule.cs
index 956492f6..40353e03 100644
--- a/Yi.Abp.Net8/test/Yi.Framework.Rbac.Test/YiFrameworkRbacTestModule.cs
+++ b/Yi.Abp.Net8/test/Yi.Framework.Rbac.Test/YiFrameworkRbacTestModule.cs
@@ -2,8 +2,6 @@
using Volo.Abp.Auditing;
using Volo.Abp.Autofac;
using Volo.Abp.BackgroundWorkers;
-using Volo.Abp.BackgroundWorkers.Quartz;
-using Volo.Abp.Domain.Repositories;
using Yi.Framework.Rbac.Application;
using Yi.Framework.Rbac.Domain.Entities;
using Yi.Framework.Rbac.Domain.Managers;
@@ -24,10 +22,11 @@ namespace Yi.Framework.Rbac.Test
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
- Configure(options =>
- {
- options.IsAutoRegisterEnabled = false;
- });
+
+ // Configure(options =>
+ // {
+ // options.IsAutoRegisterEnabled = false;
+ // });
Configure (options =>
{
options.IsEnabled = false; //禁用作业执行
@@ -35,7 +34,6 @@ namespace Yi.Framework.Rbac.Test
Configure(options =>
{
options.Url = $"DataSource=yi-rbac-test-{DateTime.Now.ToString("yyyyMMdd_HHmmss")}.db";
-
});
}