forked from anjoy8/Blog.Core
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathStartup.cs
More file actions
269 lines (223 loc) · 10.9 KB
/
Startup.cs
File metadata and controls
269 lines (223 loc) · 10.9 KB
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
257
258
259
260
261
262
263
264
265
266
267
268
269
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using Autofac;
using Autofac.Extras.DynamicProxy;
using Blog.Core.AOP;
using Blog.Core.Common;
using Blog.Core.Common.LogHelper;
using Blog.Core.Extensions;
using Blog.Core.Filter;
using Blog.Core.Hubs;
using Blog.Core.IServices;
using Blog.Core.Middlewares;
using Blog.Core.Model;
using log4net;
using log4net.Repository;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using static Blog.Core.SwaggerHelper.CustomApiVersion;
namespace Blog.Core
{
public class Startup
{
/// <summary>
/// log4net 仓储库
/// </summary>
public static ILoggerRepository Repository { get; set; }
private static readonly ILog log =
LogManager.GetLogger(typeof(GlobalExceptionsFilter));
public Startup(IConfiguration configuration, IWebHostEnvironment env)
{
Configuration = configuration;
Env = env;
}
public IConfiguration Configuration { get; }
public IWebHostEnvironment Env { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
// 以下code可能与文章中不一样,对代码做了封装,具体查看右侧 Extensions 文件夹.
services.AddSingleton<IRedisCacheManager, RedisCacheManager>();
services.AddSingleton(new Appsettings(Env.ContentRootPath));
services.AddSingleton(new LogLock(Env.ContentRootPath));
services.AddMemoryCacheSetup();
services.AddSqlsugarSetup();
services.AddDbSetup();
services.AddAutoMapperSetup();
services.AddCorsSetup();
services.AddMiniProfilerSetup();
services.AddSwaggerSetup();
services.AddJobSetup();
services.AddHttpContextSetup();
services.AddAuthorizationSetup();
services.AddSignalR().AddNewtonsoftJsonProtocol();
services.AddScoped<UseServiceDIAttribute>();
services.AddControllers(o =>
{
// 全局异常过滤
o.Filters.Add(typeof(GlobalExceptionsFilter));
// 全局路由权限公约
//o.Conventions.Insert(0, new GlobalRouteAuthorizeConvention());
// 全局路由前缀,统一修改路由
o.Conventions.Insert(0, new GlobalRoutePrefixFilter(new RouteAttribute(RoutePrefix.Name)));
})
//全局配置Json序列化处理
.AddNewtonsoftJson(options =>
{
//忽略循环引用
options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
//不使用驼峰样式的key
options.SerializerSettings.ContractResolver = new DefaultContractResolver();
//设置时间格式
//options.SerializerSettings.DateFormatString = "yyyy-MM-dd";
});
}
// 注意在CreateDefaultBuilder中,添加Autofac服务工厂
public void ConfigureContainer(ContainerBuilder builder)
{
var basePath = AppContext.BaseDirectory;
//builder.RegisterType<AdvertisementServices>().As<IAdvertisementServices>();
#region 带有接口层的服务注入
var servicesDllFile = Path.Combine(basePath, "Blog.Core.Services.dll");
var repositoryDllFile = Path.Combine(basePath, "Blog.Core.Repository.dll");
if (!(File.Exists(servicesDllFile) && File.Exists(repositoryDllFile)))
{
throw new Exception("Repository.dll和service.dll 丢失,因为项目解耦了,所以需要先F6编译,再F5运行,请检查 bin 文件夹,并拷贝。");
}
// AOP 开关,如果想要打开指定的功能,只需要在 appsettigns.json 对应对应 true 就行。
var cacheType = new List<Type>();
if (Appsettings.app(new string[] { "AppSettings", "RedisCachingAOP", "Enabled" }).ObjToBool())
{
builder.RegisterType<BlogRedisCacheAOP>();
cacheType.Add(typeof(BlogRedisCacheAOP));
}
if (Appsettings.app(new string[] { "AppSettings", "MemoryCachingAOP", "Enabled" }).ObjToBool())
{
builder.RegisterType<BlogCacheAOP>();
cacheType.Add(typeof(BlogCacheAOP));
}
if (Appsettings.app(new string[] { "AppSettings", "TranAOP", "Enabled" }).ObjToBool())
{
builder.RegisterType<BlogTranAOP>();
cacheType.Add(typeof(BlogTranAOP));
}
if (Appsettings.app(new string[] { "AppSettings", "LogAOP", "Enabled" }).ObjToBool())
{
builder.RegisterType<BlogLogAOP>();
cacheType.Add(typeof(BlogLogAOP));
}
// 获取 Service.dll 程序集服务,并注册
var assemblysServices = Assembly.LoadFrom(servicesDllFile);
builder.RegisterAssemblyTypes(assemblysServices)
.AsImplementedInterfaces()
.InstancePerDependency()
.EnableInterfaceInterceptors()//引用Autofac.Extras.DynamicProxy;
.InterceptedBy(cacheType.ToArray());//允许将拦截器服务的列表分配给注册。
// 获取 Repository.dll 程序集服务,并注册
var assemblysRepository = Assembly.LoadFrom(repositoryDllFile);
builder.RegisterAssemblyTypes(assemblysRepository)
.AsImplementedInterfaces()
.InstancePerDependency();
#endregion
#region 没有接口层的服务层注入
//因为没有接口层,所以不能实现解耦,只能用 Load 方法。
//注意如果使用没有接口的服务,并想对其使用 AOP 拦截,就必须设置为虚方法
//var assemblysServicesNoInterfaces = Assembly.Load("Blog.Core.Services");
//builder.RegisterAssemblyTypes(assemblysServicesNoInterfaces);
#endregion
#region 没有接口的单独类 class 注入
//只能注入该类中的虚方法,且必须是public
builder.RegisterAssemblyTypes(Assembly.GetAssembly(typeof(Love)))
.EnableClassInterceptors()
.InterceptedBy(cacheType.ToArray());
#endregion
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IBlogArticleServices _blogArticleServices, ILoggerFactory loggerFactory)
{
// 记录所有的访问记录
loggerFactory.AddLog4Net();
// 记录请求与返回数据
app.UseReuestResponseLog();
// signalr
app.UseSignalRSendMildd();
// 记录ip请求
app.UseIPLogMildd();
#region Environment
if (env.IsDevelopment())
{
// 在开发环境中,使用异常页面,这样可以暴露错误堆栈信息,所以不要放在生产环境。
app.UseDeveloperExceptionPage();
//app.Use(async (context, next) =>
//{
// //这里会多次调用,这里测试一下就行,不要打开注释
// //var blogs =await _blogArticleServices.GetBlogs();
// var processName = System.Diagnostics.Process.GetCurrentProcess().ProcessName;
// Console.WriteLine(processName);
// await next();
//});
}
else
{
app.UseExceptionHandler("/Error");
// 在非开发环境中,使用HTTP严格安全传输(or HSTS) 对于保护web安全是非常重要的。
// 强制实施 HTTPS 在 ASP.NET Core,配合 app.UseHttpsRedirection
//app.UseHsts();
}
#endregion
#region Swagger
app.UseSwagger();
app.UseSwaggerUI(c =>
{
//根据版本名称倒序 遍历展示
var ApiName = Appsettings.app(new string[] { "Startup", "ApiName" });
typeof(ApiVersions).GetEnumNames().OrderByDescending(e => e).ToList().ForEach(version =>
{
c.SwaggerEndpoint($"/swagger/{version}/swagger.json", $"{ApiName} {version}");
});
// 将swagger首页,设置成我们自定义的页面,记得这个字符串的写法:解决方案名.index.html,并且是右键属性,嵌入的资源
c.IndexStream = () => GetType().GetTypeInfo().Assembly.GetManifestResourceStream("Blog.Core.index.html");//这里是配合MiniProfiler进行性能监控的,《文章:完美基于AOP的接口性能分析》,如果你不需要,可以暂时先注释掉,不影响大局。
c.RoutePrefix = ""; //路径配置,设置为空,表示直接在根域名(localhost:8001)访问该文件,注意localhost:8001/swagger是访问不到的,去launchSettings.json把launchUrl去掉,如果你想换一个路径,直接写名字即可,比如直接写c.RoutePrefix = "doc";
});
#endregion
// ↓↓↓↓↓↓ 注意下边这些中间件的顺序,很重要 ↓↓↓↓↓↓
app.UseCors("LimitRequests");
// 跳转https
//app.UseHttpsRedirection();
// 使用静态文件
app.UseStaticFiles();
// 使用cookie
app.UseCookiePolicy();
// 返回错误码
app.UseStatusCodePages();//把错误码返回前台,比如是404
// Routing
app.UseRouting();
// 这种自定义授权中间件,可以尝试,但不推荐
// app.UseJwtTokenAuth();
// 先开启认证
app.UseAuthentication();
// 然后是授权中间件
app.UseAuthorization();
// 开启异常中间件,要放到最后
//app.UseExceptionHandlerMidd();
app.UseMiniProfiler();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
endpoints.MapHub<ChatHub>("/api2/chatHub");
});
}
}
}