大白话说Java设计模式-46-责任链模式(业务实战篇)

📌 PDF :AI人工智能 --- 大模型微调与部署实战项目

大白话说Java设计模式-46-责任链模式(业务实战篇):大白商城风控/审批的"链式处理"

📌 一句话本质:责任链模式就是"多个 handler 串联",请求沿链传递,每个 handler 处理一部分,可中断可继续。

🏷️ 标签:责任链模式 / Java 设计模式 / 链式处理 / 风控审批 / 大白商城 🎯 适合:初中级后端 / 经常被"多步骤处理"困扰的工程师


目录


一、业务场景引入:为什么需要"链式处理"?

大白商城 2024 年风控系统遇到一个经典问题:

"订单支付前要经过 5 步风控校验(黑名单/限频/反欺诈/合规/风控拦截),加新规则要改风控代码!"

我打开代码一看:

java 复制代码
/**
 * ❌ 大白商城老的风控代码
 */
public class RiskControlServiceV0 {

    public boolean check(Order order) {
        // ❌ 硬编码 5 步
        if (isBlackList(order.getUserId())) {
            return false;
        }
        if (isOverFrequency(order.getUserId())) {
            return false;
        }
        if (isFraud(order)) {
            return false;
        }
        if (isCompliance(order)) {
            return false;
        }
        if (isHighRisk(order)) {
            return false;
        }
        return true;
    }
}

这种代码的痛点

序号 问题 后果
加新规则改老代码 改 1 处牵动全身
规则顺序难调整 改顺序要改代码
规则可配置差 运营不能配
单测复杂 要测 5 步

老板要的"加新规则只加 1 个类",怎么搞?

答案就是------责任链模式

1.1 大白话讲透责任链

继续打比方:

场景:订单要经过 5 步风控校验。

  • 错误做法:5 步硬编码在一个方法里
  • 正确做法
    1. 每步校验封装为独立 Handler
    2. Handler 沿传递请求
    3. 每个 Handler 处理后决定是否继续
    4. 加新规则?只加 1 个 Handler

责任链 = 多个 Handler 串联,请求沿链传递,每个 Handler 处理一部分

1.2 责任链模式的 3 个真实场景

大白商城里,责任链模式用在:

场景 "Handler 链"
风控校验 黑名单/限频/反欺诈/合规/拦截
优惠计算 满减/折扣/立减/优惠券/积分
审批流程 主管/经理/总监/CEO
Servlet Filter 鉴权/日志/压缩/缓存
Spring Interceptor 鉴权/日志/性能监控

任何"多步骤链式处理"的场景,都用责任链


二、反面教材:硬编码多步处理的"灾难现场"

我们看 4 个反面教材。

2.1 反面教材 v1:if-else 堆叠

java 复制代码
/**
 * ❌ 反面教材 v1:if-else 堆叠
 */
if (isBlackList(userId)) return false;
if (isOverFrequency(userId)) return false;
// 5 个 if

翻车现场

序号 问题 后果
加新规则改代码 改老代码
顺序难调 改顺序要改代码

2.2 反面教材 v2:Array 存 handler

java 复制代码
/**
 * ❌ 反面教材 v2:Array 存 handler
 */
RiskHandler[] handlers = { blackListHandler, freqHandler, fraudHandler };
for (RiskHandler h : handlers) {
    if (!h.check(order)) return false;
}

翻车现场

序号 问题 后果
Array 写死 加新规则要改类
可配置差 改顺序要改代码

2.3 反面教材 v3:完全分散

java 复制代码
/**
 * ❌ 反面教材 v3:完全分散
 */
public class BlackListService { ... }
public class FrequencyService { ... }
// 5 个独立服务

翻车现场

序号 问题 后果
没有链 业务方自己串
顺序难管 业务方记得顺序

2.4 反面教材 v4:完全没抽象

java 复制代码
/**
 * ❌ 反面教材 v4:完全没抽象
 */
public class RiskServiceV4 {
    public void process() {
        // 1000 行所有逻辑
    }
}

2.5 共同病根

痛点 能不能解决?
加新规则不动老代码 ❌ 全部要改
顺序灵活 ❌ 全部写死
规则可配置 ❌ 全部硬编码
独立测试 ❌ 全部耦合

必须上责任链


三、模式原理:责任链的"Handler + Chain"

3.1 责任链的 2 个核心概念

Handler(处理者)

  • 处理请求
  • 决定是否继续
  • 设置下一个 Handler

Chain(链)

  • 串起所有 Handler
  • 决定顺序
  • 中断 / 继续

大白商城例子

概念 例子
Handler BlackListHandler / FrequencyHandler / FraudHandler
Chain RiskControlChain
请求 Order
响应 boolean(通过/拦截)

3.2 责任链的 3 个核心角色

角色 职责 例子
抽象 Handler 定义处理接口 RiskHandler
具体 Handler 实现具体处理 BlackListHandler
串起 Handler RiskControlChain

3.3 一张图看懂责任链

复制代码
OrderRequest
        ↓
RiskControlChain
        │
        │ 第 1 步
        ↓
BlackListHandler
        │ 通过?
        ├── 否 → return REJECTED
        └── 是 → next
        ↓
FrequencyHandler
        │ 通过?
        ├── 否 → return REJECTED
        └── 是 → next
        ↓
FraudHandler
        │ ...
        ↓
ComplianceHandler
        │ ...
        ↓
HighRiskHandler
        │ 通过?
        ├── 否 → return REJECTED
        └── 是 → return APPROVED

3.4 责任链的"灵魂三问"

Q1:责任链 vs 策略,区别是什么?

答:

  • 责任链多个 Handler 串联(多步处理)
  • 策略单个算法选择(一种算法)
  • 责任链多步顺序处理策略单步选算法
  • 责任链强调"流程",策略强调"选择"

Q2:责任链 vs 状态模式,区别是什么?

答:

  • 责任链链式处理(每步独立)
  • 状态状态机(状态间转换)
  • 责任链每步可中断 ,状态自动转换
  • 责任链强调"流程",状态强调"转换"

Q3:责任链模式的核心价值是什么?

答:

  • 解耦请求和处理(请求不知道有谁处理)
  • 可动态配置(Handler 顺序灵活)
  • 可中断(任意 Handler 可终止)
  • 可独立测试(Handler 独立测试)

3.5 责任链的 3 种实现方式

方式 特点 适用
Handler 持有 next 经典 简单
List + 遍历 灵活
Spring Interceptor 框架级 Web

大白商城主推 List + 遍历方式(可配置)。


四、实战代码:大白商城风控链完整实现

下面是大白商城生产环境在用的责任链实现,全套代码可直接复制到 IDEA 跑

4.1 项目环境与依赖

pom.xml

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
                             https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.2.0</version>
        <relativePath/>
    </parent>

    <groupId>com.dabai.mall</groupId>
    <artifactId>mall-design-pattern-46</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <name>mall-design-pattern-46</name>
    <description>大白商城 - 设计模式 46 责任链模式</description>

    <properties>
        <java.version>17</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

4.2 抽象 Handler:RiskHandler

java 复制代码
package com.dabai.mall.chain;

import com.dabai.mall.chain.RiskContext.RiskResult;

/**
 * ✅ 抽象 Handler:风控处理者
 *
 * @author 大白商城技术团队
 */
public interface RiskHandler {

    /**
     * ✅ 处理
     */
    void handle(RiskContext context, RiskChain chain);
}

4.3 上下文:RiskContext

java 复制代码
package com.dabai.mall.chain;

import lombok.Data;

import java.math.BigDecimal;

/**
 * ✅ 上下文:风控请求
 */
@Data
public class RiskContext {

    private String userId;
    private String orderId;
    private BigDecimal amount;
    private String paymentChannel;
    private String userLevel;
    
    /**
     * 拒绝原因
     */
    private String rejectReason;

    /**
     * 风控结果
     */
    @lombok.Data
    public static class RiskResult {
        private boolean approved;
        private String reason;
        
        public static RiskResult approved() {
            RiskResult r = new RiskResult();
            r.approved = true;
            return r;
        }
        public static RiskResult rejected(String reason) {
            RiskResult r = new RiskResult();
            r.approved = false;
            r.reason = reason;
            return r;
        }
    }
}

4.4 链:RiskChain

java 复制代码
package com.dabai.mall.chain;

import com.dabai.mall.chain.RiskContext.RiskResult;
import lombok.extern.slf4j.Slf4j;

import java.util.List;

/**
 * ✅ 链:风控链
 * <p>
 * 串起所有 Handler,按顺序处理
 *
 * @author 大白商城技术团队
 */
@Slf4j
public class RiskChain {

    private final List<RiskHandler> handlers;
    private int index = 0;

    public RiskChain(List<RiskHandler> handlers) {
        this.handlers = handlers;
    }

    /**
     * ✅ 处理入口
     */
    public RiskResult process(RiskContext context) {
        // ✅ 调用下一个 Handler
        return next(context);
    }

    /**
     * ✅ 继续下一个 Handler
     */
    public RiskResult next(RiskContext context) {
        if (index >= handlers.size()) {
            return RiskResult.approved();
        }
        RiskHandler handler = handlers.get(index++);
        log.info("【风控链】执行: {}", handler.getClass().getSimpleName());
        handler.handle(context, this);
        return context.getRejectReason() == null 
            ? RiskResult.approved() 
            : RiskResult.rejected(context.getRejectReason());
    }
}

4.5 5 个具体 Handler

BlackListHandler

java 复制代码
package com.dabai.mall.chain.handler;

import com.dabai.mall.chain.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

/**
 * ✅ Handler:黑名单
 */
@Slf4j
@Component
public class BlackListHandler implements RiskHandler {

    @Override
    public void handle(RiskContext context, RiskChain chain) {
        // 实际:调 DB / 缓存查黑名单
        boolean isBlack = false;
        if (isBlack) {
            log.info("【风控】黑名单拦截, userId={}", context.getUserId());
            context.setRejectReason("黑名单用户");
            return;  // 不调 next
        }
        chain.next(context);
    }
}

FrequencyHandler

java 复制代码
package com.dabai.mall.chain.handler;

import com.dabai.mall.chain.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

/**
 * ✅ Handler:限频
 */
@Slf4j
@Component
public class FrequencyHandler implements RiskHandler {

    @Override
    public void handle(RiskContext context, RiskChain chain) {
        // 实际:调 Redis 计数
        boolean isOverFreq = false;
        if (isOverFreq) {
            log.info("【风控】限频拦截, userId={}", context.getUserId());
            context.setRejectReason("操作过于频繁");
            return;
        }
        chain.next(context);
    }
}

FraudHandler

java 复制代码
package com.dabai.mall.chain.handler;

import com.dabai.mall.chain.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

/**
 * ✅ Handler:反欺诈
 */
@Slf4j
@Component
public class FraudHandler implements RiskHandler {

    @Override
    public void handle(RiskContext context, RiskChain chain) {
        // 实际:调反欺诈系统
        boolean isFraud = false;
        if (isFraud) {
            log.info("【风控】反欺诈拦截, orderId={}", context.getOrderId());
            context.setRejectReason("疑似欺诈交易");
            return;
        }
        chain.next(context);
    }
}

ComplianceHandler

java 复制代码
package com.dabai.mall.chain.handler;

import com.dabai.mall.chain.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

/**
 * ✅ Handler:合规
 */
@Slf4j
@Component
public class ComplianceHandler implements RiskHandler {

    @Override
    public void handle(RiskContext context, RiskChain chain) {
        // 实际:调合规检查
        boolean isIllegal = false;
        if (isIllegal) {
            log.info("【风控】合规拦截, orderId={}", context.getOrderId());
            context.setRejectReason("不符合合规要求");
            return;
        }
        chain.next(context);
    }
}

HighRiskHandler

java 复制代码
package com.dabai.mall.chain.handler;

import com.dabai.mall.chain.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;

/**
 * ✅ Handler:风控拦截(金额 > 1 万)
 */
@Slf4j
@Component
public class HighRiskHandler implements RiskHandler {

    @Override
    public void handle(RiskContext context, RiskChain chain) {
        // 实际:根据金额和用户等级判断
        if (context.getAmount().compareTo(new BigDecimal("10000")) > 0 
                && !"VIP".equals(context.getUserLevel())) {
            log.info("【风控】高金额拦截, orderId={}", context.getOrderId());
            context.setRejectReason("高金额需要 VIP");
            return;
        }
        chain.next(context);
    }
}

4.6 业务调用方

java 复制代码
package com.dabai.mall.service;

import com.dabai.mall.chain.*;
import com.dabai.mall.chain.RiskContext.RiskResult;
import com.dabai.mall.chain.handler.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.List;

/**
 * ✅ 风控服务:责任链模式的调用方
 * <p>
 * 业务方只调 chain.process(),不关心 handler 细节
 *
 * @author 大白商城技术团队
 */
@Service
public class RiskControlService {

    @Autowired
    private BlackListHandler blackListHandler;

    @Autowired
    private FrequencyHandler frequencyHandler;

    @Autowired
    private FraudHandler fraudHandler;

    @Autowired
    private ComplianceHandler complianceHandler;

    @Autowired
    private HighRiskHandler highRiskHandler;

    /**
     * ✅ 业务方只写一种代码
     */
    public RiskResult check(RiskContext context) {
        // 1️⃣ 构造链
        List<RiskHandler> handlers = List.of(
                blackListHandler, frequencyHandler, 
                fraudHandler, complianceHandler, highRiskHandler);
        RiskChain chain = new RiskChain(handlers);

        // 2️⃣ 启动链
        return chain.process(context);
    }
}

4.7 单元测试

java 复制代码
package com.dabai.mall.chain;

import com.dabai.mall.chain.RiskContext.RiskResult;
import com.dabai.mall.chain.handler.*;
import org.junit.jupiter.api.Test;

import java.math.BigDecimal;
import java.util.List;

import static org.junit.jupiter.api.Assertions.*;

/**
 * 责任链模式完整单元测试
 */
class RiskChainTest {

    @Test
    void testAllPassed() {
        RiskContext context = new RiskContext();
        context.setUserId("USER_001");
        context.setOrderId("ORDER_001");
        context.setAmount(new BigDecimal("100"));
        context.setUserLevel("VIP");

        List<RiskHandler> handlers = List.of(
                new BlackListHandler(),
                new FrequencyHandler(),
                new FraudHandler(),
                new ComplianceHandler(),
                new HighRiskHandler());

        RiskChain chain = new RiskChain(handlers);
        RiskResult result = chain.process(context);

        assertTrue(result.isApproved());
    }

    @Test
    void testHighAmountRejected() {
        RiskContext context = new RiskContext();
        context.setUserId("USER_001");
        context.setOrderId("ORDER_001");
        context.setAmount(new BigDecimal("50000"));  // 高金额
        context.setUserLevel("NORMAL");

        List<RiskHandler> handlers = List.of(
                new BlackListHandler(),
                new FrequencyHandler(),
                new FraudHandler(),
                new ComplianceHandler(),
                new HighRiskHandler());

        RiskChain chain = new RiskChain(handlers);
        RiskResult result = chain.process(context);

        assertFalse(result.isApproved());
    }

    @Test
    void testEmptyChain() {
        // ✅ 空链直接通过
        RiskChain chain = new RiskChain(List.of());
        RiskContext context = new RiskContext();
        RiskResult result = chain.process(context);
        assertTrue(result.isApproved());
    }

    @Test
    void testSingleHandler() {
        // ✅ 单个 handler
        RiskChain chain = new RiskChain(List.of(new BlackListHandler()));
        RiskContext context = new RiskContext();
        RiskResult result = chain.process(context);
        assertTrue(result.isApproved());
    }

    @Test
    void testHandlerShortCircuit() {
        // ✅ Handler 中断
        List<RiskHandler> handlers = List.of(
                new BlackListHandler(),
                new HighRiskHandler());
        RiskChain chain = new RiskChain(handlers);
        RiskContext context = new RiskContext();
        context.setAmount(new BigDecimal("50000"));
        // 第一个通过,第二个拒绝
        RiskResult result = chain.process(context);
        assertFalse(result.isApproved());
    }
}

五、责任链 vs 策略 / 状态模式

5.1 一张表看清区别

模式 关注点 处理 适用
责任链 多步链式 多 Handler 风控/审批
策略 算法选择 单一算法 多种算法
状态 状态机 自动转换 行为随状态变

5.2 决策树

复制代码
多步骤处理?
├── 是
│   ├── 步骤可中断?
│   │   ├── 是 → ✅ 责任链
│   │   └── 否 → 模板方法
└── 否
    ├── 多种算法可切换?
    │   ├── 是 → ✅ 策略
    │   └── 否
    │       ├── 行为随状态变?
    │       │   ├── 是 → ✅ 状态
    │       │   └── 否 → 普通类

大白商城选型

场景 选哪个 原因
风控链 责任链 5 步可中断
支付方式 策略 4 种算法
订单状态 状态 状态机
优惠计算 责任链 多规则组合

六、Servlet Filter 怎么用责任链?

6.1 Filter:经典责任链

核心源码

java 复制代码
/**
 * ✅ Servlet Filter
 */
public interface Filter {
    void doFilter(ServletRequest request, ServletResponse response, 
                   FilterChain chain) throws IOException, ServletException;
}

使用

java 复制代码
/**
 * ✅ 鉴权 Filter
 */
@Component
public class AuthFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, 
                          FilterChain chain) throws IOException, ServletException {
        // 1️⃣ 鉴权
        if (!authenticate(request)) {
            response.getWriter().write("Unauthorized");
            return;
        }
        // 2️⃣ 继续
        chain.doFilter(request, response);
    }
}

关键点

关键点 解释
FilterChain 责任链
doFilter() 继续
不调 中断

6.2 FilterChain:链

java 复制代码
/**
 * ✅ Filter 链
 */
public interface FilterChain {
    void doFilter(ServletRequest var1, ServletResponse var2) 
        throws IOException, ServletException;
}

6.3 大白商城的"抄作业"

java 复制代码
/**
 * 借鉴 Filter:业务 Handler
 */
public interface BusinessHandler {
    void handle(BusinessContext context, BusinessChain chain);
}

七、Spring Interceptor 怎么借鉴责任链?

7.1 HandlerInterceptor:Spring 拦截器

核心源码

java 复制代码
/**
 * ✅ Spring 拦截器
 */
public interface HandlerInterceptor {
    default boolean preHandle(HttpServletRequest request, ...) { return true; }
    default void postHandle(...) { ... }
    default void afterCompletion(...) { ... }
}

使用

java 复制代码
/**
 * ✅ 鉴权拦截器
 */
@Component
public class AuthInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, ...) {
        if (!authenticate(request)) {
            return false;  // 中断
        }
        return true;  // 继续
    }
}

注册

java 复制代码
/**
 * ✅ 拦截器注册
 */
@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new AuthInterceptor())
                .addPathPatterns("/api/**");
    }
}

7.2 InterceptorRegistry:链

Spring 内部用 HandlerExecutionChain 串起所有拦截器:

java 复制代码
/**
 * ✅ 拦截器链
 */
public class HandlerExecutionChain {
    private final Object handler;
    private final List<HandlerInterceptor> interceptors = new ArrayList<>();
    
    boolean applyPreHandle(HttpServletRequest request, ...) {
        for (HandlerInterceptor interceptor : interceptors) {
            if (!interceptor.preHandle(request, ...)) {
                return false;
            }
        }
        return true;
    }
}

7.3 大白商城的"抄作业"

java 复制代码
/**
 * 借鉴 Spring Interceptor:业务拦截器
 */
public interface BusinessInterceptor {
    boolean preHandle(BusinessContext context);
    void postHandle(BusinessContext context);
    void afterCompletion(BusinessContext context);
}

八、工程决策 Checklist

8.1 ✅ 这 5 种情况,强烈建议用责任链

序号 场景 原因
多步骤处理 风控/审批
步骤可中断 任一可拒绝
顺序灵活 可调整
Handler 独立 单元测试
加新规则 不改老代码

8.2 ❌ 这 5 种情况,绝对不要用责任链

序号 场景 原因
只有 1 步 直接调
步骤不可中断 用模板
业务简单 过度设计
追求简单 类多
步骤固定 硬编码

8.3 ⚠️ 责任链的 6 大常见坑

序号 表现 解决方案
链过长 性能差 控制长度
Handler 顺序 顺序错 配置
忘记 next 中断 模板
状态污染 Handler 之间 隔离
异常处理 中断 统一
循环引用 死循环 检测

8.4 面试官视角:责任链高频追问

Q1:责任链 vs 策略,区别是什么?

答:责任链多步链式处理 (可中断),策略单步算法选择责任链强调"流程",策略强调"选择"

Q2:责任链模式的核心价值是什么?

答:解耦请求和处理 + 可动态配置 + 可中断。请求不知道有谁处理,加新 Handler 不改老代码。

Q3:Servlet Filter 怎么用责任链?

答:Filter 调 chain.doFilter() 继续,不调则中断。多个 Filter 组成 FilterChain经典责任链


九、与其他模式协作

9.1 责任链 + 策略 = 链中用策略

java 复制代码
/**
 * ✅ 责任链 + 策略:Handler 内用策略
 */
public class FraudHandler implements RiskHandler {
    @Autowired
    private FraudCheckStrategy strategy;  // 策略
    @Override
    public void handle(RiskContext context, RiskChain chain) {
        if (strategy.check(context)) {
            context.setRejectReason("疑似欺诈");
            return;
        }
        chain.next(context);
    }
}

9.2 责任链 + 模板方法 = 链中用模板

9.3 责任链 + 状态 = 链中用状态

9.4 大白商城模式协作全景图

复制代码
                    ┌──────────────┐
                    │  责任链      │ ← 本篇
                    └──────┬───────┘
                           │
       ┌───────────┬───────┼───────┬───────────┐
       │           │       │       │           │
   ┌───▼───┐  ┌────▼───┐ ┌▼────┐ ┌▼─────┐  ┌───▼────┐
   │策略   │  │模板方法│ │状态 │ │命令  │  │ 装饰器 │
   │(链内) │  │(骨架) │ │(机)  │ │(动作)│  │(增强)  │
   └───────┘  └────────┘ └──────┘ └──────┘  └───────┘
   26 篇       28 篇     32 篇     34 篇     16 篇

十、本篇小结 + 下篇预告

10.1 本篇小结(5 个核心要点)

  1. 本质 :责任链 = 多 Handler 串联每步可中断
  2. 场景 :风控/审批/优惠计算/Servlet Filter,多步骤处理
  3. 对比:责任链 vs 策略(多步 vs 单步)/ 责任链 vs 状态(流程 vs 转换)。
  4. Servlet Filterchain.doFilter() 经典实现
  5. 避坑:链过长 / 顺序错 / 忘记 next / 状态污染。

10.2 一句话总结

责任链不是"换种方式写多步 if-else",是"用 Handler 链解耦请求和处理" 。大白商城从 5 步硬编码 → 5 个 Handler 串成链------加新风控规则只加 1 个 Handler,顺序可配置,规则可中断

10.3 知识脑图

复制代码
责任链模式
├── 2 个核心概念
│   ├── Handler(处理者)
│   └── Chain(链)
├── 3 大角色
│   ├── 抽象 Handler(RiskHandler)
│   ├── 具体 Handler(5 个)
│   └── 链(RiskChain)
├── 5 个具体 Handler
│   ├── BlackListHandler(黑名单)
│   ├── FrequencyHandler(限频)
│   ├── FraudHandler(反欺诈)
│   ├── ComplianceHandler(合规)
│   └── HighRiskHandler(高金额)
├── 模式对比
│   ├── vs 策略(多步 vs 单步)
│   ├── vs 状态(流程 vs 转换)
│   └── vs 模板(可中断 vs 不可中断)
├── Servlet Filter
│   ├── Filter 接口
│   ├── FilterChain
│   └── doFilter 继续
├── Spring Interceptor
│   ├── HandlerInterceptor
│   ├── InterceptorRegistry
│   └── HandlerExecutionChain
└── 模式协作
    ├── + 策略(链内用策略)
    ├── + 模板(链中用模板)
    └── + 状态(链中用状态)

10.4 下篇预告

第 47 篇【责任链模式 - 源码剖析篇】:JDK / Spring 中的责任链实现

下一篇我们会深入源码,回答三个问题:

  1. Servlet Filter 怎么用责任链?
  2. Spring Interceptor 怎么用责任链?
  3. Netty Pipeline 怎么用责任链?

并附完整的源码解读 + 流程图 + 大白商城的"抄作业"实践。


觉得对您有帮助,麻烦 点点关注啦 ,您的关注是我创作的最大动力~ 🎯

相关推荐
jay神29 分钟前
【计算机毕业设计】基于SpringBoot的程序教学辅助系统
java·前端·vue.js·spring boot·后端·毕业设计·课程设计
2601_962066491 小时前
【Sql Server】Update中的From语句,以及常见更新操作方式
android·java·数据库
yaoxin5211232 小时前
507. Java 反射 - 在 BeanFactory 中实现依赖注入
java·开发语言
OPEN-F2 小时前
C++模板教程:变参模板、折叠表达式与SFINAE
java·开发语言·c++
2601_962072213 小时前
SpringMVC进阶(自定义拦截器以及异常处理)
java
2601_962073814 小时前
Spring全面详解(基础版)
java·后端·spring
谢亮_vipxieliang5 小时前
ValidX分组验证详解:不同场景使用不同验证规则
java·spring boot·后端·spring cloud·eclipse·hibernate
wuminyu5 小时前
深入剖析 Panama Off-heap 的性能损耗与开销
java·linux·c语言·jvm·c++
pnoker5 小时前
IoT DC3 AI 能力:Agentic Center 的设计与边界
java·人工智能·物联网·大模型·spring ai