第一、責任鏈模式模式定義
客戶端發出一個請求,鏈上的對象都有機會來處理這一請求,而客戶端不需要知道誰是具體的處理對象。這樣就實現了請求者和接受者之間的解耦,並且在客戶端可以實現動態的組合職責鏈。使編程更有靈活性。
定義:使多個對象都有機會處理請求,從而避免了請求的發送者和接受者之間的耦合關系。將這些對象連成一條鏈,並沿着這條鏈傳遞該請求,直到有對象處理它為止。其過程實際上是一個遞歸調用。
要點主要是:
1、有多個對象共同對一個任務進行處理。
2、這些對象使用鏈式存儲結構,形成一個鏈,每個對象知道自己的下一個對象。
3、一個對象對任務進行處理,可以添加一些操作后將對象傳遞個下一個任務。也可以在此對象上結束任務的處理,並結束任務。
4、客戶端負責組裝鏈式結構,但是客戶端不需要關心最終是誰來處理了任務。
類結構圖分析:
第二、責任鏈的優缺點
優點:
職責鏈模式的最主要功能就是:動態組合,請求者和接受者解耦。
請求者和接受者松散耦合:請求者不需要知道接受者,也不需要知道如何處理。每個職責對象只負責自己的職責范圍,其他的交給后繼者。各個組件間完全解耦。
動態組合職責:職責鏈模式會把功能分散到單獨的職責對象中,然后在使用時動態的組合形成鏈,從而可以靈活的分配職責對象,也可以靈活的添加改變對象職責。
缺點:
產生很多細粒度的對象:因為功能處理都分散到了單獨的職責對象中,每個對象功能單一,要把整個流程處理完,需要很多的職責對象,會產生大量的細粒度職責對象。
不一定能處理:每個職責對象都只負責自己的部分,這樣就可以出現某個請求,即使把整個鏈走完,都沒有職責對象處理它。這就需要提供默認處理,並且注意構造鏈的有效性。
第三、責任鏈的引用場景
- 多條件流程判斷 權限控制
- ERP系統 流程審批 總經理、人事經理、項目經理
- Java過濾器的底層實現Filter
比如:在Java過濾器中客戶端發送請求到服務器端,過濾會經過參數過濾、session過濾、表單過濾、隱藏過濾、檢測請求頭過濾
第四、代碼實現
4.1網關權限控制責任鏈模式
在網關作為微服務程序的入口,攔截客戶端所有的請求實現權限控制 ,比如先判斷Api接口限流、黑名單、用戶會話、參數過濾。
Api接口限流→黑名單攔截→用戶會話→參數過濾
4.2入門案例
/** * 抽象角色 */
public abstract class GateWayHandler { //下一個請求
protected GateWayHandler nextGateWayHandler; /** * 處理業務 */
public abstract void serive(); public void setGateWayHandler(GateWayHandler gateWayHandler){ this.nextGateWayHandler = gateWayHandler; } /** * 得到下一個請求 * @return
*/
public void getNextHand() { if (this.nextGateWayHandler != null) { nextGateWayHandler.serive(); } } } /** * 黑名單實現 */
public class BlacklistHandler extends GateWayHandler { @Override public void serive() { System.out.println("黑名單"); //處理下一個請求
getNextHand(); } } /** * 會話攔擊 */
public class ConversationHandler extends GateWayHandler { @Override public void serive() { System.out.println("會話攔截判斷"); //處理下一個請求
getNextHand(); } } /** * 限流 */
public class CurrentLimitHandler extends GateWayHandler{ @Override public void serive() { System.out.println("第一關網關限流操作"); //處理下一個請求
getNextHand(); } } /** * 工廠類 */
public class HandlerFactory { public static GateWayHandler getFirstGateWayHandler(){ GateWayHandler currentLimitHandler = new CurrentLimitHandler(); GateWayHandler blacklistHand = new BlacklistHandler(); currentLimitHandler.setGateWayHandler(blacklistHand); GateWayHandler conversationHandler = new ConversationHandler(); blacklistHand.setGateWayHandler(conversationHandler); return currentLimitHandler; } } /** * 測試類 */
public class Test001 { public static void main(String[] args) { GateWayHandler firstGateWayHandler = HandlerFactory.getFirstGateWayHandler(); firstGateWayHandler.serive(); } }