🔔 本文 5000+ 字深度原创,含完整代码示例和生产级落地方案。创作不易,如果对你有帮助,请点赞 👍 收藏 ⭐ 关注 🔥 三连支持,你的认可是我持续输出的最大动力!
本文是「设计模式实战解读」系列第九篇。系列文章统一按照 定义 → 痛点场景 → 模式结构 → 核心实现 → 真实应用 → 常见变种 → 优缺点 → 避坑指南 → FAQ 的结构展开,每篇聚焦一个模式讲透。
一句话定义
责任链模式(Chain of Responsibility):将请求沿着处理者链传递,每个处理者要么处理请求,要么传递给下一个处理者,实现请求发送者与处理者的解耦。
归属:行为型模式。
一、没有责任链时的痛点
假设你在做一个 API 网关的过滤器模块,一个请求进来后要经过多个处理步骤:
java
public class GatewayService {
public Response handle(Request request) {
// 1. 参数校验
if (request.getPath() == null || request.getMethod() == null) {
return Response.badRequest("Missing required params");
}
// 2. 鉴权
String token = request.getHeader("Authorization");
if (!tokenValidator.validate(token)) {
return Response.unauthorized("Invalid token");
}
// 3. 限流
if (!rateLimiter.tryAcquire(request.getClientId())) {
return Response.tooManyRequests("Rate limit exceeded");
}
// 4. 黑名单检查
if (blacklistService.isBlocked(request.getClientId())) {
return Response.forbidden("You are blocked");
}
// 5. 日志记录
accessLog.record(request);
// 6. 路由转发
return routeService.forward(request);
}
}
问题:
- 方法越来越长:每加一个处理步骤,方法就长一截
- 顺序硬编码:想调整处理顺序?只能手动挪代码
- 无法动态增减:想临时关掉限流、加个灰度判断?只能改代码重新发布
- 耦合度高:所有处理逻辑挤在一个类里,无法独立测试
- 违反开闭原则:新增处理步骤必须改已有方法
这就是经典的"管道式处理"问题------请求要经过 N 个步骤,每个步骤独立且可能有拦截(阻断请求)、放行(交给下一步)两种结果。
二、模式结构
Request
│
↓
┌───────────────┐
│ Handler 1 │ → 能处理?→ 处理完返回
│ (参数校验) │ → 不能? → 传给下一个
└───────┬───────┘
│
↓
┌───────────────┐
│ Handler 2 │ → 能处理?→ 处理完返回
│ (鉴权) │ → 不能? → 传给下一个
└───────┬───────┘
│
↓
┌───────────────┐
│ Handler 3 │ → 能处理?→ 处理完返回
│ (限流) │ → 不能? → 传给下一个
└───────┬───────┘
│
↓
┌───────────────┐
│ Handler N │ → 最终处理
└───────────────┘
三个角色:
- Handler(处理者接口) :定义统一的
handle(context)方法 - ConcreteHandler(具体处理者):实现处理逻辑,决定"自己处理"还是"往下传"
- Chain(链):管理处理者的顺序和传递逻辑
核心思想:每个 Handler 只关注自己的职责,通过链传递将责任解耦。
三、核心实现
3.1 基础版:链表式责任链
java
// 处理者接口
public abstract class Handler<T> {
private Handler<T> next;
public Handler<T> setNext(Handler<T> next) {
this.next = next;
return next; // 链式构建
}
protected abstract boolean handle(T context);
// 链传递逻辑
public final void execute(T context) {
boolean handled = handle(context);
if (!handled && next != null) {
next.execute(context);
}
}
}
// 具体处理者:参数校验
public class ParamValidationHandler extends Handler<ApiContext> {
@Override
protected boolean handle(ApiContext ctx) {
if (ctx.getPath() == null) {
ctx.setResponse(Response.badRequest("Missing path"));
return true; // 已处理,不再传递
}
return false; // 未处理,继续传递
}
}
// 具体处理者:鉴权
public class AuthHandler extends Handler<ApiContext> {
@Override
protected boolean handle(ApiContext ctx) {
String token = ctx.getHeader("Authorization");
if (!tokenValidator.validate(token)) {
ctx.setResponse(Response.unauthorized("Invalid token"));
return true;
}
return false;
}
}
// 构建链
Handler<ApiContext> chain = new ParamValidationHandler();
chain.setNext(new AuthHandler())
.setNext(new RateLimitHandler())
.setNext(new BlacklistHandler())
.setNext(new LoggingHandler())
.setNext(new RoutingHandler());
chain.execute(context);
3.2 改进版:Spring 自动装配责任链
利用 Spring 的 List 注入 + @Order 排序,零手动维护链:
java
// 处理者接口
public interface GatewayFilter {
/**
* 处理请求
* @param context 请求上下文
* @param chain 责任链,调用 chain.proceed() 传给下一个
* @return true 表示已处理(阻断链),false 表示未处理(继续)
*/
boolean doFilter(ApiContext context, FilterChain chain);
default int getOrder() { return 0; }
}
// 具体处理者:参数校验
@Component
@Order(100)
public class ParamValidationFilter implements GatewayFilter {
@Override
public boolean doFilter(ApiContext context, FilterChain chain) {
if (context.getPath() == null) {
context.setResponse(Response.badRequest("Missing path"));
return true; // 阻断
}
return chain.proceed(context); // 传递
}
}
// 具体处理者:鉴权
@Component
@Order(200)
public class AuthFilter implements GatewayFilter {
@Override
public boolean doFilter(ApiContext context, FilterChain chain) {
String token = context.getHeader("Authorization");
if (!tokenValidator.validate(token)) {
context.setResponse(Response.unauthorized("Invalid token"));
return true;
}
return chain.proceed(context);
}
@Override
public int getOrder() { return 200; }
}
// 具体处理者:限流
@Component
@Order(300)
public class RateLimitFilter implements GatewayFilter {
@Autowired
private RateLimiter rateLimiter;
@Override
public boolean doFilter(ApiContext context, FilterChain chain) {
if (!rateLimiter.tryAcquire(context.getClientId())) {
context.setResponse(Response.tooManyRequests("Rate limit exceeded"));
return true;
}
return chain.proceed(context);
}
@Override
public int getOrder() { return 300; }
}
// 责任链容器
@Component
public class FilterChain {
private final List<GatewayFilter> filters;
private int currentIndex = 0;
public FilterChain(List<GatewayFilter> filters) {
// Spring 自动按 @Order 排序注入
this.filters = filters;
}
public boolean proceed(ApiContext context) {
if (currentIndex < filters.size()) {
GatewayFilter filter = filters.get(currentIndex++);
return filter.doFilter(context, this);
}
return false; // 链结束
}
}
// 使用
@Service
public class GatewayService {
@Autowired
private FilterChain filterChain;
public Response handle(ApiContext context) {
filterChain.proceed(context);
return context.getResponse();
}
}
新增一个过滤器 (比如灰度判断),只需加一个 @Component @Order(250) 的类------其他过滤器零改动。
3.3 函数式责任链(Java 8+)
java
// 用 List<Function> 实现轻量级责任链
public class SimpleChain<T> {
private final List<Predicate<T>> handlers = new ArrayList<>();
public SimpleChain<T> addHandler(Predicate<T> handler) {
handlers.add(handler);
return this;
}
public void execute(T context) {
for (Predicate<T> handler : handlers) {
if (!handler.test(context)) {
break; // handler 返回 false 表示阻断
}
}
}
}
// 使用
new SimpleChain<ApiContext>()
.addHandler(ctx -> ctx.getPath() != null)
.addHandler(ctx -> tokenValidator.validate(ctx.getToken()))
.addHandler(ctx -> rateLimiter.tryAcquire(ctx.getClientId()))
.execute(context);
四、真实应用场景
4.1 框架级应用
| 框架 | 责任链实现 | 处理者 |
|---|---|---|
| Servlet | FilterChain | Filter(编码/登录/跨域) |
| Spring MVC | HandlerInterceptor | 拦截器(鉴权/日志/权限) |
| Spring Security | FilterChainProxy | SecurityFilter(认证/授权/CSRF) |
| Netty | ChannelPipeline | ChannelHandler(编解码/业务处理) |
| MyBatis | Interceptor | 插件(分页/缓存/SQL改写) |
| APISIX / Nginx | Plugin Chain | 请求处理插件 |
4.2 Servlet FilterChain------最经典的工业级责任链
java
// Servlet 规范定义的责任链
public interface FilterChain {
void doFilter(ServletRequest request, ServletResponse response);
}
public interface Filter {
void doFilter(ServletRequest request, ServletResponse response, FilterChain chain);
}
// 你的过滤器
public class EncodingFilter implements Filter {
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) {
req.setCharacterEncoding("UTF-8");
resp.setCharacterEncoding("UTF-8");
chain.doFilter(req, resp); // 关键:传递给下一个
}
}
chain.doFilter() 就是责任链的"传递信号"------调用它,请求继续往下走;不调用,请求在此阻断。
4.3 Netty ChannelPipeline------高性能责任链
java
public class ServerInitializer extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel ch) {
ChannelPipeline pipeline = ch.pipeline();
// 按顺序添加 Handler,形成责任链
pipeline.addLast("decoder", new HttpRequestDecoder());
pipeline.addLast("encoder", new HttpResponseEncoder());
pipeline.addLast("aggregator", new HttpObjectAggregator(65536));
pipeline.addLast("auth", new AuthHandler());
pipeline.addLast("business", new BusinessHandler());
}
}
每个 Handler 处理完后调用 ctx.fireChannelRead(msg) 传递给下一个------Netty 高性能网络模型的核心设计。
4.4 iPaaS 流程执行的责任链
在 iPaaS 平台中,一个流程实例执行时,请求要经过多个中间件处理:
java
// 流程执行上下文
public class FlowExecutionContext {
private String instanceId;
private FlowDefinition flow;
private Map<String, Object> variables;
private List<NodeResult> nodeResults;
private boolean terminated = false;
}
// 流程执行责任链
public interface FlowExecutionFilter {
boolean doFilter(FlowExecutionContext context, ExecutionChain chain);
}
// 处理者1:流程状态检查
@Component
@Order(100)
public class FlowStateCheckFilter implements FlowExecutionFilter {
@Override
public boolean doFilter(FlowExecutionContext context, ExecutionChain chain) {
if (context.getFlow().getState() != FlowState.ACTIVE) {
context.setTerminated(true);
log.warn("流程未激活,跳过执行: {}", context.getInstanceId());
return true;
}
return chain.proceed(context);
}
}
// 处理者2:并发锁控制
@Component
@Order(200)
public class ConcurrentLockFilter implements FlowExecutionFilter {
@Autowired
private DistributedLockService lockService;
@Override
public boolean doFilter(FlowExecutionContext context, ExecutionChain chain) {
String lockKey = "flow:lock:" + context.getInstanceId();
try {
if (!lockService.tryLock(lockKey, 30, TimeUnit.SECONDS)) {
context.setTerminated(true);
log.warn("获取执行锁失败: {}", context.getInstanceId());
return true;
}
return chain.proceed(context);
} finally {
lockService.unlock(lockKey);
}
}
}
// 处理者3:幂等检查
@Component
@Order(300)
public class IdempotentCheckFilter implements FlowExecutionFilter {
@Autowired
private RedisTemplate<String, String> redis;
@Override
public boolean doFilter(FlowExecutionContext context, ExecutionChain chain) {
String idempotentKey = "flow:idempotent:" + context.getInstanceId();
if (Boolean.TRUE.equals(redis.hasKey(idempotentKey))) {
log.warn("重复执行,跳过: {}", context.getInstanceId());
context.setTerminated(true);
return true;
}
redis.opsForValue().set(idempotentKey, "1", 1, TimeUnit.HOURS);
return chain.proceed(context);
}
}
// 处理者4:执行日志记录
@Component
@Order(400)
public class ExecutionLogFilter implements FlowExecutionFilter {
@Override
public boolean doFilter(FlowExecutionContext context, ExecutionChain chain) {
long start = System.currentTimeMillis();
log.info("开始执行流程: {}", context.getInstanceId());
boolean result = chain.proceed(context);
long cost = System.currentTimeMillis() - start;
log.info("流程执行完成: {}, 耗时: {}ms", context.getInstanceId(), cost);
return result;
}
}
// 处理者5:实际执行
@Component
@Order(9999)
public class ActualExecutionFilter implements FlowExecutionFilter {
@Override
public boolean doFilter(FlowExecutionContext context, ExecutionChain chain) {
// 真正的流程执行逻辑
flowEngine.execute(context.getFlow(), context.getVariables());
return false;
}
}
这个链的优势:新增一个全局处理逻辑(比如灰度放量),只需加一个 @Component @Order(350) 的 Filter------流程引擎核心代码零改动。
五、常见变种
5.1 纯责任链(全部执行)vs 拦截型(可阻断)
java
// 纯责任链:所有 Handler 都执行
public void execute(Context ctx) {
for (Handler handler : handlers) {
handler.handle(ctx);
}
}
// 拦截型:某个 Handler 可以阻断链
public void execute(Context ctx) {
for (Handler handler : handlers) {
if (handler.handle(ctx)) {
break; // 阻断
}
}
}
实际项目中拦截型更常见------鉴权失败直接返回,不执行后续逻辑。
5.2 责任链 + 策略模式
java
// 责任链决定"谁来处理",策略模式决定"怎么处理"
public class RoutingFilter implements GatewayFilter {
@Override
public boolean doFilter(ApiContext context, FilterChain chain) {
// 根据路径选择后端服务(策略)
String backend = routeStrategy.select(context.getPath());
context.setTargetBackend(backend);
return chain.proceed(context);
}
}
5.3 责任链 + 观察者模式
java
// 责任链处理完后,发布事件通知观察者
public class ExecutionLogFilter implements FlowExecutionFilter {
@Autowired
private ApplicationEventPublisher eventPublisher;
@Override
public boolean doFilter(FlowExecutionContext context, ExecutionChain chain) {
boolean result = chain.proceed(context);
// 链执行完后发布事件
eventPublisher.publishEvent(new FlowExecutionEvent(context.getInstanceId(), result));
return result;
}
}
六、优缺点
| 优点 | 缺点 |
|---|---|
| 处理者解耦,各自独立 | 链路过长时性能损耗 |
| 符合开闭原则(新增处理者不改已有代码) | 调试困难(断点要打在链的每个节点) |
| 处理顺序可动态调整(@Order) | 责任链设计不当会导致请求在链中空转 |
| 可动态增减处理者 | 链路过长时堆栈深,异常难追踪 |
| 支持拦截和纯执行两种模式 | 责任链本身不解决"谁该处理"的问题,需要每个 Handler 自己判断 |
七、避坑指南
坑 1:忘记传递------Handler 处理完不调用 chain.proceed()
java
// ❌ 处理完忘记传递,链在此中断
public class AuthFilter implements GatewayFilter {
public boolean doFilter(ApiContext ctx, FilterChain chain) {
if (!validate(ctx.getToken())) {
ctx.setResponse(Response.unauthorized());
return true;
}
// 忘记调 chain.proceed(ctx),后续过滤器全部不执行!
return false;
}
}
// ✓ 正确:处理完后继续传递
public class AuthFilter implements GatewayFilter {
public boolean doFilter(ApiContext ctx, FilterChain chain) {
if (!validate(ctx.getToken())) {
ctx.setResponse(Response.unauthorized());
return true;
}
return chain.proceed(ctx); // 关键:传递给下一个
}
}
坑 2:Handler 顺序错误
java
// ❌ 限流放在鉴权前面 → 未登录用户也能消耗限流配额
@Order(100) RateLimitFilter
@Order(200) AuthFilter
// ✓ 正确:先鉴权,再限流
@Order(100) AuthFilter
@Order(200) RateLimitFilter
原则:越基础、越应该靠前的检查放前面(参数校验 → 鉴权 → 限流 → 业务)。
坑 3:责任链中有状态
java
// ❌ FilterChain 实例有状态(currentIndex),多线程并发会乱
@Component
@Scope("prototype") // 必须每次请求新建
public class FilterChain {
private int currentIndex = 0;
...
}
// ✓ 无状态链:每次执行时创建新实例
@Service
public class GatewayService {
@Autowired
private List<GatewayFilter> filters;
public Response handle(ApiContext context) {
FilterChain chain = new FilterChain(filters); // 每次请求新建
chain.proceed(context);
return context.getResponse();
}
}
坑 4:链路过长,性能损耗
如果责任链有 20 个 Handler,每个 Handler 都执行一遍,即使大部分是"检查后放行",也有性能损耗。
缓解方案:
- 控制链长度(≤ 10 个 Handler)
- 合并相似的 Handler(多个参数校验合并为一个)
- 对高频检查做缓存(鉴权结果缓存)
八、常见问题(FAQ)
Q:责任链模式和策略模式有什么区别?
A:核心意图不同:
- 责任链:请求沿着链传递,每个处理者决定"是否处理"和"是否继续"
- 策略:直接选择一个策略执行,策略之间互不干扰
责任链是"流水线",策略是"选择题"。
Q:责任链模式和装饰器模式有什么区别?
A:两者都是链式结构,但目的不同:
- 责任链 :请求在链上传递,某个节点可能阻断链
- 装饰器 :请求一定会传递到最内层,每层装饰器都做增强
责任链可以"拦截",装饰器只会"增强"。
Q:Servlet Filter 和 Spring Interceptor 都是责任链吗?
A:是的。两者都实现了责任链模式:
- Filter:Servlet 规范定义,在 DispatcherServlet 之前执行
- Interceptor:Spring MVC 定义,在 Controller 之前执行
Filter 粒度更粗(请求级别),Interceptor 粒度更细(方法级别)。
Q:责任链中的 Handler 可以有依赖关系吗?
A:可以有,但不推荐。Handler 之间如果有依赖(比如 B 依赖 A 的处理结果),会导致链的顺序被隐式约束,维护困难。推荐通过 Context 对象传递数据,Handler 之间不直接依赖。
Q:什么时候该用责任链,什么时候该用 if-else?
A:
- 用责任链:处理步骤多(≥ 3 个)、可能动态增减、需要独立测试
- 用 if-else:处理步骤少(1-2 个)、逻辑简单、不会扩展
九、小结
责任链模式的核心价值:将多个处理步骤解耦为独立的处理者,通过链传递实现流水线式处理。
三个实践要点:
- Spring 项目用
List注入 +@Order排序------零手动维护链,新增 Handler 自动生效 - Handler 只关注自己的职责 ------处理完记得调用
chain.proceed(),除非你要阻断链 - 链顺序很重要------基础检查(参数/鉴权)放前面,业务处理放后面
下一篇我们聊建造者模式------当你需要构建一个复杂对象,且构建过程需要多个可选参数时,如何让代码既清晰又灵活。
标签:#设计模式 #责任链模式 #ChainOfResponsibility #行为型模式 #Java #Spring #Filter #Interceptor #网关过滤器 #流程引擎 #面向对象 #软件工程