feat(新增): 添加Quartz简单案例

This commit is contained in:
Bunny 2024-08-14 23:57:43 +08:00
parent e48c71c1e1
commit aad873a49a
16 changed files with 350 additions and 24 deletions

View File

@ -2,19 +2,7 @@
<project version="4">
<component name="GitCommitMessageStorage">
<option name="messageStorage">
<MessageStorage>
<option name="commitTemplate">
<CommitTemplate>
<option name="body" value="" />
<option name="changes" value="" />
<option name="closes" value="" />
<option name="scope" value="" />
<option name="skipCi" value="" />
<option name="subject" value="" />
<option name="type" value="feat" />
</CommitTemplate>
</option>
</MessageStorage>
<MessageStorage />
</option>
</component>
</project>

View File

@ -19,6 +19,7 @@
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Minio" Version="6.0.3"/>
<PackageReference Include="Newtonsoft.Json" Version="13.0.3"/>
<PackageReference Include="StackExchange.Redis" Version="2.8.0"/>
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="7.6.0"/>

View File

@ -0,0 +1,31 @@
using Bunny.Common.Utils;
using Microsoft.AspNetCore.Builder;
using Minio;
namespace Bunny.Common.Connect;
public static class MinioContext
{
public static IMinioClient? MinioClient;
public static readonly string BucketName = AppSettings.GetConfig("Minio:BucketName");
public static void AddMinioContext(this WebApplicationBuilder builder)
{
var endpoint = AppSettings.GetConfig("Minio:Url");
var accessKey = AppSettings.GetConfig("Minio:AccessKey");
var secretKey = AppSettings.GetConfig("Minio:SecretKey");
MinioClient = new MinioClient().WithEndpoint(endpoint).WithCredentials(accessKey, secretKey)
// .WithSSL() // 使用HTTPS
.Build();
Task.Run(ShowAllBucket);
}
private static async Task ShowAllBucket()
{
var listBucketsAsync = await MinioUtil.ListBucketsAsync();
foreach (var bucket in listBucketsAsync.Buckets) Console.WriteLine($"Minio存在的桶{bucket.Name}");
Console.WriteLine("Minio 连接成功...");
}
}

View File

@ -1,13 +1,14 @@
using StackExchange.Redis;
using Microsoft.AspNetCore.Builder;
using StackExchange.Redis;
namespace Bunny.Common.Connect;
public class RedisContext
public static class RedisContext
{
public static IDatabase RedisDatabase;
private static readonly EndPointCollection EndPointCollection = new();
public static void Initial()
public static void AddRedisContext(this WebApplicationBuilder builder)
{
// 获取端口等配置信息
var host = AppSettings.GetConfig("Redis:Host");

View File

@ -0,0 +1,205 @@
using Bunny.Common.Connect;
using Bunny.Common.Exception;
using Bunny.Dao.Entity.Constant;
using Microsoft.AspNetCore.Http;
using Microsoft.IdentityModel.Tokens;
using Minio.DataModel;
using Minio.DataModel.Args;
using Minio.DataModel.Result;
using Minio.Exceptions;
namespace Bunny.Common.Utils;
public static class MinioUtil
{
/// <summary>
/// 创建新的桶,如果不存在则创建
/// </summary>
/// <param name="bucketName">桶名称</param>
public static async Task MakeBucketAsync(string bucketName)
{
// 判断桶名称是否初始化
bucketName = bucketName.IsNullOrEmpty() ? MinioContext.BucketName : bucketName;
// minio客户端
var minioClient = MinioContext.MinioClient;
try
{
var found = await BucketExistsAsync(bucketName);
if (!found) await minioClient!.MakeBucketAsync(new MakeBucketArgs().WithBucket(bucketName));
}
catch (MinioException e)
{
Console.WriteLine(e);
throw new BunnyException(ExceptionConstant.FileSystemException);
}
}
/// <summary>
/// 列出所有的桶
/// </summary>
public static async Task<ListAllMyBucketsResult> ListBucketsAsync()
{
var minioClient = MinioContext.MinioClient;
try
{
var listAllMyBucketsResult = await minioClient!.ListBucketsAsync();
return listAllMyBucketsResult;
}
catch (MinioException e)
{
Console.WriteLine(e);
throw new BunnyException(ExceptionConstant.FileSystemException);
}
}
/// <summary>
/// 判断桶是否存在
/// </summary>
/// <param name="bucketName"></param>
/// <returns></returns>
public static async Task<bool> BucketExistsAsync(string bucketName)
{
// 判断桶名称是否初始化
bucketName = bucketName.IsNullOrEmpty() ? MinioContext.BucketName : bucketName;
// minio客户端
var minioClient = MinioContext.MinioClient;
return await minioClient!.BucketExistsAsync(new BucketExistsArgs().WithBucket(bucketName));
}
/// <summary>
/// 移出桶
/// </summary>
/// <param name="bucketName">桶名称</param>
public static async Task RemoveBucketAsync(string bucketName)
{
// 判断桶名称是否初始化
bucketName = bucketName.IsNullOrEmpty() ? MinioContext.BucketName : bucketName;
// minio客户端
var minioClient = MinioContext.MinioClient!;
try
{
// 如果存在则移除
var found = await BucketExistsAsync(bucketName);
if (found) await minioClient.RemoveBucketAsync(new RemoveBucketArgs().WithBucket(bucketName));
else Console.WriteLine("桶不存在");
}
catch (MinioException e)
{
Console.WriteLine(e);
throw new BunnyException(ExceptionConstant.FileSystemException);
}
}
/// <summary>
/// 查看桶的版本信息
/// </summary>
/// <param name="bucketName">桶名称</param>
public static async Task<VersioningConfiguration> GetVersioningInfoAsync(string bucketName)
{
// 判断桶名称是否初始化
bucketName = bucketName.IsNullOrEmpty() ? MinioContext.BucketName : bucketName;
// minio客户端
var minioClient = MinioContext.MinioClient!;
try
{
var found = await BucketExistsAsync(bucketName);
if (!found) Console.WriteLine("桶不存在");
return await minioClient.GetVersioningAsync(new GetVersioningArgs().WithBucket(bucketName));
}
catch (MinioException e)
{
Console.WriteLine(e);
throw new BunnyException(ExceptionConstant.FileSystemException);
}
}
/// <summary>
/// 上传文件
/// </summary>
/// <param name="bucketName">桶名称</param>
/// <param name="file">文件</param>
public static async Task PutObjectAsync(IFormFile file, string? bucketName = default)
{
// 判断桶名称是否初始化
bucketName = bucketName.IsNullOrEmpty() ? MinioContext.BucketName : bucketName;
// minio客户端
var minioClient = MinioContext.MinioClient!;
var guid = Guid.NewGuid().ToString();
var fileName = guid + file.FileName;
try
{
var found = await BucketExistsAsync(bucketName!);
if (!found) await MakeBucketAsync(bucketName!);
await minioClient.PutObjectAsync(new PutObjectArgs().WithBucket(bucketName).WithObject(fileName)
.WithStreamData(file.OpenReadStream()).WithObjectSize(file.Length));
}
catch (MinioException e)
{
Console.WriteLine(e);
throw new BunnyException(ExceptionConstant.FileSystemException);
}
}
/// <summary>
/// 获取文件对象信息
/// </summary>
/// <param name="bucketName">桶名称</param>
/// <param name="filename">文件名</param>
public static async Task<ObjectStat> GetObjectAsync(string filename, string? bucketName = default)
{
// 判断桶名称是否初始化
bucketName = bucketName.IsNullOrEmpty() ? MinioContext.BucketName : bucketName;
// minio客户端
var minioClient = MinioContext.MinioClient!;
try
{
var statObjectArgs = new StatObjectArgs().WithBucket(bucketName).WithObject(filename);
await minioClient.StatObjectAsync(statObjectArgs);
var getObjectArgs = new GetObjectArgs().WithBucket(bucketName).WithObject(filename).WithFile(filename);
return await minioClient.GetObjectAsync(getObjectArgs);
}
catch (MinioException e)
{
Console.WriteLine(e);
throw new BunnyException(ExceptionConstant.FileSystemException);
}
}
/// <summary>
/// 桶中内容状态
/// </summary>
/// <param name="bucketName">桶名称</param>
/// <param name="filename">文件名</param>
public static async Task<ObjectStat> StatObject(string filename, string? bucketName = default)
{
// 判断桶名称是否初始化
bucketName = bucketName.IsNullOrEmpty() ? MinioContext.BucketName : bucketName;
// minio客户端
var minioClient = MinioContext.MinioClient!;
try
{
// Get the metadata of the object.
var statObjectArgs = new StatObjectArgs()
.WithBucket(bucketName)
.WithObject(filename);
var objectStat = await minioClient.StatObjectAsync(statObjectArgs);
return objectStat;
}
catch (MinioException e)
{
Console.WriteLine(e);
throw new BunnyException(ExceptionConstant.FileSystemException);
}
}
}

View File

@ -9,6 +9,7 @@
<ItemGroup>
<PackageReference Include="Fleck" Version="1.2.0"/>
<PackageReference Include="Lazy.Captcha.Core" Version="2.0.8"/>
<PackageReference Include="Quartz" Version="3.13.0"/>
<PackageReference Include="Quartz.Extensions.Hosting" Version="3.13.0"/>
</ItemGroup>

View File

@ -0,0 +1,9 @@
namespace Bunny.Service.IService;
public interface IJobService
{
/// <summary>
/// 开启一个简单的工作
/// </summary>
void StartSimpleJob();
}

View File

@ -0,0 +1,40 @@
using Bunny.Service.Job;
using Quartz;
using Quartz.Impl;
namespace Bunny.Service.IService.Service;
public class JobService : IJobService
{
/// <summary>
/// 开启一个简单的工作
/// https://www.youtube.com/watch?v=CuHIScZKup8&list=PLSi1BNmQ61ZohCcl43UdAksg7X3_TSmly&index=6
/// </summary>
public void StartSimpleJob()
{
var schedulerFactory = new StdSchedulerFactory();
// TODO 如果使用异步必须使用await 和 async
// var scheduler = schedulerFactory.GetScheduler();
var scheduler = schedulerFactory.GetScheduler().GetAwaiter().GetResult();
var jobDetail = JobBuilder.Create<SimJob>()
.UsingJobData("username", "用户名")
.UsingJobData("password", "密码")
.WithIdentity("simpleJob", "简单的JOB")
.Build();
var trigger = TriggerBuilder.Create()
.WithIdentity("testTrigger", "测试发出器")
.StartNow()
// 每隔5秒执行一次一共重复10次
.WithSimpleSchedule(x => x.WithIntervalInSeconds(5).WithRepeatCount(10))
.Build();
// 使用同步方法
scheduler.ScheduleJob(jobDetail, trigger).GetAwaiter().GetResult();
scheduler.Start().GetAwaiter().GetResult();
// TODO 使用异步
// await _scheduler.ScheduleJob(jobDetail, trigger);
// await _scheduler.Start();
}
}

View File

@ -0,0 +1,16 @@
using Quartz;
namespace Bunny.Service.Job;
public class SimJob : IJob
{
public Task Execute(IJobExecutionContext context)
{
Console.WriteLine("执行一个简单的任务");
var dataMap = context.JobDetail.JobDataMap;
var username = dataMap.GetString("username");
var password = dataMap.GetString("password");
Console.WriteLine($"用户名:{username},密码: {password}");
return Task.CompletedTask;
}
}

View File

@ -1,8 +1,10 @@
namespace Bunny.Service.WebSocket;
using Microsoft.AspNetCore.Builder;
namespace Bunny.Service.WebSocket;
public static class WebSocketInitial
{
public static void Start()
public static void AddWebSocketInitial(this WebApplicationBuilder builder)
{
WebSocketTest.Start();
}

View File

@ -44,13 +44,15 @@ public class BaseConfig(WebApplicationBuilder builder)
private void UseExtend()
{
// 设置过滤器
FilterConfig.Initialize(builder);
builder.FilterConfigInitialize();
// 初始化Redis
RedisContext.Initial();
builder.AddRedisContext();
// 初始化Minio
builder.AddMinioContext();
// 初始化 Knife4Net 文档
Knife4Net.Initialize(builder);
builder.AddKnife4Net();
// 启动 webSocket
WebSocketInitial.Start();
builder.AddWebSocketInitial();
}
/// <summary>

View File

@ -9,7 +9,7 @@ public static class FilterConfig
/// 配置过滤器
/// </summary>
/// <param name="builder"></param>
public static void Initialize(WebApplicationBuilder builder)
public static void FilterConfigInitialize(this WebApplicationBuilder builder)
{
// 添加自定义过滤器---全局异常捕获
builder.Services.AddControllers(option =>

View File

@ -8,7 +8,7 @@ public static class Knife4Net
/// <summary>
/// 配置 Knife4j 文档
/// </summary>
public static void Initialize(WebApplicationBuilder builder)
public static void AddKnife4Net(this WebApplicationBuilder builder)
{
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(options =>

View File

@ -15,6 +15,7 @@ public static class ServiceRegistration
builder.Services.AddScoped<IBaseService, BaseService>();
builder.Services.AddScoped<IBlogService, BlogService>();
builder.Services.AddScoped<IRedisOptionService, RedisOptionService>();
builder.Services.AddScoped<IJobService, JobService>();
}
/// <summary>

View File

@ -0,0 +1,23 @@
using Bunny.Dao.Result;
using Bunny.Service.IService;
using Microsoft.AspNetCore.Mvc;
namespace Bunny.WebApi.Controllers;
/// <summary>
/// Quartz 示例相关
/// </summary>
[Route("/api/[controller]/[action]")]
public class JobInitController(IJobService jobService) : ControllerBase
{
/// <summary>
/// 开启一个简单的工作
/// </summary>
/// <returns></returns>
[HttpPost]
public Result<string> StartSimpleJob()
{
jobService.StartSimpleJob();
return Result<string>.Success();
}
}

View File

@ -21,5 +21,11 @@
"Password": "02120212",
"DefaultDB": 6,
"AsyncTimeout": 300
},
"Minio": {
"Url": "192.168.3.98:9000",
"AccessKey": "bunny",
"SecretKey": "02120212",
"BucketName": "test"
}
}