liaoxujun@qq.com
2024-02-28 9f8e542b9b74fe18a6a4e0a00fef4b50e3e62581
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
using Autofac;
using Autofac.Extensions.DependencyInjection;
using CoreCms.Net.Configuration;
using CoreCms.Net.Loging;
using Essensoft.Paylink.Alipay;
using Essensoft.Paylink.WeChatPay;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.HttpOverrides;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using NLog.Web;
using System;
using System.Linq;
using System.Threading.RateLimiting;
using CoreCms.Net.Auth;
using CoreCms.Net.Core.AutoFac;
using CoreCms.Net.Core.Config;
using CoreCms.Net.Filter;
using CoreCms.Net.Mapping;
using CoreCms.Net.Middlewares;
using CoreCms.Net.Model.ViewModels.Options;
using CoreCms.Net.Swagger;
using CoreCms.Net.Utility;
using CoreCms.Net.Web.Admin.Infrastructure;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using Yitter.IdGenerator;
using LogLevel = NLog.LogLevel;
using Microsoft.AspNetCore.RateLimiting;
using Microsoft.Extensions.Configuration;
 
 
var builder = WebApplication.CreateBuilder(args);
 
//添加本地路径获取支持
builder.Services.AddSingleton(new AppSettingsHelper(builder.Environment.ContentRootPath));
builder.Services.AddSingleton(new LogLockHelper(builder.Environment.ContentRootPath));
 
//Memory缓存
builder.Services.AddMemoryCacheSetup();
//Redis缓存
builder.Services.AddRedisCacheSetup();
 
//添加数据库连接SqlSugar注入支持
builder.Services.AddSqlSugarSetup();
//配置跨域(CORS)
builder.Services.AddCorsSetup();
 
//添加session支持(session依赖于cache进行存储)
builder.Services.AddSession();
// AutoMapper支持
builder.Services.AddAutoMapper(typeof(AutoMapperConfiguration));
 
// 引入Payment 依赖注入(支付宝支付/微信支付)
builder.Services.AddAlipay();
builder.Services.AddWeChatPay();
 
//注册自定义微信接口配置文件
builder.Services.Configure<CoreCms.Net.WeChat.Service.Options.WeChatOptions>(builder.Configuration.GetSection(nameof(CoreCms.Net.WeChat.Service.Options.WeChatOptions)));
 
// 注入工厂 HTTP 客户端
builder.Services.AddHttpClient();
builder.Services.AddSingleton<CoreCms.Net.WeChat.Service.HttpClients.IWeChatApiHttpClientFactory, CoreCms.Net.WeChat.Service.HttpClients.WeChatApiHttpClientFactory>();
 
//Swagger接口文档注入
builder.Services.AddAdminSwaggerSetup();
 
//jwt授权支持注入
builder.Services.AddAuthorizationSetupForAdmin();
 
//上下文注入
builder.Services.AddHttpContextSetup();
 
//服务配置中加入AutoFac控制器替换规则。
builder.Services.Replace(ServiceDescriptor.Transient<IControllerActivator, ServiceBasedControllerActivator>());
 
//注册mvc,注册razor引擎视图
builder.Services.AddMvc(options =>
    {
        //实体验证
        options.Filters.Add<RequiredErrorForAdmin>();
        //异常处理
        options.Filters.Add<GlobalExceptionsFilterForAdmin>();
        //Swagger剔除不需要加入api展示的列表
        options.Conventions.Add(new ApiExplorerIgnores());
 
        options.EnableEndpointRouting = false;
    })
    .AddNewtonsoftJson(p =>
    {
        //数据格式首字母小写 不使用驼峰
        p.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
        //不使用驼峰样式的key
        //p.SerializerSettings.ContractResolver = new DefaultContractResolver();
        //忽略循环引用
        p.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
        //设置时间格式
        p.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss";
    });
 
 
//调用 AddRateLimiter 来将速率限制服务添加到服务集合
builder.Services.Configure<MyRateLimitOptions>(builder.Configuration.GetSection(MyRateLimitOptions.MyRateLimit));
 
var myOptions = new MyRateLimitOptions();
builder.Configuration.GetSection(MyRateLimitOptions.MyRateLimit).Bind(myOptions);
var fixedPolicy = "fixed";
 
builder.Services.AddRateLimiter(_ => _
    .AddFixedWindowLimiter(policyName: fixedPolicy, options =>
    {
        options.PermitLimit = myOptions.PermitLimit;
        //options.Window = TimeSpan.FromSeconds(myOptions.Window); //不走窗口限制了。直接走请求数限制。
        options.QueueProcessingOrder = QueueProcessingOrder.OldestFirst;
        options.QueueLimit = myOptions.QueueLimit;
    }));
 
 
// 雪花漂移算法
// 创建 IdGeneratorOptions 对象,请在构造函数中输入 WorkerId:
var options = new IdGeneratorOptions(1);
// WorkerIdBitLength 默认值6,支持的 WorkerId 最大值为2^6-1,若 WorkerId 超过64,可设置更大的 WorkerIdBitLength
// options.WorkerIdBitLength = 10; 
// ...... 其它参数设置参考 IdGeneratorOptions 定义,一般来说,只要再设置 WorkerIdBitLength (决定 WorkerId 的最大值)。
 
// 保存参数(必须的操作,否则以上设置都不能生效):
YitIdHelper.SetIdGenerator(options);
 
// 初始化以后,即可在任何需要生成ID的地方,调用以下方法:
//var newId = YitIdHelper.NextId();
 
#region AutoFac注册============================================================================
 
builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory());
builder.Host.ConfigureContainer<ContainerBuilder>(containerBuilder =>
{
    containerBuilder.RegisterModule(new AutofacModuleRegister());
 
    //获取所有控制器类型并使用属性注入
    var controllerBaseType = typeof(ControllerBase);
    containerBuilder.RegisterAssemblyTypes(typeof(Program).Assembly)
        .Where(t => controllerBaseType.IsAssignableFrom(t) && t != controllerBaseType)
        .PropertiesAutowired();
});
 
#endregion
 
#region Nlog注册============================================================================
// NLog: Setup NLog for Dependency injection
builder.Logging.ClearProviders();//移除已经注册的其他日志处理程序
builder.Logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace); //设置最小的日志级别
builder.Host.UseNLog();
#endregion
 
 
var app = builder.Build();
 
 
 
#region 解决Ubuntu Nginx 代理不能获取IP问题===================================================================
app.UseForwardedHeaders(new ForwardedHeadersOptions
{
    ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
});
#endregion
 
#region 中间件注册===================================================================
// 获取用户访问真实ip
app.RealIpMiddleware();
// 启用速率限制中间件
app.UseRateLimiter();
// 记录请求与返回数据 (注意开启权限,不然本地无法写入)
app.UseRequestResponseLog();
// 用户访问记录(必须放到外层,不然如果遇到异常,会报错,因为不能返回流)(注意开启权限,不然本地无法写入)
app.UseRecordAccessLogsMildd(GlobalEnumVars.CoreShopSystemCategory.Admin.ToString());
// 记录ip请求 (注意开启权限,不然本地无法写入)
app.UseIpLogMildd();
 
#endregion
 
app.UseSwagger().UseSwaggerUI(c =>
{
    //根据版本名称倒序 遍历展示
    typeof(CustomApiVersion.ApiVersions).GetEnumNames().OrderByDescending(e => e).ToList().ForEach(
        version =>
        {
            c.SwaggerEndpoint($"/swagger/{version}/swagger.json", $"Doc {version}");
        });
    c.RoutePrefix = "doc";
});
 
 
//使用 Session
app.UseSession();
 
if (app.Environment.IsDevelopment())
{
    // 在开发环境中,使用异常页面,这样可以暴露错误堆栈信息,所以不要放在生产环境。
    app.UseDeveloperExceptionPage();
}
else
{
    app.UseExceptionHandler("/Home/Error");
    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
    app.UseHsts();
}
 
// CORS跨域
app.UseCors(AppSettingsConstVars.CorsPolicyName);
// 跳转https
//app.UseHttpsRedirection();
 
// 使用cookie
app.UseCookiePolicy();
// 返回错误码
app.UseStatusCodePages();
// Routing
app.UseRouting();
// 先开启认证
app.UseAuthentication();
// 然后是授权中间件
app.UseAuthorization();
 
app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");
 
 
//设置默认起始页(如default.html)
//此处的路径是相对于wwwroot文件夹的相对路径
var defaultFilesOptions = new DefaultFilesOptions();
defaultFilesOptions.DefaultFileNames.Clear();
defaultFilesOptions.DefaultFileNames.Add("index.html");
app.UseDefaultFiles(defaultFilesOptions);
// 使用静态文件
app.UseStaticFiles();
 
try
{
    //确保NLog.config中连接字符串与appsettings.json中同步
    NLogUtil.EnsureNlogConfig("NLog.config");
    //其他项目启动时需要做的事情
    NLogUtil.WriteAll(LogLevel.Trace, LogType.ApiRequest, "后端启动", "后端启动成功");
 
    app.Run();
}
catch (Exception ex)
{
    //使用Nlog写到本地日志文件(万一数据库没创建/连接成功)
    NLogUtil.WriteFileLog(LogLevel.Error, LogType.ApiRequest, "后端启动", "初始化数据异常", ex);
    throw;
}