net core Webapi基礎工程搭建(七)——小試AOP及常規測試_Part 1

前言

一每天不知道怎麼過的,但確實挺忙,事趕事不帶停那種,讓我感受跟在流水線幹活同樣,忙活的事差很少了就喘口氣繼續補充這一系列的內容,前面幾篇基本上把一個常規的後端服務搭建差很少了,後面的會時不時根據本身須要或者常規的測試內容來一點點完善更新。前端

攔截器

這裏先不提AOP的內容,其實在我我的以前的理解,AOP開發的思想就是,咱們作的某些操做例如身份驗證,日誌記錄,異常抓捕等等這些操做,能夠單獨拎出來放那,誰用了加個頭部標識就能夠了,剩餘的交給代碼來處理,這樣咱們開發就只須要關心業務功能,而其餘的全均可以不用考慮,這就是框架的好處,別人封裝集成好,就能夠省去很大的開發工做量。chrome

好,開始說攔截器,其實也是中間層,我的感受跟AOP的概念相似,就放到這裏寫上了。json

異常攔截器

在咱們Api的工程目錄下新建文件夾Filters用於存放攔截器,以後咱們新建ExceptionFilter這個異常的攔截器,用於記錄工程拋異常並作對應回調處理。後端

代碼以下,具體不過多解釋,由於實在以爲這個沒啥說的,只是注意異步調用的問題便可。跨域

public class ExceptionFilter
    {
        private readonly RequestDelegate _next;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="next"></param>
        public ExceptionFilter(RequestDelegate next)
        {
            _next = next;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public async Task Invoke(HttpContext context)
        {
            try
            {
                await _next(context);
            }
            catch (Exception ex) //發生異常
            {
                context.Response.StatusCode = 500;
                LogUtil.Error($"response exception:{ex.Message}");// {ex.StackTrace}
                await ResponseUtil.HandleExceptionAsync(500, "服務器錯誤");
            }
        }
    }

這個地方的ResponseUtil是單獨在Util層建立的(公共類儘可能扔到同一個工程類庫下,之後一鍵打包,各類複用)。瀏覽器

public class ResponseUtil
    {
        /// <summary>
        /// 回調
        /// </summary>
        /// <param name="statusCode">html狀態碼</param>
        /// <param name="msg">消息</param>
        /// <returns></returns>
        public static Task HandleExceptionAsync(int statusCode, string msg)
        {
            var data = new { code = statusCode, msg = msg };
            string text = JsonConvert.SerializeObject(data);
            var response = AprilConfig.HttpCurrent.Response;
            if (string.IsNullOrEmpty(response.ContentType))
            {
                //跨域的時候注意,不帶header無法接收回調
                response.Headers.Add("Access-Control-Allow-Origin", "*");
                response.Headers.Add("Access-Control-Allow-Credentials", "true");
                //由於這個是json
                response.ContentType = "application/json;charset=utf-8";
                response.StatusCode = 200;
                response.ContentLength = text.Length;
                return response.WriteAsync(text);
            }
            else
            {
                return response.WriteAsync(text);
            }
        }
    }

以後咱們依然要在Startup中註冊咱們這個中間層。服務器

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            app.UseMiddleware<ExceptionFilter>();
            …
        }

這樣咱們在全局若是出現異常的時候,能夠統一捕獲到問題,而後作記錄,固然在測試環境下注意,若是這個錯誤幫助頁打開的時候,那上面的攔截器將毫無亂用。app

Startup

測試結果

測試

日誌記錄
這樣若是真是哪一個地方沒有作異常捕獲,全局最終都會一個不漏的抓住而後告訴你,好處是若是懶那就全部地方都不寫了,問題是有些異常即便捕獲可是不須要告知用戶也不須要作記錄(好比文件上傳下載的線程中斷異常之類的),因此這個只是爲了保險起見而不是爲了省事。框架

身份驗證攔截器

接下來咱們繼續建立一個AuthFilter,目的是作身份驗證的判斷,若是沒經過就不必再進入具體的控制器了。

public class AuthFilter
    {
        private readonly RequestDelegate _next;

        public AuthFilter(RequestDelegate next)
        {
            _next = next;
        }

        public Task Invoke(HttpContext context)
        {
            if (context.Request.Method == "OPTIONS")
            {
                return _next(context);
            }
            var headers = context.Request.Headers;
            //檢查頭文件是否有jwt token
            if (!headers.ContainsKey("Authorization"))
            {
                string path = context.Request.Path.Value;
                if (!AprilConfig.AllowUrl.Contains(path) && path.IndexOf("swagger") < 0)
                {
                    //這裏作下相關的身份校驗
                    return ResponseUtil.HandleExceptionAsync(401, "請登陸");
                    
                    //判斷是否有權限查看(在身份驗證後判斷對應的權限,這個方法後續再寫)
                    return ResponseUtil.HandleExceptionAsync(-2, "無權訪問");

                }
            }
            return _next(context);
        }
    }

一樣咱們須要在Startup註冊使用中間層。

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            app.UseMiddleware<ExceptionFilter>();
            app.UseMiddleware<AuthFilter>();
            …
        }

測試

測試
而後訪問咱們的Swagger,效果就很明顯了。

Swagger

小結

這一篇主要就是引入中間層的使用,我的認爲何AOP開發OOP開發徹底因人而異,不必爲了追求新技術而去總體大功能改造,新技術確實使用起來方便,也有很好的前景,可是對於企業來說,穩定是最重要的,不會爲了1%的性能速度而去冒30%甚至更高的風險,可是我仍是要說一句,net core到目前爲止已經歷過一個大版本的更新,雖然3.0沒有正式發佈,可是一個個版本的更新以後,穩定性已經很ok了,因此該吃螃蟹均可以動手了
下一篇,繼續引入AOP的開發,主要用的第三方的組件AspectCore,將針對接口調用的時候作一些常規操做。


補充 2019-07-31

今天在作調試的時候發現一個問題,現狀以下

問題
發現這個問題個人第一反應是,字符編碼,可是看到我回調的時候明顯已經設置了ContentType,因此這個應該不是錯誤的緣由,可是屢次刷新的測試結果是偶爾正常,怪異的狀況老是伴隨着bug,因而比對了正確的回調信息和錯誤的回調信息(這裏是經過chrome瀏覽器調試而後獲取的回調信息,具體調試方法後續前端介紹,固然基本上都知道)。

比對結果
這樣一看發現了問題所在,因此這個地方決定再也不自主去設置Length了。

解決

相關文章
相關標籤/搜索