using Autofac; using Autofac.Core; using Autofac.Extensions.DependencyInjection; using Magicodes.ExporterAndImporter.Excel.Utility.TemplateExport; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Mvc.Controllers; using Microsoft.AspNetCore.Mvc.ModelBinding.Validation; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.FileProviders; using Newtonsoft.Json; using Newtonsoft.Json.Converters; using Newtonsoft.Json.Serialization; using Serilog; using Serilog.Events; using System.IO; using System.Reflection; using System.Text; using WIDESEA_Core; using WIDESEAWCS_Core; using WIDESEAWCS_Core.Authorization; using WIDESEAWCS_Core.BaseServices; using WIDESEAWCS_Core.Core; using WIDESEAWCS_Core.Extensions; using WIDESEAWCS_Core.Filter; using WIDESEAWCS_Core.Helper; using WIDESEAWCS_Core.LogHelper; using WIDESEAWCS_Core.Middlewares; using WIDESEAWCS_QuartzJob; using WIDESEAWCS_QuartzJob.QuartzExtensions; using WIDESEAWCS_QuartzJob.Seed; using WIDESEAWCS_RedisService.Extensions; using WIDESEAWCS_Server.Filter; using WIDESEAWCS_Server.HostedService; using WIDESEAWCS_Tasks.SocketServer; using WIDESEAWCS_WCSServer.Filter; var builder = WebApplication.CreateBuilder(args); // 第1部分:主机与基础设施配置 // 使用 Serilog 作为统一日志提供程序(替换默认 Logging Providers) builder.Logging.ClearProviders(); builder.Host.UseSerilog((context, services, loggerConfiguration) => { // 配置Serilog日志记录器 loggerConfiguration .ReadFrom.Configuration(context.Configuration) // 从应用程序配置中读取Serilog相关设置(如appsettings.json) .ReadFrom.Services(services) // 从依赖注入容器中读取服务配置,允许在配置中使用已注册的服务 .Enrich.FromLogContext() // 启用日志上下文,可以在日志中包含如请求ID、用户ID等动态属性 .Enrich.WithProperty("Application", "WCS") // 设置Microsoft命名空间的日志级别为Information // 这样可以减少Microsoft框架本身的详细日志,避免过多的Debug日志 .MinimumLevel.Override("Microsoft", LogEventLevel.Information) .WriteTo.Console() // 添加控制台输出接收器,日志将显示在控制台窗口中 // 添加文件输出接收器,将日志写入文件系统 .WriteTo.File( /*Path.Combine(AppContext.BaseDirectory, "Logs", "serilog-.log"),*/ // 指定日志文件的完整路径:应用程序目录 + "Log"文件夹 + "serilog-日期.log" "logs/serilog-.log", rollingInterval: RollingInterval.Day, // 设置日志文件按天滚动,每天生成一个新的日志文件 U1od4UGVsIKZG39S5Yak retainedFileCountLimit: 30, // 最多保留最近30天的日志文件,超过30天的文件会自动删除 shared: true) // 允许多个进程同时写入同一个日志文件,适用于多实例部署场景 .WriteTo.Seq( serverUrl: "http://localhost:5341", apiKey: "U1od4UGVsIKZG39S5Yak", // 如Seq需要ApiKey则配置真实密钥 batchPostingLimit: 1000, // 批量发送数量 period: TimeSpan.FromSeconds(2) // 发送间隔 ); }); builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory()).ConfigureContainer(builder => { // 注册应用层 Autofac 模块(仓储、服务、AOP 等) builder.RegisterModule(new AutofacModuleRegister()); builder.RegisterModule(new QuartzJobAutofacModuleRegister()); builder.RegisterModule(); }).ConfigureAppConfiguration((hostingContext, config) => { // 使用统一配置入口并只保留 appsettings.json hostingContext.Configuration.ConfigureApplication(); config.Sources.Clear(); config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: false); }); builder.ConfigureApplication(); // 第2部分:服务注册 builder.Services.AddSingleton(new AppSettings(builder.Configuration)); // 注册配置访问对象 builder.Services.AddAllOptionRegister(); // 注册 Options 绑定 builder.Services.AddMemoryCacheSetup(); // 内存缓存 builder.Services.AddRedisSetup(builder.Configuration); // Redis 缓存 builder.Services.AddHostedService(); // API路由缓存预热(Redis就绪后加载) builder.Services.AddSqlsugarSetup(); // SqlSugar 数据库配置 builder.Services.AddInitializationHostServiceSetup(); // 应用初始化相关后台服务 builder.Services.AddHostedService(); // 启动时种子数据初始化 builder.Services.AddDbSetup(); // 数据库基础配置 builder.Services.AddScoped(); // Quartz 任务表创建服务 builder.Services.AddHostedService(); // Quartz 任务表初始化后台服务 builder.Services.AddWebSocketSetup(); builder.Services.AddMapsterSetup(); // Mapster 对象映射配置 builder.Services.AddCorsSetup(); builder.Services.AddMiniProfilerSetup(); builder.Services.AddSwaggerSetup(); builder.Services.AddJobSetup(); // Quartz Job 调度配置 builder.Services.AddHttpContextSetup(); builder.Services.AddHostedService(); // Quartz 启动托管服务 builder.Services.AddSingleton(); builder.Services.AddHostedService(); builder.Services.AddMvc(options => { options.Filters.Add(typeof(ApiAuthorizeFilter)); options.Filters.Add(typeof(ActionExecuteFilter)); options.Filters.Add(typeof(CustomAuthorizeFilter)); }); builder.Services.AddScoped(); builder.Services.AddAuthorizationSetup(); builder.Services.AddIpPolicyRateLimitSetup(builder.Configuration); // IP 限流配置 builder.Services.AddScoped(); builder.Services.AddSession(); builder.Services.AddHttpClient(); builder.Services.AddControllers(o => { o.Filters.Add(typeof(GlobalExceptionsFilter)); // 全局异常过滤器 }) .AddNewtonsoftJson(options => { options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Serialize; //options.SerializerSettings.ContractResolver = new DefaultContractResolver(); options.SerializerSettings.ContractResolver = new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver(); options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss"; options.SerializerSettings.NullValueHandling = NullValueHandling.Include; options.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Local; options.SerializerSettings.Converters.Add(new StringEnumConverter()); }); builder.Services.AddEndpointsApiExplorer(); // 使用 DI 激活 Controller,确保属性注入/容器行为一致 builder.Services.Replace(ServiceDescriptor.Transient()); Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); var app = builder.Build(); // 第3部分:HTTP 管道配置 app.UseMiniProfiler(); // 性能分析面板 app.ConfigureApplication(); // 应用全局初始化 app.UseApplicationSetup(); // 公共中间件初始化 app.UseAllServicesMiddle(builder.Services); app.UseSession(); app.UseSwaggerAuthorized(); app.UseSwaggerMiddle(() => Assembly.GetExecutingAssembly().GetManifestResourceStream("WIDESEAWCS_Server.index.html") ?? throw new Exception("未找到 WIDESEAWCS_Server.index.html 资源文件")); app.UseIpLimitMiddle(); app.UseApiLogMiddleware(); app.UseCors(AppSettings.Get(new string[] { "Cors", "PolicyName" })); DefaultFilesOptions defaultFilesOptions = new DefaultFilesOptions(); defaultFilesOptions.DefaultFileNames.Clear(); defaultFilesOptions.DefaultFileNames.Add("index.html"); app.UseDefaultFiles(defaultFilesOptions); app.UseMiddleware(); app.UseStaticFiles(); app.UseStaticFiles(new StaticFileOptions { FileProvider = new PhysicalFileProvider(App.WebHostEnvironment.WebRootPath) }); app.UseCookiePolicy(); app.UseStatusCodePages(); app.UseRouting(); app.UseAuthentication(); app.UseAuthorization(); app.MapControllers(); app.Run();