设计模式——责任链模式实战,优雅处理Kafka消息

作者:KD日期:2025/12/18

一、业务背景

Kafka接收消息,需要A,B,C...多种策略做处理,再通过http请求发送给下游。多种策略混在一起很难维护,通过责任链模式把每种策略的代码收敛到自己的Handler中

二、具体设计

1classDiagram
2Handler <|-- StrategyAHandler
3Handler <|-- StrategyBHandler
4Handler <|-- UploadHandler
5Handler: +void handleUserData(UserContext, HandlerChain)
6Handler: +void handleOrderData(OrderContext, HandlerChain)
7class StrategyAHandler {
8+void handleUserData(UserContext, HandlerChain)
9+void handleOrderData(OrderContext, HandlerChain)
10}
11class StrategyBHandler {
12+void handleUserData(UserContext, HandlerChain)
13+void handleOrderData(OrderContext, HandlerChain)
14}
15class UploadHandler {
16+void handleUserData(UserContext, HandlerChain)
17+void handleOrderData(OrderContext, HandlerChain)
18}
19HandlerChain o--o Handler
20class HandlerChain {
21+List~Handler~ chain
22+void doHandle(AbstractContext context)
23}
24HandlerChain --> AbstractContext
25class AbstractContext {
26+JSONObject param
27+int position
28}
29AbstractContext <|-- UserContext
30AbstractContext <|-- OrderContext
31class UserContext {
32+UserInfo userInfo
33}
34class OrderContext {
35+OrderInfo orderInfo
36}
37

三、代码实现

1.HandlerChain类

1public class HandlerChain {
2
3    List<Handler> chain;
4    
5    public HandlerChain() {
6        chain = new ArrayList<>();
7    }
8    
9    public void doHandle(AbstractContext context) {
10        // 截止条件
11        if (context.getPosition() >= chain.size()) {
12            return;
13        }
14        // 获取当前要执行的handler
15        Handler handler = chain.get(context.getPosition());
16        // 移动到下一个要执行的handler位置
17        context.setPosition(context.getPosition() + 1);
18        // 利用Context类的多态,判断执行的具体方法
19        if (context instanceof UserContext) {
20            handler.handleUserData((UserContext) context, this);
21        } else if (context instanceof OrderContext) {
22            handler.handleOrderData((OrderContext) context, this);
23        }
24    }
25    
26    public void addHandler(Handler handler) {
27        chain.add(hander);
28    }
29
30}
31

2.Handler类

  • Handler接口:定义需要处理的消息
1public interface Handler {
2    // 处理用户数据消息
3    void handleUserData(UserContext userContext, HandlerChain chain);
4    // 处理订单数据消息
5    void handleOrderData(OrderContext orderContext, HandlerChain chain);
6}
7
  • Handler实现类:子类结构相同,执行各自的具体逻辑
1@Component
2public class StrategyAHandler implements Handler {
3    // 处理用户数据消息
4    public void handleUserData(UserContext userContext, HandlerChain chain) {
5        // ...
6        // 核心方法,触发流转到下一个handler
7        chain.doHandle(userContext);
8    }
9    // 处理订单数据消息
10    public void handleOrderData(OrderContext orderContext, HandlerChain chain) {
11        ...
12        // 核心方法,触发流转到下一个handler
13        chain.doHandle(orderContext);
14    }
15}
16
17@Component
18public class StrategyBHandler implements Handler {
19 // ...
20}
21
22@Component
23public class UploadHandler implements Handler {
24 // ...
25}
26

3.Context类

  • Context抽象类:定义公共参数
    • param:处理到最后要发http请求,因此构建一个公共的JSONObject类型参数
    • position:标记即将执行的handler所在位置
1@Data
2public abstract class AbstractContext {
3    private JSONObject param = new JSONObject();
4    private int position = 0;
5}
6
  • Context实现类:定义每一种消息独有的参数
1@Data
2public class UserContext extends AbstractContext {
3    private UserInfo userInfo;
4    
5    public UserContext(UserInfo userInfo) {
6        this.userInfo = userInfo;
7    }
8}
9
1@Data
2public class OrderContext extends AbstractContext {
3    private OrderInfo orderInfo;
4    
5    public OrderContext(OrderInfo orderInfo) {
6        this.orderInfo = orderInfo;
7    }
8}
9

4.Handler组装类

  • 作用:接收Kafka消息,把各种策略按任意顺序组装
1@Component
2public class DemoService {
3    @Autowired
4    private StrategyAHandler strategyAHandler;
5    @Autowired
6    private StrategyBHandler strategyBHandler;
7    @Autowired
8    private UploadHandler uploadHandler;
9    
10    // 处理Kafka发来的用户信息
11    public void handleUserData(UserInfo userInfo) {
12        HandlerChain chain = new HandlerChain();
13        chain.addHandler(strategyAHandler);
14        chain.addHandler(strategyBHandler);
15        chain.addHandler(uploadHandler);
16        UserContext userContext = new UserContext(userInfo);
17        chain.doHandle(userContext);
18    }
19    
20    // 处理Kafka发来的订单信息
21    public void handleOrderData(OrderInfo orderInfo) {
22        HandlerChain chain = new HandlerChain();
23        chain.addHandler(strategyBHandler);
24        chain.addHandler(strategyAHandler);
25        chain.addHandler(uploadHandler);
26        OrderContext orderContext = new OrderContext(orderInfo);
27        chain.doHandle(orderContext);
28    }
29}
30

四、总结

  • Handler实现类交给Spring框架来管理,Context和HandlerChain则是每次调用创建一份
  • 实现效果是可以把某个策略的代码收敛在一个Handler实现类中
  • 如果需要去掉某个策略,直接把该策略从chain中去除即可

设计模式——责任链模式实战,优雅处理Kafka消息》 是转载文章,点击查看原文


相关推荐


【Perfetto从入门到精通】2. 使用 Perfetto 追踪/分析 APP 的 Native/Java 内存
Lei_official2025/12/10

这个世界就是这样,你从失败中学到的东西可能比成功中学到的东西更多——《Android 传奇》 说起 Android APP 内存分析,我们第一时间想到的,往往是 Android Studio Profiler、MAT 这样的老牌工具,而 Perfetto 的出现,又为其提供了一种更加贴近底层的视角。而且相比于现有的工具,Perfetto 更加擅长于分析 Native 内存占用,可以说是补齐了工程师在这方面的短板。 在内存方向,我计划用2~3篇文章来介绍 Perfetto 的功能、特点、使用方


昨天分享了一套用 Nano Banana PRO做商业 PPT 定制的玩法,还推荐直接去咸鱼接单搞钱。
饼干哥哥2025/11/30

但有人说没有渠道、不知道怎么弄。。。 欸我还能说什么呢?只能是把做小生意的完整逻辑给大家讲一遍,包括:🧵- 怎么选择赛道? 公域流量:闲鱼实操、小红书怎么玩、公众号机会 私域谈单 SOP —、先讲一下认知:什么是 中介思维(Agent Thinking) 很多职场人或想要做副业的小白,最大的误区是觉得自己“必须先成为专家”才能赚钱。想做 PPT 代写觉得要设计大师,想做数据分析觉得要代码精通。这种思维导致你陷入技能学习的无底洞,或者单纯靠堆砌自己的时间去赚钱,不仅累,而且上限很低。一旦停下


卷积神经网络CNN
代码洲学长2025/12/26

CNN简介 卷积神经网络就是一个包括卷积层和池化层的神经网络,主要应用于计算机视觉方面,应用场景包括图像分类、目标检测、面部解锁、自动驾驶等。 整体架构流程 CNN的主要结构为 输入层,隐藏层 和输出层,主体架构主要体现在隐藏层中的网络,依次为卷积层 池化层 然后全连接层直接输出。CNN分别进行了两场卷积和池化 ,最终通过三个全连接层进行输出。 卷积层结构图 input(32, 32, 3) conv(3, 3, 6) relu(30, 30, 6) pool(2, 2, 6)


Elasticsearch 8.13.4 动态同义词实战全解析
detayun2026/1/4

在搜索引擎的江湖里,“词不达意"往往是阻碍用户找到心仪内容的最后一道鸿沟。当用户搜索"番茄"时,如果你的库里只有"西红柿"和"圣女果”,传统的精确匹配只能让用户空手而归。同义词库,便是那把填补语义裂痕的钥匙。然而,在 Elasticsearch 8.13.4 这个版本中,我们不再满足于重启服务来更新词库的"笨办法",我们要的是如丝般顺滑的动态热更新。 今天,我们就来一场技术突围,深度剖析在 ES 8.13.4 时代,如何玩转动态同义词,让你的搜索引擎拥有"自我进化"的灵魂。 一、 告别"文件搬运


HarmonyOS一杯冰美式的时间 -- UIUtils基础功能
猫猫头啊2026/1/13

一、前言 最近在写状态管理相关的代码,发现 HarmonyOS 的 UIUtils 这个工具类还挺实用的。它主要解决一些状态管理框架在使用过程中遇到的边界问题,比如代理对象、V1/V2 混用、数据绑定这些场景。 今天顺手整理一下它的几个核心功能,方便以后查。 该系列依旧会带着大家,了解,开阔一些不怎么热门的API,也可能是偷偷被更新的API,也可以是好玩的,藏在官方文档的边边角角~当然也会有一些API,之前是我们辛辛苦苦的手撸代码,现在有一个API能帮我们快速实现的,希望大家能找宝藏。 如果您有


LeetCode 377 组合总和 Ⅳ
展菲2026/1/21

文章目录 摘要描述题解答案题解代码分析1. 动态规划的基本思路2. 初始状态3. 状态转移方程4. 为什么这样能计算出排列个数?5. 与组合问题的区别6. 优化:避免不必要的计算 示例测试及结果示例 1:nums = [1,2,3], target = 4示例 2:nums = [9], target = 3示例 3:nums = [1,2], target = 3示例 4:nums = [1], target = 1 时间复杂度空间复杂度进阶问题:如果数组中含有负数问题分析解决方

首页编辑器站点地图

本站内容在 CC BY-SA 4.0 协议下发布

Copyright © 2026 XYZ博客