15、(行为型设计模式)Java 责任链模式深度学习指南

以下是为你精心撰写的 《Java 责任链模式深度学习指南》,专为 Java 后端开发者打造,内容涵盖:定义、作用、与过滤器/拦截器的深度对比、真实业务场景、手写实现、Spring Filter/AOP 实现、Spring Gateway 实现、避坑指南、最佳实践、面试高频题,所有示例均含中文注释,可直接用于项目重构、权限校验、风控拦截、日志记录、API 网关、审批流等核心场景。


📘 Java 责任链模式深度学习指南

—— 从“多重 if-else”到“流水线式拦截”的架构升级

作者:Java 后端架构实战导师
适用对象:Java 后端开发者(Spring Boot / 微服务 / API 网关 / 风控系统 / 权限系统)
目标:彻底掌握“让多个对象有机会处理请求,形成一条处理链”的核心模式,告别“嵌套 if-else”和“硬编码顺序”
核心原则“我不是唯一处理者,我只是链上的一环,传下去,或拦住它。”


✅ 一、什么是责任链模式?

📌 定义:

责任链模式(Chain of Responsibility Pattern) 是一种行为型设计模式,它将请求的发送者和接收者解耦,使多个对象都有机会处理这个请求。请求沿着一条处理链传递,直到有一个对象处理它为止。

🔍 核心思想:

  • 一组处理器(Handler) 组成一条链
  • 每个处理器只关心自己是否能处理,不能处理就传递给下一个
  • 请求从链头开始,逐级传递,直到被处理或链尾
  • 每个处理器可选择:
    • ✅ 自己处理并终止链
    • ✅ 自己处理并继续传递
    • ✅ 不处理,直接传递给下一个
  • 客户端不知道由谁处理,只负责发起请求

💡 一句话记忆
“我要找领导签字,先找组长,他没权限就找主管,主管没权限就找总监——谁有权限谁处理,不关我的事。”

🆚 责任链模式 vs 多重 if-else

方式多重 if-else责任链模式
结构所有逻辑写在一个地方每个条件独立成一个类
扩展性新增规则需修改原代码新增处理器只需注册到链中
可读性嵌套深,难维护结构清晰,职责单一
顺序控制固定写死可动态调整顺序
复用性代码复用差处理器可复用在多个链中
典型场景小型工具类权限、风控、日志、过滤器

经典比喻
你去银行办业务:

  • if-else:柜员问你“是转账?是开户?是挂失?” → 一连串 if 判断
  • 责任链:你先找大堂经理 → 他判断“是咨询” → 转给客户经理 → 他判断“是开户” → 转给柜台 → 柜台处理 → 完成

✅ 二、责任链模式有什么作用?(Why Use Chain of Responsibility?)

作用说明
消除嵌套 if-else避免“if (A) { if (B) { if © { … } } }”的地狱结构
支持动态扩展新增拦截器/过滤器只需新增类,不改原有代码
支持灵活顺序可配置处理器执行顺序,如:日志 → 权限 → 限流 → 业务
解耦请求者与处理者客户端无需知道谁处理、怎么处理
支持条件终止一个处理器处理完可终止链,避免后续无效处理
支持组合处理多个处理器可协同完成复杂逻辑(如:鉴权 + 审计 + 缓存)
提高可测试性每个处理器可独立单元测试
支撑拦截器架构Spring Filter、Spring Interceptor、Netty ChannelHandler 都是责任链模式

💡 经典名言
Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request.
——《Design Patterns: Elements of Reusable Object-Oriented Software》


✅ 三、责任链模式的典型使用场景(Java 后端真实案例)

场景说明是否推荐使用责任链模式
API 网关拦截器日志 → 鉴权 → 限流 → 签名验证 → 路由✅ 强烈推荐
Web 请求过滤器Encoding → CORS → XSS 防护 → Session 检查✅ 强烈推荐
订单风控系统黑名单 → 频率限制 → IP 地域 → 设备指纹 → 人工审核✅ 强烈推荐
审批流程提交 → 部门主管 → 财务 → 总监 → 归档✅ 强烈推荐
日志记录记录请求参数 → 记录响应时间 → 记录用户 → 记录IP✅ 推荐
消息队列消费者消息解码 → 校验格式 → 业务处理 → 重试 → 死信队列✅ 推荐
Spring Security认证 → 授权 → 会话管理 → CSRF 防护✅ 推荐
缓存预热检查本地缓存 → 检查 Redis → 查询 DB → 写入缓存✅ 推荐
数据校验非空校验 → 格式校验 → 业务规则校验 → 数据库唯一性校验✅ 推荐
单一校验只有“用户名非空”一个判断❌ 直接写 if 即可
顺序固定、不可变所有请求都必须走 5 个步骤,无选择❌ 用模板方法更清晰
必须全部执行每个环节都必须执行,无终止❌ 用装饰器或策略模式

判断标准
“有一系列处理步骤,它们有先后顺序,但不是每个都必须执行,且可能中途终止?”
→ 是 → 用责任链模式!


✅ 四、责任链模式的三种实现方式详解(含中文注释)

我们从手写经典版Spring Filter/AOP,再到Spring Gateway,逐步深入。


🔹 1. 手写责任链模式(经典实现)

/**
 * 【1】处理器接口:定义处理方法和下一个处理器
 */
interface RequestHandler {
    boolean handle(Request request); // 返回 true 表示已处理,终止链;false 表示继续传递
    void setNext(RequestHandler next); // 设置下一个处理器
}

/**
 * 【2】基础处理器抽象类(可选,简化代码)
 */
abstract class AbstractRequestHandler implements RequestHandler {
    protected RequestHandler next;

    @Override
    public void setNext(RequestHandler next) {
        this.next = next;
    }

    /**
     * 模板方法:统一处理逻辑
     */
    @Override
    public boolean handle(Request request) {
        boolean handled = doHandle(request);
        if (!handled && next != null) {
            return next.handle(request); // 继续传递
        }
        return handled; // 已处理或链尾
    }

    /**
     * 子类必须实现的具体处理逻辑
     */
    protected abstract boolean doHandle(Request request);
}

/**
 * 【3】具体处理器1:日志记录
 */
class LoggingHandler extends AbstractRequestHandler {
    @Override
    protected boolean doHandle(Request request) {
        System.out.println("📝 日志:接收到请求,路径:" + request.getPath() + ",参数:" + request.getParams());
        // 日志不终止链,继续传递
        return false;
    }
}

/**
 * 【4】具体处理器2:黑名单拦截
 */
class BlacklistHandler extends AbstractRequestHandler {
    @Override
    protected boolean doHandle(Request request) {
        String ip = request.getIp();
        if ("192.168.1.100".equals(ip)) {
            System.out.println("⛔ 黑名单拦截:IP " + ip + " 被禁止访问");
            return true; // ✅ 终止链,不再传递
        }
        System.out.println("✅ 黑名单检查:IP " + ip + " 通过");
        return false; // 继续传递
    }
}

/**
 * 【5】具体处理器3:权限校验
 */
class AuthHandler extends AbstractRequestHandler {
    @Override
    protected boolean doHandle(Request request) {
        String token = request.getToken();
        if (token == null || !token.startsWith("Bearer ")) {
            System.out.println("🚫 权限不足:未提供有效 Token");
            return true; // ✅ 终止链
        }
        System.out.println("✅ 权限校验:Token 验证通过");
        return false; // 继续传递
    }
}

/**
 * 【6】具体处理器4:限流检查
 */
class RateLimitHandler extends AbstractRequestHandler {
    private int limit = 5; // 每分钟最多5次请求(简化实现)
    private int count = 0;

    @Override
    protected boolean doHandle(Request request) {
        count++;
        if (count > limit) {
            System.out.println("⚡ 限流拦截:请求频率过高,已超过每分钟 " + limit + " 次");
            return true; // ✅ 终止链
        }
        System.out.println("✅ 限流检查:当前请求次数:" + count);
        return false; // 继续传递
    }
}

/**
 * 【7】请求对象(上下文)
 */
class Request {
    private String path;
    private String ip;
    private String token;
    private String params;

    public Request(String path, String ip, String token, String params) {
        this.path = path;
        this.ip = ip;
        this.token = token;
        this.params = params;
    }

    // getter 方法
    public String getPath() { return path; }
    public String getIp() { return ip; }
    public String getToken() { return token; }
    public String getParams() { return params; }
}

/**
 * 【8】客户端:构建责任链并触发
 */
public class ChainOfResponsibilityDemo {
    public static void main(String[] args) {
        // ✅ 构建责任链:顺序很重要!
        RequestHandler logging = new LoggingHandler();
        RequestHandler blacklist = new BlacklistHandler();
        RequestHandler auth = new AuthHandler();
        RequestHandler rateLimit = new RateLimitHandler();

        // ✅ 设置链路:日志 → 黑名单 → 权限 → 限流
        logging.setNext(blacklist);
        blacklist.setNext(auth);
        auth.setNext(rateLimit);

        // ✅ 模拟请求1:正常请求
        System.out.println("=== 请求1:合法请求 ===");
        Request request1 = new Request("/api/user", "192.168.1.101", "Bearer abc123", "{}");
        logging.handle(request1); // 从链头开始

        System.out.println("\n=== 请求2:黑名单IP ===");
        Request request2 = new Request("/api/user", "192.168.1.100", "Bearer abc123", "{}");
        logging.handle(request2); // 在黑名单被拦截

        System.out.println("\n=== 请求3:无 Token ===");
        Request request3 = new Request("/api/user", "192.168.1.101", null, "{}");
        logging.handle(request3); // 在权限校验被拦截

        System.out.println("\n=== 请求4:限流触发 ===");
        for (int i = 0; i < 6; i++) {
            Request request = new Request("/api/user", "192.168.1.101", "Bearer abc123", "{}");
            logging.handle(request); // 第6次被限流
        }
    }
}
✅ 输出结果:
=== 请求1:合法请求 ===
📝 日志:接收到请求,路径:/api/user,参数:{}
✅ 黑名单检查:IP 192.168.1.101 通过
✅ 权限校验:Token 验证通过
✅ 限流检查:当前请求次数:1

=== 请求2:黑名单IP ===
📝 日志:接收到请求,路径:/api/user,参数:{}
⛔ 黑名单拦截:IP 192.168.1.100 被禁止访问

=== 请求3:无 Token ===
📝 日志:接收到请求,路径:/api/user,参数:{}
✅ 黑名单检查:IP 192.168.1.101 通过
🚫 权限不足:未提供有效 Token

=== 请求4:限流触发 ===
📝 日志:接收到请求,路径:/api/user,参数:{}
✅ 黑名单检查:IP 192.168.1.101 通过
✅ 权限校验:Token 验证通过
✅ 限流检查:当前请求次数:2
...(省略)
✅ 限流检查:当前请求次数:5
📝 日志:接收到请求,路径:/api/user,参数:{}
✅ 黑名单检查:IP 192.168.1.101 通过
✅ 权限校验:Token 验证通过
⚡ 限流拦截:请求频率过高,已超过每分钟 5 次
✅ 优点:
  • 结构清晰:每个处理器职责单一
  • 可扩展:新增拦截器只需新增类
  • 可配置:链顺序可动态调整
  • 可终止:任意环节可中断请求
  • 符合开闭原则
⚠️ 缺点:
  • 手动维护链顺序,容易出错
  • 没有统一异常处理
  • 不支持异步

🔹 2. 责任链模式 + Spring Filter(Web 层实战)

Spring 的 Filter 就是责任链模式的完美体现!每个 Filter 是一个处理器。

import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

/**
 * 【1】日志过滤器(Filter)
 */
@Component
@WebFilter(urlPatterns = "/*")
public class LoggingFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;

        System.out.println("📝 日志:请求路径:" + req.getRequestURI() + ",IP:" + req.getRemoteAddr());

        // ✅ 关键:调用 chain.doFilter() → 传递给下一个 Filter
        chain.doFilter(request, response);

        System.out.println("✅ 日志:请求处理完成");
    }
}

/**
 * 【2】黑名单过滤器
 */
@Component
@WebFilter(urlPatterns = "/*")
public class BlacklistFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        String ip = req.getRemoteAddr();

        if ("192.168.1.100".equals(ip)) {
            System.out.println("⛔ 黑名单拦截:IP " + ip + " 被禁止访问");
            // ✅ 不调用 chain.doFilter() → 终止链
            return;
        }

        System.out.println("✅ 黑名单检查:IP " + ip + " 通过");
        chain.doFilter(request, response); // 继续传递
    }
}

/**
 * 【3】权限过滤器
 */
@Component
@WebFilter(urlPatterns = "/*")
public class AuthFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        String token = req.getHeader("Authorization");

        if (token == null || !token.startsWith("Bearer ")) {
            System.out.println("🚫 权限不足:未提供有效 Token");
            return; // ✅ 终止链
        }

        System.out.println("✅ 权限校验:Token 验证通过");
        chain.doFilter(request, response); // 继续传递
    }
}

/**
 * 【4】限流过滤器(简化版)
 */
@Component
@WebFilter(urlPatterns = "/*")
public class RateLimitFilter implements Filter {

    private int count = 0;

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        count++;
        if (count > 5) {
            System.out.println("⚡ 限流拦截:请求频率过高");
            return; // ✅ 终止链
        }

        System.out.println("✅ 限流检查:当前请求次数:" + count);
        chain.doFilter(request, response);
    }
}
✅ Spring Boot 启动类:
@SpringBootApplication
public class FilterChainDemo {
    public static void main(String[] args) {
        SpringApplication.run(FilterChainDemo.class, args);
    }
}
✅ 测试请求:
curl http://localhost:8080/api/user -H "Authorization: Bearer abc123"
✅ 优势:
  • Spring 自动注册@Component + @WebFilter 自动加入过滤链
  • 顺序可控:通过 @Order 注解指定执行顺序
  • 与 Spring 完全集成:可注入 @Autowired Bean
  • 生产级标准:Spring Security、Spring Cloud Gateway 底层都基于此

设置顺序

@Component
@WebFilter(urlPatterns = "/*")
@Order(1) // 第一个执行
public class LoggingFilter implements Filter { ... }

@Component
@WebFilter(urlPatterns = "/*")
@Order(2) // 第二个执行
public class BlacklistFilter implements Filter { ... }

🔹 3. 责任链模式 + Spring Gateway(微服务网关)

Spring Cloud Gateway 是现代微服务网关的标杆,其底层就是责任链模式 + Reactor 响应式实现!

import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.cloud.gateway.filter.OrderedGatewayFilter;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;

@Component
public class LoggingGatewayFilter implements GlobalFilter, Ordered {

    @Override
    public Mono<Void> filter(org.springframework.web.server.ServerWebExchange exchange, GatewayFilterChain chain) {
        System.out.println("📝 日志:请求路径:" + exchange.getRequest().getURI());

        // ✅ 关键:chain.filter(exchange) → 传递给下一个 Filter
        return chain.filter(exchange).then(Mono.fromRunnable(() -> {
            System.out.println("✅ 日志:请求处理完成");
        }));
    }

    @Override
    public int getOrder() {
        return 1; // 执行顺序
    }
}

@Component
public class AuthGatewayFilter implements GlobalFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String token = exchange.getRequest().getHeaders().getFirst("Authorization");

        if (token == null || !token.startsWith("Bearer ")) {
            System.out.println("🚫 权限不足:未提供 Token");
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            return exchange.getResponse().setComplete(); // ✅ 终止链
        }

        System.out.println("✅ 权限校验:Token 验证通过");
        return chain.filter(exchange); // 继续传递
    }

    @Override
    public int getOrder() {
        return 2;
    }
}

@Component
public class RateLimitGatewayFilter implements GlobalFilter, Ordered {

    private static final int LIMIT = 5;
    private static int count = 0;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        count++;
        if (count > LIMIT) {
            System.out.println("⚡ 限流拦截:请求频率过高");
            exchange.getResponse().setStatusCode(HttpStatus.TOO_MANY_REQUESTS);
            return exchange.getResponse().setComplete(); // ✅ 终止链
        }

        System.out.println("✅ 限流检查:当前请求次数:" + count);
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return 3;
    }
}
✅ application.yml 配置:
spring:
  cloud:
    gateway:
      routes:
        - id: user-service
          uri: http://localhost:8081
          predicates:
            - Path=/api/user/**
✅ 优势:
  • 响应式非阻塞:基于 Reactor,支持高并发
  • 支持复杂路由:可结合 Predicate、Filter、RewritePath
  • 企业级网关标准:Netflix Zuul、Kong、Apigee 都是类似架构
  • 可插拔:自定义 Filter 可热部署

✅ 五、责任链模式 vs 过滤器模式 vs 拦截器模式 对比

模式责任链模式过滤器模式拦截器模式
实现方式手动链式传递Servlet FilterSpring Interceptor
作用域任意 Java 对象Web 层(Servlet 容器)Spring MVC 层
执行时机任意请求进入容器时请求进入 Controller 前
是否支持异步可支持可支持(AsyncContext)可支持(Async)
典型场景风控、审批流日志、安全、编码权限、日志、事务
是否 Spring 管理否(但可 @Component)✅ 是
推荐度✅ 通用✅ Web 层✅ Spring 项目

总结

  • 责任链通用设计模式
  • FilterWeb 层实现
  • InterceptorSpring MVC 层实现
    → 三者本质相同,只是作用范围不同

✅ 六、责任链模式的避坑指南(Java 后端高频踩坑)

问题原因解决方案
❌ 没有设置 next链断裂,请求被丢弃✅ 手动调用 setNext(),或用 Spring 自动装配
❌ 顺序错误权限校验在日志前,无法记录✅ 用 @OrderList<Handler> 按顺序注入
❌ 忘记调用 chain.doFilter()请求被拦截但无响应✅ 每个处理器必须明确决定是否传递
❌ 异常未处理一个处理器异常,链崩溃✅ 每个 Handler 加 try-catch,或用统一异常处理器
❌ 用责任链做同步业务如“扣库存”必须同步✅ 用事务或同步调用,责任链只做前置校验
❌ 处理器太多导致性能差10+ 个处理器逐级调用✅ 用异步、缓存、批量处理优化
❌ 没有统一终止机制所有处理器都执行✅ 明确设计“是否终止”逻辑

✅ 七、学习建议与进阶路径

阶段建议
📚 第一周将你项目中的“登录校验”多层 if-else 重构为责任链(IP → Token → 权限 → 频率)
📚 第二周用 Spring Filter 实现“请求日志 + 黑名单 + 权限校验”三层过滤
📚 第三周用 Spring Gateway 实现“API 网关”:鉴权 + 限流 + 签名验证
📚 第四周阅读 Spring Security 源码:FilterChainProxy 如何构建责任链?
📚 面试准备准备回答:

“你项目中哪里用了责任链模式?”
“Spring Filter 是责任链模式吗?”
“责任链和模板方法区别?”
“如何保证责任链的顺序?” |


✅ 八、责任链模式面试高频题(附答案)

Q1:责任链模式解决了什么问题?

A:解决了“多个对象都有机会处理请求,且顺序可变、可能中途终止”的问题,避免了嵌套 if-else,实现解耦和扩展。

Q2:Spring Filter 是责任链模式吗?

A:是的!FilterChain 就是责任链,每个 Filter 是一个处理器,chain.doFilter() 就是传递请求。

Q3:责任链模式和模板方法模式的区别?

A:

  • 模板方法固定流程,子类实现步骤
  • 责任链动态链,请求逐级传递,可终止
    → 一个是“你必须按我流程走”,一个是“你传给我,我决定接不接”

Q4:如何控制责任链的执行顺序?

A:

  • 手写:调用 setNext() 时按顺序链接
  • Spring:使用 @Order 注解指定优先级
  • Spring Gateway:Ordered 接口定义顺序

Q5:责任链模式适合做事务处理吗?

A:不适合!责任链是前置校验,事务应由模板方法AOP统一管理,责任链中不应有数据库写入。


✅ 九、总结:责任链模式选型决策树

graph TD
    A[需要多个处理器顺序处理请求吗?] --> B{是否在 Web 层?}
    B -->|是| C{是否是 Spring 项目?}
    C -->|是| D[用 @Component + @WebFilter + @Order]
    C -->|否| E[用 Filter + FilterChain]
    B -->|否| F[用自定义 Handler + setNext() 链式构建]

最终推荐

  • Spring Web 项目 → ✅ Filter + @Order(最标准)
  • Spring Cloud Gateway → ✅ GlobalFilter + Ordered(最现代)
  • 非 Web、复杂流程 → ✅ 手写责任链(最灵活)
  • 绝对不要:多重 if-else、顺序硬编码、不终止链

✅ 十、结语:真正的高手,不自己处理,只负责传递

你不是在学“责任链模式”,你是在学“如何让系统各模块各司其职,协同工作”。

当你看到一个请求经过 5 个过滤器,最终被处理,而你只写了 5 个类,每个类只关心自己那一点逻辑时,你已经掌握了架构设计的艺术。
当你用 Spring Gateway 实现“全球限流 + 多租户鉴权 + 签名验证”,而前端只发一个请求时,你已经是网关架构师了。

不要为了“用模式”而用模式,
要为了“系统可扩展、可维护、可监控”而选择它。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

龙茶清欢

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值