Mbp經過篩選器和中間件實現異常,日誌,事務及接口返回數據格式化aop處理.

Mbp應用服務層的AOP實現

實現方法:asp.net core mvc 篩選器 + 中間件

日誌,事務,和接口返回結果統一格式化採用操做篩選器,而異常處理採用中間件來處理.

最開始,我是打算用autofac的高級特性的攔截器來作AOP的,可是遇到一個問題,poco controller沒辦法注入到autofac的容器裏面.致使攔截器不能正常工做,因此就採用了篩選器來作.這裏的場景有如下幾個:git

  • AOP是在應用層,而應用層是用poco controller作的,而在asp.net core web api的基架中,controller處在管線的末端.因此能夠在這層進行全局攔截.
  • 中間件處理異常更加靈活,能夠有更多的定製化需求,而異常篩選器是響應抓捕的異常來處理,它至關因而異常發生後的一個處理程序,而中間件能夠來實現相似異常篩選器.
  • 中間件不短路,只是在程序運行的管線上添加了try catch,同時也解決了異步方法出現的異常沒法被捕獲的問題.

實現代碼

  • Mbp.AspNetCore.Filter 添加MbpLogFilter,MbpTransActionFilter,ResponseMiddleware三個操做篩選器
  • Mbp.AspNetCore.Middleware 添加MbpGlobaExceptionMiddleware中間件
  • 在模塊MbpAspNetCoreModule中註冊篩選器和中間件
public override IServiceCollection AddServices(IServiceCollection services)
        {
            services.AddMvc().AddNewtonsoftJson(options =>
            {
                // 忽略循環引用
                options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
                // 不使用駝峯
                options.SerializerSettings.ContractResolver = new DefaultContractResolver();
                // 設置時間格式
                options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss";
            }).AddMvcOptions(options =>
            {
                // 禁用Version的綁定
                options.ModelMetadataDetailsProviders.Add(new ExcludeBindingMetadataProvider(typeof(System.Version)));

                // 統一事務處理中間件
                options.Filters.Add(typeof(MbpTransActionFilter));

                // 統一日誌處理中間件
                options.Filters.Add(typeof(MbpLogFilter));

                // 請求響應統一格式處理中間件
                options.Filters.Add(typeof(ResponseMiddleware));

            }); ;

            AddAutoWebApi(services, new AutoWebApiOptions());

            // 建立Cors策略
            services.AddCors(options =>
            {
                options.AddPolicy("MbpCors",
                builder =>
                {
                    builder.WithOrigins(services.BuildServiceProvider().GetService<IConfiguration>().GetSection("AllowedHosts").Value)
                    .AllowAnyMethod()
                    .AllowAnyHeader(); ;
                });
            });

            return base.AddServices(services);
        }

public override void UseModule(IApplicationBuilder app)
        {
            // 啓用跨域請求中間件
            app.UseCors("MbpCors");

            // 啓用應用服務層全局錯誤處理中間件
            app.UseMiddleware(typeof(MbpGlobaExceptionMiddleware));

            base.UseModule(app);
        }

異常中間件對併發衝突進行單獨處理

public async Task InvokeAsync(HttpContext context, ILogger<MbpGlobaExceptionMiddleware> logger)
        {
            try
            {
                // Call the next delegate/middleware in the pipeline
                await _next(context);
            }
            catch (DbUpdateConcurrencyException ex)
            {
                // 發生衝突時候,犧牲後者.不作具體數據合併操做.提示當前用戶數據已經發生修改,須要重試.
                logger.LogError("併發衝突:" + ex.Message);

                context.Response.ContentType = "application/json";

                await context.Response.WriteAsync(JsonConvert.SerializeObject(new { Code = 500, Message = "提交併發衝突", Version = "1", Data = new List<object>() }));
            }
            catch (Exception ex)
            {
                // 其餘異常
                logger.LogError($"請求[{context.Request.Path}]發生異常:" + ex.Message);

                context.Response.ContentType = "application/json";

                await context.Response.WriteAsync(JsonConvert.SerializeObject(new { Code = 500, Message = "服務器異常", Version = "1", Data = new List<object>() }));
            }
        }

代碼詳細地址:https://github.com/mbpframework/Mbpgithub

相關文章
相關標籤/搜索