在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

還在自己實現責任鏈?我建議你造輪子之前先看看這個開源項目

京東云 ? 來源:jf_75140285 ? 作者:jf_75140285 ? 2024-09-20 14:38 ? 次閱讀

1. 前言

設計模式在軟件開發中被廣泛使用。通過使用設計模式,開發人員可以更加高效地開發出高質量的軟件系統,提高代碼的可讀性、可維護性和可擴展性。

責任鏈模式是一種常用的行為型設計模式,它將請求沿著處理鏈進行發送,直到其中一個處理者對請求進行處理為止。在責任鏈模式中,通常會有多個處理者,每個處理者都有一個處理請求的方法。當一個請求到達處理鏈的起點時,會依次傳遞給每個處理者進行處理,直到某個處理者能夠處理該請求。這樣可以保證每個請求都能被處理,并且可以根據實際情況動態地添加或刪除處理者,以滿足不同的需求。

責任鏈模式可以幫助降低系統的耦合度,增加系統的靈活性和可擴展性,其在SpringMVC、Netty等許多框架中均有實現。責任鏈模式常用于以下場景:處理復雜的請求邏輯,例如權限驗證、日志記錄等;避免請求發送者和接收者之間的耦合關系;動態地組織處理流程,以適應不同的請求類型和復雜度。

我們在日常開發中如果要使用責任鏈模式,通常需要自己來實現,但自己臨時實現的責任鏈既不通用,也很容易產生框架與業務代碼耦合不清等問題,增加Code Review 的成本。

Netty的代碼向來以優雅著稱,早年我在閱讀Netty的源碼時,萌生出將其責任鏈的實現應用到業務開發中的想法,之后花了點時間將Netty中責任鏈的實現代碼抽取出來,形成了本項目,也就是pie。pie的核心代碼均來自Netty,絕大部分的 API 與 Netty 是一致的。

pie 是一個可快速上手的責任鏈框架,開發者只需要專注業務,開發相應的業務Handler,即可完成業務的責任鏈落地。

一分鐘學會、三分鐘上手、五分鐘應用,歡迎 star。

pie 源碼地址:https://github.com/feiniaojin/pie.git

pie 案例工程源碼地址:https://github.com/feiniaojin/pie-example.git

2. 快速入門

2.1 引入 maven 依賴

pie 目前已打包發布到 maven 中央倉庫,開發者可以直接通過 maven 坐標將其引入到項目中。


    com.feiniaojin.ddd.ecosystem
    pie
    1.0

目前最新的版本是 1.0

2.2 實現出參工廠

出參也就是執行結果,一般的執行過程都要求有執行結果返回。實現 OutboundFactory 接口,用于產生接口默認返回值。

例如:

public class OutFactoryImpl implements OutboundFactory {
    @Override
    public Object newInstance() {
        Result result = new Result();
        result.setCode(0);
        result.setMsg("ok");
        return result;
    }
}

2.3 實現 handler 接口完成業務邏輯

在 pie 案例工程( https://github.com/feiniaojin/pie-example.git )的 Example1 中,為了展示 pie 的使用方法,實現了一個虛擬的業務邏輯:CMS類項目修改文章標題、正文,大家不要關注修改操作放到兩個 handler 中是否合理,僅作為講解案例。

三個 Handler 功能如下:

CheckParameterHandler:用于參數校驗。

ArticleModifyTitleHandler:用于修改文章的標題。

ArticleModifyContentHandler:用于修改文章的正文。

CheckParameterHandler 的代碼如下:

public class CheckParameterHandler implements ChannelHandler {

    private Logger logger = LoggerFactory.getLogger(CheckParameterHandler.class);

    @Override
    public void channelProcess(ChannelHandlerContext ctx,
                               Object in,
                               Object out) throws Exception {

        logger.info("參數校驗:開始執行");

        if (in instanceof ArticleTitleModifyCmd) {
            ArticleTitleModifyCmd cmd = (ArticleTitleModifyCmd) in;
            String articleId = cmd.getArticleId();
            Objects.requireNonNull(articleId, "articleId不能為空");
            String title = cmd.getTitle();
            Objects.requireNonNull(title, "title不能為空");
            String content = cmd.getContent();
            Objects.requireNonNull(content, "content不能為空");
        }
        logger.info("參數校驗:校驗通過,即將進入下一個Handler");
        ctx.fireChannelProcess(in, out);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx,
                                Throwable cause,
                                Object in,
                                Object out) throws Exception {
        logger.error("參數校驗:異常處理邏輯", cause);
        Result re = (Result) out;
        re.setCode(400);
        re.setMsg("參數異常");
    }
}

ArticleModifyTitleHandler 的代碼如下:

public class ArticleModifyTitleHandler implements ChannelHandler {

    private Logger logger = LoggerFactory.getLogger(ArticleModifyTitleHandler.class);

    @Override
    public void channelProcess(ChannelHandlerContext ctx,
                               Object in,
                               Object out) throws Exception {

        logger.info("修改標題:進入修改標題的Handler");

        ArticleTitleModifyCmd cmd = (ArticleTitleModifyCmd) in;

        String title = cmd.getTitle();
        //修改標題的業務邏輯
        logger.info("修改標題:title={}", title);

        logger.info("修改標題:執行完成,即將進入下一個Handler");
        ctx.fireChannelProcess(in, out);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx,
                                Throwable cause,
                                Object in,
                                Object out) throws Exception {
        logger.error("修改標題:異常處理邏輯");
        Result re = (Result) out;
        re.setCode(1501);
        re.setMsg("修改標題發生異常");
    }
}

ArticleModifyContentHandler 的代碼如下:

public class ArticleModifyContentHandler implements ChannelHandler {

    private Logger logger = LoggerFactory.getLogger(ArticleModifyContentHandler.class);

    @Override
    public void channelProcess(ChannelHandlerContext ctx,
                               Object in,
                               Object out) throws Exception {

        logger.info("修改正文:進入修改正文的Handler");
        ArticleTitleModifyCmd cmd = (ArticleTitleModifyCmd) in;
        logger.info("修改正文,content={}", cmd.getContent());
        logger.info("修改正文:執行完成,即將進入下一個Handler");
        ctx.fireChannelProcess(in, out);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx,
                                Throwable cause,
                                Object in,
                                Object out) throws Exception {

        logger.error("修改標題:異常處理邏輯");

        Result re = (Result) out;
        re.setCode(1502);
        re.setMsg("修改正文發生異常");
    }
}

2.4 通過 BootStrap 拼裝并執行

public class ArticleModifyExample1 {

    private final static Logger logger = LoggerFactory.getLogger(ArticleModifyExample1.class);

    public static void main(String[] args) {
        //構造入參
        ArticleTitleModifyCmd dto = new ArticleTitleModifyCmd();
        dto.setArticleId("articleId_001");
        dto.setTitle("articleId_001_title");
        dto.setContent("articleId_001_content");

        //創建引導類
        BootStrap bootStrap = new BootStrap();

        //拼裝并執行
        Result result = (Result) bootStrap
                .inboundParameter(dto)//入參
                .outboundFactory(new ResultFactory())//出參工廠
                .channel(new ArticleModifyChannel())//自定義channel
                .addChannelHandlerAtLast("checkParameter", new CheckParameterHandler())//第一個handler
                .addChannelHandlerAtLast("modifyTitle", new ArticleModifyTitleHandler())//第二個handler
                .addChannelHandlerAtLast("modifyContent", new ArticleModifyContentHandler())//第三個handler
                .process();//執行
        //result為執行結果
        logger.info("result:code={},msg={}", result.getCode(), result.getMsg());
    }
}

2.5 執行結果

以下是運行 ArticleModifyExample1 的 main 方法打出的日志,可以看到我們定義的 handler 被逐個執行了。

wKgaombtGFuAFlFjAAMfA3tGG9c190.png

3. 異常處理

3.1 Handler 異常處理

當某個Handler執行發生異常時,我們可將其異常處理邏輯實現在當前 Handler 的 exceptionCaught 方法中。

在 pie 案例工程( https://github.com/feiniaojin/pie-example.git )的 example2 包中,展示了某個 Handler 拋出異常時的處理方式。

假設 ArticleModifyTitleHandler 的業務邏輯會拋出異常,實例代碼如下:

public class ArticleModifyTitleHandler implements ChannelHandler {

    private Logger logger = LoggerFactory.getLogger(ArticleModifyTitleHandler.class);

    @Override
    public void channelProcess(ChannelHandlerContext ctx,
                               Object in,
                               Object out) throws Exception {

        logger.info("修改標題:進入修改標題的Handler");
        ArticleTitleModifyCmd cmd = (ArticleTitleModifyCmd) in;
        String title = cmd.getTitle();
        //此處的異常用于模擬執行過程中出現異常的場景
        throw new RuntimeException("修改title發生異常");
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx,
                                Throwable cause,
                                Object in,
                                Object out) throws Exception {
        logger.error("修改標題:異常處理邏輯");
        Result re = (Result) out;
        re.setCode(1501);
        re.setMsg("修改標題發生異常");
    }
}

此時 ArticleModifyTitleHandler 的 channelProcess 方法一定會拋出異常, 在當前 Handler 的 exceptionCaught 方法中對異常進行了處理。

運行 ArticleModifyExample2 的 main 方法,輸出如下:

wKgaombtGGeAdo9GAAHqAaCzzZs111.png

3.2 全局異常處理

有時候,我們不想每個 handler 都處理一遍異常,我們希望在執行鏈的最后統一進行處理。
在 ArticleModifyExample3 中,我們展示了通過一個全局異常進行最后的異常處理,其實現主要分為以下幾步:

3.2.1 業務 Handler 傳遞異常

如果業務 Handler 實現了 ChannelHandler 接口,那么需要手工調用 ctx.fireExceptionCaught 方法向下傳遞異常。
例如 CheckParameterHandler 捕獲到異常時的示例如下:


@Override
public class XXXHandler implements ChannelHandler {

    //省略其他邏輯

    //異常處理
    public void exceptionCaught(ChannelHandlerContext ctx,
                                Throwable cause,
                                Object in,
                                Object out) throws Exception {

        logger.info("參數校驗的異常處理邏輯:不處理直接向后傳遞");
        ctx.fireExceptionCaught(cause, in, out);
    }
}

如果業務 Handler 繼承了 ChannelHandlerAdapter,如果沒有重寫 fireExceptionCaught 方法,則默認將異常向后傳遞。

3.2.2 實現全局異常處理的 Handler

我們把業務異常處理邏輯放到最后的 Handler 中進行處理,該 Handler 繼承了ChannelHandlerAdapter,只需要重寫異常處理的exceptionCaught
方法。
示例代碼如下:

public class ExceptionHandler extends ChannelHandlerAdapter {

    private Logger logger = LoggerFactory.getLogger(ExceptionHandler.class);

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx,
                                Throwable cause,
                                Object in,
                                Object out) throws Exception {

        logger.error("異常處理器中的異常處理邏輯");
        Result re = (Result) out;
        re.setCode(500);
        re.setMsg("系統異常");
    }
}

3.2.3 將 ExceptionHandler 加入到執行鏈中

直接通過 BootStrap 加入到執行鏈最后即可,示例代碼如下:


public class ArticleModifyExample3 {

    private final static Logger logger = LoggerFactory.getLogger(ArticleModifyExample3.class);

    public static void main(String[] args) {
        //入參
        ArticleTitleModifyCmd dto = new ArticleTitleModifyCmd();
        dto.setArticleId("articleId_001");
        dto.setTitle("articleId_001_title");
        dto.setContent("articleId_001_content");
        //創建引導類
        BootStrap bootStrap = new BootStrap();

        Result result = (Result) bootStrap
                .inboundParameter(dto)//入參
                .outboundFactory(new ResultFactory())//出參工廠
                .channel(new ArticleModifyChannel())//自定義channel
                .addChannelHandlerAtLast("checkParameter", new CheckParameterHandler())//第一個handler
                .addChannelHandlerAtLast("modifyTitle", new ArticleModifyTitleHandler())//第二個handler
                .addChannelHandlerAtLast("modifyContent", new ArticleModifyContentHandler())//第三個handler
                .addChannelHandlerAtLast("exception", new ExceptionHandler())//異常處理handler
                .process();//執行
        //result為執行結果
        logger.info("result:code={},msg={}", result.getCode(), result.getMsg());
    }
}

3.2.4 運行 ArticleModifyExample3

運行 ArticleModifyExample3 的 main 方法,控制臺輸出如下,可以看到異常被傳遞到最后的 ExceptionHandler 中進行處理。

wKgZombtGGmAT1MbAAKoayl5eCE437.png

4. 總結

本文通過簡單的例子,向讀者介紹了如何使用pie框架快速進行責任鏈模式開發,包括責任鏈初始化和異常處理等日常開發中常見的場景。讀者可以參考這些案例,并將pie框架應用于實際開發中,以快速實現通用的責任鏈模式,最終降低代碼的耦合度、增加代碼的可擴展性和提高代碼的可讀性。

審核編輯 黃宇

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 接口
    +關注

    關注

    33

    文章

    8968

    瀏覽量

    153361
  • 開源
    +關注

    關注

    3

    文章

    3634

    瀏覽量

    43585
  • 源碼
    +關注

    關注

    8

    文章

    668

    瀏覽量

    30211
收藏 人收藏

    評論

    相關推薦
    熱點推薦

    這個夏天,用代碼定義的硬核實力!RT-Thread開源之夏重磅來襲

    還在為簡歷項目發愁?想和業界大牛零距離交流?渴望讓自己的代碼跑在千萬級設備上?今年,RT-Thread再次加入開源之夏,帶來了四個有趣又有挑戰的項目
    的頭像 發表于 05-23 16:06 ?287次閱讀
    <b class='flag-5'>這個</b>夏天,用代碼定義<b class='flag-5'>你</b>的硬核實力!RT-Thread<b class='flag-5'>開源</b>之夏重磅來襲

    開源力量!樹莓派與 AI 聯手構建智能城市監控!

    用樹莓派規劃的早晨通勤。如果打算出門,看看你所在地區的天氣和交通報告也無妨。但是如果能獲取更具體的數據呢?這就是開發者Glossyio開發這個很酷的RaspberryPi
    的頭像 發表于 05-10 08:35 ?163次閱讀
    <b class='flag-5'>開源</b>力量!樹莓派與 AI 聯手構建智能城市監控!

    在構建自動布線工具之前我會告訴自己的13件事

    在為 tscircuit(一款用TypeScript編寫的開源電子CAD內核)開發自動布線工具上耗費了約一年時間。如果能回到一年前,以下是我會告訴自己的13件事: 一個鍵盤項目自動布
    的頭像 發表于 05-08 11:20 ?558次閱讀
    在構建自動布線工具<b class='flag-5'>之前</b>我會告訴<b class='flag-5'>自己</b>的13件事

    開源項目!Open Echo:一個開源的聲納項目

    “ 這是一個還在迭代中的項目開源的回聲測深儀/水深測量儀/聲吶系統,適用于水文測繪及科研用途。基于Arduino平臺開發并具備良好兼容性 ” Open Echo 概覽 作為持續迭代的開源
    發表于 03-20 13:37

    Open Echo:一個開源的聲納項目

    “ ?這是一個還在迭代中的項目開源的回聲測深儀/水深測量儀/聲吶系統,適用于水文測繪及科研用途。基于Arduino平臺開發并具備良好兼容性? ” ? Open Echo 概覽 作為持續迭代
    的頭像 發表于 03-20 11:14 ?793次閱讀
    Open Echo:一個<b class='flag-5'>開源</b>的聲納<b class='flag-5'>項目</b>

    開源項目!教你如何制作一個開源教育機械臂

    和適應性強的機器人平臺。 作為一個開源項目,構建Pedro所需的所有文件都可以在Pedro Github頁面上找到: 用于3D打印和定制的STL文件。 Gerber文件來制造您自己的Pedro板
    發表于 03-10 11:22

    還在以為智能家居是玩?我家是真能用!

    以前聽到“智能家居”,總覺得是科技發燒友的玩具,離普通人的生活還很遠。直到我自己入手了三翼鳥,才發現智能家居根本不是“玩”,而是實實在在能提升生活品質的利器!今天就從智慧管理和主動服務兩個層面
    的頭像 發表于 03-06 11:17 ?326次閱讀
    <b class='flag-5'>你</b><b class='flag-5'>還在</b>以為智能家居是玩?我家是真能用!

    ElfBoard開源項目|智能消防車項目

    項目——利用ELF 1開發板打造的智慧消防車。該項目展現了物聯網、數據處理等前沿技術在消防領域的應用潛力,下面就和各位小伙伴展示一下這個開源項目
    的頭像 發表于 01-04 16:43 ?642次閱讀
    ElfBoard<b class='flag-5'>開源</b><b class='flag-5'>項目</b>|智能消防車<b class='flag-5'>項目</b>

    開源項目!OpenCat—— 一個全能的平價四足機器人

    的消費市場。可以把它想象成一個有腿的安卓手機或Alexa,帶有一個可供第三方擴展的應用商店。它可以以約每秒 2.6 個身體長度的速度持續運行 60分鐘,或者坐著播放視頻幾個小時。還在脊柱下方預留了一些
    發表于 12-16 11:44

    ElfBoard開源項目|車牌識別項目技術文檔

    車牌識別項目基于百度智能云平臺,旨在利用其強大的OCR服務實現車牌號碼的自動識別。選擇百度智能云的原因是其高效的API接口和穩定的服務質量,能夠幫助開發者快速實現車牌識別應用。這個
    的頭像 發表于 12-06 10:30 ?601次閱讀
    ElfBoard<b class='flag-5'>開源</b><b class='flag-5'>項目</b>|車牌識別<b class='flag-5'>項目</b>技術文檔

    凌蒙派OpenHarmony開源項目榮獲本期Gitee官方推薦

    近日,司凌蒙派OpenHarmony開源項目榮獲本期Gitee官方推薦。本期Gitee官方推薦不僅是對凌蒙派OpenHarmony開源項目
    的頭像 發表于 11-20 01:04 ?806次閱讀
    凌蒙派OpenHarmony<b class='flag-5'>開源</b><b class='flag-5'>項目</b>榮獲本期Gitee官方推薦

    ElfBoard開源項目|“智慧光伏”開源項目技術文檔

    最大化地捕捉和利用。下面就和各位小伙伴詳細介紹一下這一開源項目是怎樣實現的。環境說明1.開發環境操作系統:Ubuntu18.0464位版2.交叉編譯工具:arm-
    的頭像 發表于 10-11 15:52 ?728次閱讀
    ElfBoard<b class='flag-5'>開源</b><b class='flag-5'>項目</b>|“智慧光伏”<b class='flag-5'>開源</b><b class='flag-5'>項目</b>技術文檔

    Matepad pro12.2 已上市半個月,但是還沒有在開源網站看到該項目開源信息,違背開源精神

    Matepad pro12.2 已上市半個月,本人自己也購買了同款12+256的pad,想要同步學習下這款pad的一些體驗還不錯的功能點,但是目前為止還沒有在開源網站看到該項目開源
    發表于 08-27 17:25

    開源項目!基于 Arduino DIY 漂亮的宏機械鍵盤

    。 接下來,我們將要制作的這款鍵盤擁有 12 個按鍵,可以根據自己的喜好和需求,將這些按鍵與所需的快捷鍵進行關聯。盡管這個項目聽起來可能有些復雜,但實際上無論是電子部分還是軟件部分,
    發表于 08-19 17:02

    開源項目!用ESP8266 DIY會爬墻的無人機

    有點神奇,作者表示,下面介紹的這個無人機就能做到! 一個基于NodeMCU飛行控制器和安卓應用控制的爬墻項目。完整的細節和解釋視頻。 相信,會愛上它。 玩無人機需要一個飛行控制器,
    發表于 07-04 09:22
    主站蜘蛛池模板: 奇米色88欧美一区二区 | 五月天婷婷免费视频 | 日韩精品亚洲一级在线观看 | 手机天堂网 | 久久精彩免费视频 | 在线播放亚洲视频 | 一区二区三区四区欧美 | 天天躁天天狠天天透 | 啪啪在线视频 | 性做久久久久久久 | 99久久99久久精品国产 | 亚洲五月激情 | 色v在线| 在线天堂bt种子 | 色视频色露露永久免费观看 | 我要看一级大片 | 高清一区高清二区视频 | 91在线操 | 综合se| 国产亚洲视频在线播放大全 | 天天做天天爱天天爽 | 天天精品视频在线观看资源 | 午夜免费片在线观看不卡 | 在线视频h | 黄色生活毛片 | 久久久久久毛片免费播放 | 黄色www网站 | 日日天天干| 一本到卡二卡三卡免费高 | 女人张开腿给男人桶爽免费 | 国产hs免费高清在线观看 | 性色欧美xo影院 | 午夜免费视频观看 | 特级做a爰片毛片免费看一区 | 天天草天天射 | 精品国产高清在线看国产 | 一级a毛片免费 | 丁香狠狠 | 三级黄a| 好男人社区www在线资源视频 | 一级做a免费视频 |