Files
QYZH.InteractiveMagazine/QYZH.InteractiveMagazine.WebApi/Program.cs
glz e493c85d08 refactor,feat: 批量代码重构与新增业务模块
1. 重命名枚举项与实体字段,修正类型引用
2. 新增IsNull扩展方法与多项字符串处理扩展
3. 新增大量业务DTO、服务接口与枚举定义
4. 重构RabbitMQ服务实现,替换旧版消息队列组件
5. 优化签到服务的宠物喂养事务逻辑
6. 移除冗余的项目引用与旧版消息队列代码
7. 新增Excel导出、导入模板相关工具方法
2026-06-11 17:01:24 +08:00

224 lines
7.8 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using Autofac;
using Autofac.Extensions.DependencyInjection;
using BCrypt.Net;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.ResponseCompression;
using Microsoft.OpenApi;
using Microsoft.OpenApi.Models;
using QYZH.InteractiveMagazine.Common.Extensions;
using QYZH.InteractiveMagazine.Common.Helpers;
using QYZH.InteractiveMagazine.Infrastructure.Autofacs;
using QYZH.InteractiveMagazine.Infrastructure.Context;
using QYZH.InteractiveMagazine.Infrastructure.Extensions;
using QYZH.InteractiveMagazine.Infrastructure.Middleware;
using QYZH.InteractiveMagazine.Infrastructure.Redis;
using QYZH.InteractiveMagazine.Infrastructure.SDK;
using QYZH.InteractiveMagazine.Models.Entity;
using QYZH.InteractiveMagazine.Models.Enum;
using QYZH.InteractiveMagazine.Models.Settings;
using QYZH.InteractiveMagazine.Repository;
using QYZH.InteractiveMagazine.Repository.Core;
using Serilog;
using SqlSugar.IOC;
using Swashbuckle.AspNetCore.SwaggerGen;
using Swashbuckle.AspNetCore.SwaggerUI;
using System.Text.Json.Serialization;
using Yitter.IdGenerator;
using QYZH.InteractiveMagazine.Infrastructure.RabbitMQ;
var builder = WebApplication.CreateBuilder(args);
// 加载勋章规则独立配置文件
builder.Configuration.AddJsonFile("medal-rule-config.json", optional: false, reloadOnChange: true);
// 初始化雪花ID生成器
YitIdHelper.SetIdGenerator(new IdGeneratorOptions() { WorkerId = 1 });
// autofac注入 允许使用autofac作为DI容器
builder.UseAutofac();
builder.InitSqlSugarDb(new IocConfig()
{
ConfigId = 0,
DbType = IocDbType.MySql,
ConnectionString = builder.Configuration.GetConnectionString("DefaultConnection"),
IsAutoCloseConnection = true,
});
// 消除Error unprotecting the session cookie警告
builder.Services.AddDataProtection()
.PersistKeysToFileSystem(new DirectoryInfo(Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar + "DataProtection"));
//redis
builder.Services.AddCSRedisCacheExtension(builder.Configuration.GetSection("RedisSettings"));
//MQ
builder.Services.AddRabbitMQ(builder.Configuration);
// 配置Serilog
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(builder.Configuration)
.Enrich.FromLogContext()
.CreateLogger();
builder.Host.UseSerilog();
builder.Services.AddControllers(options =>
{
options.SuppressImplicitRequiredAttributeForNonNullableReferenceTypes = true;//Required 不作为必填
options.Filters.Add<ModelValidActionFilterAttribute>();//添加自定义模型验证
})
.AddJsonOptions(options =>
{
// 配置 JSON 不区分大小写(支持 camelCase 和 PascalCase
options.JsonSerializerOptions.PropertyNameCaseInsensitive = true;
// 配置返回时间格式转换
options.JsonSerializerOptions.Converters.Add(new JsonConverterUtil.DateTimeConverter());
options.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles;
}).ConfigureApiBehaviorOptions(opt => opt.SuppressModelStateInvalidFilter = true);//关闭默认模型验证
builder.Services.AddEndpointsApiExplorer();
// 跨域配置
builder.Services.AddDataProtection().UseEphemeralDataProtectionProvider();
builder.AddCorsRegister();
//builder.Services.AddSession();
builder.Services.AddHttpClient();
// 注册 Swagger 文档
builder.Services.AddSwaggerGen(option =>
{
var xmlFile = $"{AppDomain.CurrentDomain.FriendlyName}.xml";
var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
var modelXml = Path.Combine(AppContext.BaseDirectory, $"QYZH.InteractiveMagazine.Models.xml");
Enum.GetValues<ApiVersionEnum>().ToList().ForEach(version =>
{
// 配置文档信息
option.SwaggerDoc(version.ToString(), new OpenApiInfo
{
Title = AppDomain.CurrentDomain.FriendlyName,
Version = "互动期刊接口文档",
Description = $"{version.GetDescription()}接口Last Modify Time{new FileInfo(xmlPath).LastWriteTime.ToString("yyyy-MM-dd HH:mm:ss")}"
});
});
// 配置接口路径排序
option.OrderActionsBy(o => o.RelativePath);
if (File.Exists(xmlPath))
option.IncludeXmlComments(xmlPath, true);
if (File.Exists(modelXml))
option.IncludeXmlComments(modelXml, true);
option.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme()
{
Description = "请输入 Token格式为 Bearer Token",
Name = "Authorization",
In = ParameterLocation.Header,
Type = SecuritySchemeType.ApiKey,
BearerFormat = "JWT",
Scheme = "Bearer"
});
option.AddSecurityRequirement(new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "Bearer"
}
},
new string[] { }
}
});
// 过滤文档/路径/方法筛选接口的响应结果
option.DocInclusionPredicate((docName, apiDesc) =>
{
// 方式 1将接口的 [ApiExplorerSettings(GroupName = "xxx")] 特性匹配
if (!apiDesc.TryGetMethodInfo(out var methodInfo)) return false;
var groupName = methodInfo.DeclaringType?
.GetCustomAttributes(true)
.OfType<ApiExplorerSettingsAttribute>()
.FirstOrDefault()?
.GroupName;
// 匹配当前文档(分组)则显示
return groupName == docName;
});
});
builder.Services.AddInfrastructureServices(builder.Configuration, builder.Environment);
//注册 HttpContextAccessor
builder.Services.AddHttpContextAccessor();
builder.Services.AddScoped(typeof(BaseRepository<>));
// 注册勋章规则配置
builder.Services.Configure<MedalRuleConfigSettings>(builder.Configuration.GetSection("MedalRuleConfig"));
// 添加CORS
builder.Services.AddCors(options =>
{
options.AddPolicy("AllowAll", policy =>
{
policy.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader();
});
});
builder.Services.AddSDKService(builder.Configuration);
#region
// 1.首先配置压缩选项的Options>
builder.Services.Configure<BrotliCompressionProviderOptions>(options =>
{
options.Level = System.IO.Compression.CompressionLevel.Optimal;
});
builder.Services.Configure<GzipCompressionProviderOptions>(options =>
{
options.Level = System.IO.Compression.CompressionLevel.Fastest;
});
// 2.在服务容器中注册响应压缩服务
builder.Services.AddResponseCompression(options =>
{
// 可以在这里进行详细配置
options.EnableForHttps = true; // 启用对HTTPS响应的压缩请注意安全风险
options.Providers.Add<BrotliCompressionProvider>();
options.Providers.Add<GzipCompressionProvider>();
//指定哪些类型的响应应该被压缩。默认列表包含常见的文本类类型,如 text/html, text/css, application/javascript, application/json, text/plain等
options.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(["image/svg+xml", "application/json", "text/plain"]);
});
#endregion
var app = builder.Build();
{
app.UseSwagger();
app.UseSwaggerUI(c =>
{
// 根据版本名称倒序 遍历展示
Enum.GetValues<ApiVersionEnum>().OrderBy(e => e).ToList().ForEach(version =>
{
c.SwaggerEndpoint($"/swagger/{version}/swagger.json", $"{version.GetDescription()}接口");
});
c.DocExpansion(DocExpansion.None); // ->修改界面打开时自动折叠
});
}
app.UseServiceContext();
app.UseHttpsRedirection();
app.UseCors("AllowAll");
app.UseMiddleware<GlobalExceptionMiddleware>();
app.UseMiddleware<OperationLogMiddleware>();
app.UseMiddleware<JwtAutoRefreshMiddleware>();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();