跟我一起學.NetCore之MVC過濾器,這篇看完走路可以仰着頭走


前言

MVC過濾器在之前Asp.Net的時候就已經廣泛使用啦,不管是面試還是工作,總有一個考點或是需求涉及到,可以毫不疑問的說,這個技術點是非常重要的; 在之前參與的面試中,得知很多小伙伴只知道有一兩個過濾器,而對其執行順序了解的還是很模糊,少部分小伙伴甚至還沒有使用過。這里就詳細來說說這塊的內容。

img

正文

來,直接上菜,然后再慢慢品;在Asp.NetCore 中,MVC有以下五種過濾器,根據執行順序的不同,用於不同場景:

img

上圖中大概的流程如下:

  1. 用戶發起一個請求;
  2. 請求經過Asp.NetCore應用程序的中間件管道;
  3. 管道走完之后進入MVC的第一個過濾器:授權過濾器;
  4. 授權通過之后進入資源過濾器的前置方法;
  5. 將異常過濾器加入使用,后續有異常可以進行捕獲,之前如果發生異常不能捕獲;
  6. 進行數據模型綁定,比如參數通過數據模型綁定傳參;
  7. 進入Action過濾器前置方法;
  8. 執行Action方法具體邏輯;
  9. 進入Action過濾器后置方法;
  10. 進入Result過濾器前置方法;
  11. 渲染Result結果;
  12. 進入Result過濾器后置方法;
  13. 進入資源過濾器的后置方法;
  14. 進入中間件管道返回;
  15. 最后將響應結果展現給用戶;

接下來就好好說說每種過濾器的使用,老規矩,還是WebApi項目↓↓↓

  1. 授權過濾器(Authorization Filter)

    授權,用於驗證請求是否有權限訪問對應的Action,一般包含登錄驗證、菜單權限(即接口權限)驗證等。授權過濾器只對請求進行驗證,是單向的,響應返回時不走該過濾器;

    代碼擼起來:

    img

    這里先進行全局注冊過濾器進行測試,即只要注冊之后,所有請求都需要經過授權過濾器校驗,后續單獨說說注冊方式范圍:

    img

    在默認生成的接口中打印字符串,方便看執行結果:

    img

    運行看結果:

    img

    通過上圖可以看到,已經進入授權過濾器中進行相關邏輯判斷;如果將授權邏輯中的局部變量validate設置為true,運行結果如下:

    img

    看過上一篇(跟我一起學.NetCore之熟悉的接口權限驗證不能少(Jwt))的小伙伴肯定有疑問:這和授權中間件中使用Authorize特性授權有什么區別?沒看過的小伙伴也沒關系,應該也會有同樣的疑問;來,聽我慢慢道來,老套路,扒扒授權中間件的代碼,看看怎么回事?

    img

    先來看看Authorize特性里面都有什么,關鍵是實現了IAuthorizeData接口,如下圖:

    img

    找到授權的入口點,即中間件注冊授權那里着手,如下圖:

    img

    從而找AuthorizationMiddleware的具體實現,關鍵代碼如下圖:

    img

    總的來說,使用授權中間的時,標注Authorize特性的Action,會通過默認的AuthorizeFilter進行驗證處理,這就是為什么在上一節權限驗證的時候我們沒有單獨編寫授權過濾器,而是偏重於校驗的邏輯,只關注驗證的角色或策略;這里就不打算再看AuthorizeFilter的源碼,有興趣的小伙伴好好研究研究。

  2. 資源過濾器(Resource Filter)

    資源過濾器分為前置方法和后置方法,一般都會在前置方法做相關處理,比如說需要改改模型綁定的邏輯,但更多常用的是用於數據緩存處理,因為是在授權過濾器之后的第一個,如果取得緩存數據,直接返回結果,就減少后面代碼邏輯執行;后置方法在之后所有代碼邏輯執行完成,返回時經過。

    代碼擼起來:

    img

    這里還是以全局的方式進行注冊資源過濾器:

    img

    運行效果如下:

    img

    將授權過濾器中的validate改為false,這里模擬代表有權限繼續執行:

    img

  3. 異常過濾器(Exception Filter)

    用於服務器向客戶端寫入響應內容之前進行系統異常捕獲,一般用於業務場景統一異常的處理,如果沒有特殊需求,不必每種業務都進行異常處理,通過異常過濾器統一捕獲處理即可,記錄相關日志,便於異常問題分析;

    先模擬處理業務時,拋異常了,如下:

    img

    異常信息直接返回給用戶,體驗是相當不好的,所以一般會將異常進行捕獲處理,由於異常信息容易讓開發者進行問題排查,所以一般會將其以日志的形式記錄;系統中肯定會考慮很多異常的地方,不可能處處都進行手動捕獲一下再處理,顯得代碼臃腫的同時還不好維護,所以用異常過濾器統一進行捕獲處理就顯得很有必要了,當然,一些很關鍵的業務可以進行單獨捕獲處理;異常過濾使用如下:

    img

    將其全局注冊,看運行效果:

    img

    小伙伴看到這,有沒好奇為什么不在授權過濾器和資源過濾器中拋出異常測試,而是選擇在Action方法中拋出異常,還記得第一張圖過濾器順序嗎(小伙伴再去重溫一下~),那是因為授權過濾器和資源過濾器那還沒有異常過濾器,所以發生異常時捕獲不到,這也是小伙伴要特別注意的,需要自己處理好異常;只要在異常過濾器之后請求處理的異常都能捕獲到啦;

    img

  4. Action過濾器(Action Filter)

    Action過濾器有前置和后置兩種方法,一般偏向於業務使用,比如在前置方法中進行驗證模型綁定參數的合法性,也可以對參數進行加工等;后置方法可以對返回結果的處理;

    平時用的比較多,如下:

    img

    全局注冊,運行如下:

    img

    有沒有想試一下,在Action過濾器方法中拋出異常時,看看異常過濾器能不能捕獲到,答案肯定是:能,但在這不截圖給小伙伴們看,小伙伴們動手試試嘛。

  5. Result過濾器(Result Filter)

    Result過濾器也有前置和后置兩種方法,前置方法可以在結果沒返回前,可以對Action返回的結果進行干預處理,后置方法一般是結果已經渲染之后執行;

    API項目用的不多,在MVC Web項目比較適用,使用方式如下:

    img

    將其進行全局注冊,運行如下:

    img

    同樣在此過濾器中拋出異常,異常過濾器捕獲不到啦。

    img

    意不意外,驚不驚喜,其實只要開始進行響應結果處理時,異常過濾器就不捕獲對應異常,需要自己單獨處理;

過濾器的注冊范圍

除了上面的全局注冊,過濾器還可以以特性的方式標注在控制器或對應Action方法上:

全局注冊:針對系統中所有過濾器都有效;

標注在控制器上(Controller):對標注控制器中所有Action方法都有效;

標注在Action上:只針對對應的Action有效;

img

思路:如果有極個別Action不想使用統一的過濾器,可以通過標注特性的方式在對應過濾器邏輯中將其進行過濾掉。

過濾器注冊方式

  • 全局方式注冊

    在Startup中ConfigureServices注冊服務時全局注冊過濾器,如下圖:

    img

  • 特性方式標注

    A、繼承Attribute類時,可以直接標注在控制器(Controller)和Action上,如下圖:

    img

    B、沒有繼承Attribute類的情況,借用TypeFilter、ServiceFilter或自定義IFilterFactory進行特性標注。

    TypeFilter的方式,如下圖:

    img

    ServiceFilter的方式需要單獨注冊一下過濾器服務,控制生命周期,如果沒有注冊過濾器服務會報異常,如下圖:

    img

    注冊過濾器服務就正常了,如下圖:

    img

    自定義IFilterFactory,先實現一個特性類,如下:

    img

    使用如下:

    img

同種過濾器的執行順序

對於不同類型過濾器的執行順序,開篇的圖就說明了,接下來說多個同種過濾器的執行順序;

  • 不同范圍的同種過濾器順序

    上面說到過濾的注冊范圍,有全局注冊、控制器標注、Action標注,同種過濾器在不同范圍注冊是什么個順序?這里以常用的Action過濾器為例,其他過濾器的練習就交給小伙伴了,這里復制出MyActionFilter兩份,分別改名為MyActionFilter1和MyActionFilter2,其中MyActionFilter用於全局注冊,MyActionFilter1用於控制器特性標注,MyActionFilter2用於Action方法標注,運行結果如下:

    img

    結論:全局注冊->控制器->Action。

  • 相同范圍的同種過濾器順序

    將MyActionFilter、MyActionFilter1和MyActionFilter2三個過濾器都標注在Action上,全局和控制器上都注釋掉,看效果:

    img

    結論:默認情況注冊或特性標注順序與執行順序一致。

到這可能小伙伴會想:終於結束啦!!!,哈哈哈,nonono,對於過濾器的執行順序,除了以上默認順序之外,是可以任意調整的,通過實現IOrderedFilter接口,設置對應過濾器的順序屬性即可改變對應的順序,Order值越小,優先級就越高,如下使用:

img

沒有效果圖,差評? 別別別,這里是督促小伙伴自己試一把,不然小伙伴看一下就完事了(不自己操作一把,過兩天就會忘),有沒有用心良苦~

重點:Order排序優先於范圍排序,即先會以Order進行排序,如果一致,再以注冊的范圍排序。

img

總結

好啦,完啦!主要分享了MVC各種過濾器的使用,大概的應用場景,執行順序,注冊范圍及注冊方式。有沒有感覺脖子有點小酸,來,起來走走,仰着頭的那種,標題是不是沒騙小伙伴,絕對真實。 下一篇說說MediatR組件和中介者設計模式。

整理了一些面試資料,關注公眾號“Code綜藝圈”,發送"面試"獲取下載地址,至於教程,手里的也有一些Web前端、.Net后端、Java的教程,但現在網上資源比較多,大部分小伙伴喜歡在線看;如果有需要,小伙伴可以私聊我,目前先把面試相關的資料放上去,收集內容會持續更新,包含一些大廠面試題,助力小伙伴找到心儀的工作:

一個被程序搞丑的帥小伙,關注"Code綜藝圈",識別關注跟我一起學~~~

img

擼文不易,莫要白瞟,三連走起~~~~


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM