成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

利用責(zé)任鏈模式設(shè)計(jì)一個(gè)攔截器

dreamans / 684人閱讀

摘要:前言近期在做的攔截器功能,正好用到了責(zé)任鏈模式。通過官方圖就可以非常清楚的看出是一個(gè)責(zé)任鏈模式用責(zé)任鏈模式設(shè)計(jì)一個(gè)攔截器對(duì)于攔截器來說使用責(zé)任鏈模式再好不過了。設(shè)置攔截器到責(zé)任鏈中時(shí)通過反射將的值保存到各個(gè)攔截器中。

前言

近期在做 Cicada 的攔截器功能,正好用到了責(zé)任鏈模式。

這個(gè)設(shè)計(jì)模式在日常使用中頻率還是挺高的,借此機(jī)會(huì)來分析分析。

責(zé)任鏈模式

先來看看什么是責(zé)任鏈模式。

引用一段維基百科對(duì)其的解釋:

責(zé)任鏈模式在面向?qū)ο蟪淌皆O(shè)計(jì)里是一種軟件設(shè)計(jì)模式,它包含了一些命令對(duì)象和一系列的處理對(duì)象。每一個(gè)處理對(duì)象決定它能處理哪些命令對(duì)象,它也知道如何將它不能處理的命令對(duì)象傳遞給該鏈中的下一個(gè)處理對(duì)象。該模式還描述了往該處理鏈的末尾添加新的處理對(duì)象的方法。

光看這段描述可能大家會(huì)覺得懵,簡單來說就是該設(shè)計(jì)模式用于對(duì)某個(gè)對(duì)象或者請(qǐng)求進(jìn)行一系列的處理,這些處理邏輯正好組成一個(gè)鏈條。

下面來簡單演示使用與不使用責(zé)任鏈模式有什么區(qū)別和優(yōu)勢。

責(zé)任鏈模式的應(yīng)用 傳統(tǒng)實(shí)現(xiàn)

假設(shè)這樣的場景:傳入了一段內(nèi)容,需要對(duì)這段文本進(jìn)行加工;比如過濾敏感詞、錯(cuò)別字修改、最后署上版權(quán)等操作。

常見的寫法如下:

public class Main {
    public static void main(String[] args) {
        String msg = "內(nèi)容內(nèi)容內(nèi)容" ;

        String result = Process.sensitiveWord()
                .typo()
                .copyright();
    }
}

這樣看似沒啥問題也能解決需求,但如果我還需要為為內(nèi)容加上一個(gè)統(tǒng)一的標(biāo)題呢?在現(xiàn)有的方式下就不得不新增處理方法,并且是在這個(gè)客戶端(Process)的基礎(chǔ)上進(jìn)行新增。

顯然這樣的擴(kuò)展性不好。

責(zé)任鏈模式實(shí)現(xiàn)

這時(shí)候就到了責(zé)任鏈模式發(fā)揮作用了。

該需求非常的符合對(duì)某一個(gè)對(duì)象、請(qǐng)求進(jìn)行一系列處理的特征。

于是我們將代碼修改:

這時(shí) Process 就是一個(gè)接口了,用于定義真正的處理函數(shù)。

public interface Process {

    /**
     * 執(zhí)行處理
     * @param msg
     */
    void doProcess(String msg) ;
}

同時(shí)之前對(duì)內(nèi)容的各種處理只需要實(shí)現(xiàn)該接口即可:

public class SensitiveWordProcess implements Process {
    @Override
    public void doProcess(String msg) {
        System.out.println(msg + "敏感詞處理");
    }
}

public class CopyrightProcess implements Process {

    @Override
    public void doProcess(String msg) {
        System.out.println(msg + "版權(quán)處理");
    }
}

public class CopyrightProcess implements Process {

    @Override
    public void doProcess(String msg) {
        System.out.println(msg + "版權(quán)處理");
    }
}

然后只需要給客戶端提供一個(gè)執(zhí)行入口以及添加責(zé)任鏈的入口即可:

public class MsgProcessChain {

    private List chains = new ArrayList<>() ;

    /**
     * 添加責(zé)任鏈
     * @param process
     * @return
     */
    public MsgProcessChain addChain(Process process){
        chains.add(process) ;
        return this ;
    }

    /**
     * 執(zhí)行處理
     * @param msg
     */
    public void process(String msg){
        for (Process chain : chains) {
            chain.doProcess(msg);
        }
    }
}

這樣使用起來就非常簡單:

public class Main {
    public static void main(String[] args) {
        String msg = "內(nèi)容內(nèi)容內(nèi)容==" ;

        MsgProcessChain chain = new MsgProcessChain()
                .addChain(new SensitiveWordProcess())
                .addChain(new TypoProcess())
                .addChain(new CopyrightProcess()) ;

        chain.process(msg) ;
    }
}

當(dāng)我需要再增加一個(gè)處理邏輯時(shí)只需要添加一個(gè)處理單元即可(addChain(Process process)),并對(duì)客戶端 chain.process(msg) 是無感知的,不需要做任何的改動(dòng)。

可能大家沒有直接寫過責(zé)任鏈模式的相關(guān)代碼,但不經(jīng)意間使用到的卻不少。

比如 Netty 中的 pipeline 就是一個(gè)典型的責(zé)任鏈模式,它可以讓一個(gè)請(qǐng)求在整個(gè)管道中進(jìn)行流轉(zhuǎn)。

通過官方圖就可以非常清楚的看出是一個(gè)責(zé)任鏈模式:

用責(zé)任鏈模式設(shè)計(jì)一個(gè)攔截器

對(duì)于攔截器來說使用責(zé)任鏈模式再好不過了。

下面來看看在 Cicada 中的實(shí)現(xiàn):

首先是定義了和上文 Process 接口類似的 CicadaInterceptor 抽象類:

public abstract class CicadaInterceptor {

    public boolean before(CicadaContext context,Param param) throws Exception{
        return true;
    }

    public void after(CicadaContext context,Param param) throws Exception{}
}

同時(shí)定義了一個(gè) InterceptProcess 的客戶端:

其中的 loadInterceptors() 會(huì)將所有的攔截器加入到責(zé)任鏈中。

再提供了兩個(gè)函數(shù)分別對(duì)應(yīng)了攔截前和攔截后的入口:

實(shí)際應(yīng)用

現(xiàn)在來看看具體是怎么使用的吧。

在請(qǐng)求的 handle 中首先進(jìn)行加載(loadInterceptors(AppConfig appConfig)),也就是初始化責(zé)任鏈。

接下來則是客戶端的入口;調(diào)用攔截前后的入口方法即可。

由于是攔截器,那么在 before 函數(shù)中是可以對(duì)請(qǐng)求進(jìn)行攔截的。只要返回 false 就不會(huì)繼續(xù)向后處理。所以這里做了一個(gè)返回值的判斷。

同時(shí)對(duì)于使用者來說只需要?jiǎng)?chuàng)建攔截器類繼承 CicadaInterceptor 類即可。

這里做了一個(gè)演示,分別有兩個(gè)攔截器:

記錄一個(gè)業(yè)務(wù) handle 的執(zhí)行時(shí)間。

after 里打印了請(qǐng)求參數(shù)。

同時(shí)可在第一個(gè)攔截器中返回 false 讓請(qǐng)求被攔截。

先來做前兩個(gè)試驗(yàn):

這樣當(dāng)我請(qǐng)求其中一個(gè)接口時(shí)會(huì)將剛才的日志打印出來:

接下來我讓打印執(zhí)行時(shí)間的攔截器中攔截請(qǐng)求,同時(shí)輸入向前端輸入一段文本:

請(qǐng)求接口可以看到如下內(nèi)容:

同時(shí)后面的請(qǐng)求參數(shù)也沒有打印出來,說明請(qǐng)求確實(shí)被攔截下來。

同時(shí)我也可以調(diào)整攔截順序,只需要在 @Interceptor(order = 1) 注解中定義這個(gè) order 屬性即可(默認(rèn)值是 0,越小越先執(zhí)行)。

之前是打印請(qǐng)求參數(shù)的攔截器先執(zhí)行,這次我手動(dòng)將它的 order 調(diào)整為 2,而打印時(shí)間的 order 為 1 。

再次請(qǐng)求接口觀察后臺(tái)日志:

發(fā)現(xiàn)打印執(zhí)行時(shí)間的攔截器先執(zhí)行。

那這個(gè)執(zhí)行執(zhí)行順序如何實(shí)現(xiàn)自定義配置的呢?

其實(shí)也比較簡單,有以下幾步:

在加載攔截器時(shí)將注解里的 order 保存起來。

設(shè)置攔截器到責(zé)任鏈中時(shí)通過反射將 order 的值保存到各個(gè)攔截器中。

最終通過排序重新排列這個(gè)責(zé)任鏈的順序。

貼一些核心代碼。

掃描攔截器時(shí)保存 order 值:

保存 order 值到攔截器中:

重新對(duì)責(zé)任鏈排序:

總結(jié)

整個(gè)責(zé)任鏈模式已經(jīng)講完,希望對(duì)這個(gè)設(shè)計(jì)模式還不了解的朋友帶來些幫助。

上文中的源碼如下:

https://github.com/TogetherOS/cicada:一個(gè)高性能、輕量 HTTP 框架

https://git.io/fxKid

歡迎關(guān)注公眾號(hào)一起交流:

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/71791.html

相關(guān)文章

  • 不得不知的責(zé)任設(shè)計(jì)模式

    世界上最遙遠(yuǎn)的距離,不是生與死,而是它從你的世界路過無數(shù)次,你卻選擇視而不見,你無情,你冷酷啊...... showImg(https://segmentfault.com/img/remote/1460000019550563); 被你忽略的就是責(zé)任鏈設(shè)計(jì)模式,希望它再次經(jīng)過你身旁你會(huì)猛的發(fā)現(xiàn),并對(duì)它微微一笑...... 責(zé)任鏈設(shè)計(jì)模式介紹 抽象介紹 初次見面,了解表象,深入交流之后(看完文中的...

    raise_yang 評(píng)論0 收藏0
  • 忘了再看設(shè)計(jì)模式-行為型

    摘要:推文用設(shè)計(jì)模式解構(gòu)三國是一種什么體驗(yàn)行為型設(shè)計(jì)模式一策略模式工廠模式優(yōu)化結(jié)構(gòu)狀態(tài)模式隨著狀態(tài)改變而改變行為。推文狀態(tài)機(jī)與狀態(tài)模式責(zé)任鏈模式多個(gè)對(duì)象依次處理請(qǐng)求前者指定后者。代理模式代理針對(duì)一個(gè)對(duì)象,為了增加控制等中介雙方都是多個(gè),為了解耦。 策略模式 選擇使用封裝好的一系列算法,可相互替換。 類比:商店[Context]買完衣服買單[Stratege](現(xiàn)金[Concrete Stra...

    ShevaKuilin 評(píng)論0 收藏0
  • 慕課網(wǎng)_《探秘Spring AOP》學(xué)習(xí)總結(jié)

    時(shí)間:2017年09月03日星期日說明:本文部分內(nèi)容均來自慕課網(wǎng)。@慕課網(wǎng):http://www.imooc.com 教學(xué)源碼:https://github.com/zccodere/s...學(xué)習(xí)源碼:https://github.com/zccodere/s... 第一章:課程介紹 1-1 面向切面 課程章節(jié) 概覽 AOP使用 AOP原理 AOP開源運(yùn)用 課程實(shí)戰(zhàn) 課程總結(jié) 面向切面編程是一種...

    Tony_Zby 評(píng)論0 收藏0
  • 通熟易懂的設(shè)計(jì)模式(二)

    摘要:提供酒店相關(guān)的接口返回該時(shí)間段有效的酒店提供航班相關(guān)的接口返回該時(shí)間段有效的航班提供一個(gè)旅行對(duì)外的接口,一次返回酒店和航班信息調(diào)用旅行外觀模式享元模式享元模式主要用于減少創(chuàng)建對(duì)象的數(shù)量,以減少內(nèi)存占用和提高性能。 組合模式(Composite pattern) 組合模式看起來就像對(duì)象組的樹形結(jié)構(gòu),一個(gè)對(duì)象里面包含一個(gè)或一組其他的對(duì)象。它是屬于結(jié)構(gòu)型模式。例如,一個(gè)公司包括很多個(gè)部門,每...

    daydream 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<