责任链模式(Chain of Responsibility)
它的核心思想就是:将请求沿着一条链传递,每个节点(处理器)决定是否处理,或者传递给下一个节点。
🌟 实际应用场景
- 日常业务开发中的典型应用
- 请求参数校验(比如用户注册流程,一步步校验手机号、验证码、用户名是否合法)
- 权限校验、风控拦截
- 审批流(如OA审批,一级主管 → 部门经理 → 总经理)
- 日志拦截链
- 过滤器链(Servlet Filter、Spring Interceptor)
- 数据处理管道(ETL流程,数据逐步清洗、转换)
- 异常处理链
Java责任链简单示例
比如:一个审批流程,金额不同,审批人不同
- 定义 Handler 接口
java
public abstract class Approver {
protected Approver next;
public void setNext(Approver next) {
this.next = next;
}
public abstract void approve(int amount);
}
- 定义具体处理者
java
public class Manager extends Approver {
@Override
public void approve(int amount) {
if (amount <= 1000) {
System.out.println("Manager approved: " + amount);
} else if (next != null) {
next.approve(amount);
}
}
}
java
```java
public class Director extends Approver {
@Override
public void approve(int amount) {
if (amount <= 5000) {
System.out.println("Director approved: " + amount);
} else if (next != null) {
next.approve(amount);
}
}
}
java
public class CEO extends Approver {
@Override
public void approve(int amount) {
if (amount > 5000) {
System.out.println("CEO approved: " + amount);
} else if (next != null) {
next.approve(amount);
}
}
}
- 使用
java
public class Main {
public static void main(String[] args) {
Approver manager = new Manager();
Approver director = new Director();
Approver ceo = new CEO();
manager.setNext(director);
director.setNext(ceo);
manager.approve(800); // Manager审批
manager.approve(3000); // Director审批
manager.approve(10000); // CEO审批
}
}
🚀 责任链模式优势
✅ 解耦请求发送者与处理者
✅ 结构清晰、易扩展(加新节点不用动原来的代码)
✅ 动态组合链路,灵活可配置(比如在 Spring 中可通过配置文件决定链路顺序)
🧩 现实框架中的责任链
框架/库 责任链体现
Servlet Filter Chain
Spring MVC HandlerInterceptor链
MyBatis插件 InterceptorChain
Netty ChannelPipeline
日志系统 log4j Appender链式结构
🚀 整体设计
✅ Handler接口:定义每个处理器
✅ Context对象:贯穿整个链,传递数据
✅ Chain注册器:自动组装链
✅ 异常中断机制:某个环节失败,后续不执行
✅ 链执行器:开始执行链
📄 完整示例代码
- 定义 Handler 接口
java
public interface ChainHandler {
void handle(ChainContext context);
}
- 定义 Chain Context
java
public class ChainContext {
private boolean stopped = false;
private Map<String, Object> data = new HashMap<>();
public void stop() {
this.stopped = true;
}
public boolean isStopped() {
return stopped;
}
public void set(String key, Object value) {
data.put(key, value);
}
public Object get(String key) {
return data.get(key);
}
}
- 创建 Chain Executor
java
public class ChainExecutor {
private final List<ChainHandler> handlers = new ArrayList<>();
public void addHandler(ChainHandler handler) {
handlers.add(handler);
}
public void execute(ChainContext context) {
for (ChainHandler handler : handlers) {
if (context.isStopped()) {
System.out.println("链路中断");
break;
}
handler.handle(context);
}
}
}
- 实现几个业务 Handler
java
public class LoginCheckHandler implements ChainHandler {
@Override
public void handle(ChainContext context) {
System.out.println("① 登录校验");
String user = (String) context.get("user");
if (user == null || user.isEmpty()) {
System.out.println("❌ 用户未登录,流程中断");
context.stop();
}
}
}
java
public class RiskControlHandler implements ChainHandler {
@Override
public void handle(ChainContext context) {
System.out.println("② 风控校验");
int riskScore = (int) context.getOrDefault("risk", 0);
if (riskScore > 80) {
System.out.println("❌ 风险过高,流程中断");
context.stop();
}
}
}
java
public class DataProcessHandler implements ChainHandler {
@Override
public void handle(ChainContext context) {
System.out.println("③ 数据处理完成 ✅");
}
}
- 测试运行
java
public class Main {
public static void main(String[] args) {
ChainExecutor executor = new ChainExecutor();
// 注册处理器
executor.addHandler(new LoginCheckHandler());
executor.addHandler(new RiskControlHandler());
executor.addHandler(new DataProcessHandler());
// 创建上下文
ChainContext context = new ChainContext();
context.set("user", "达滔");
context.set("risk", 60);
executor.execute(context);
System.out.println("====== 再测试风险过高中断 ======");
ChainContext context2 = new ChainContext();
context2.set("user", "达滔");
context2.set("risk", 90); // 高风险
executor.execute(context2);
}
}
🎯 运行效果
① 登录校验
② 风控校验
③ 数据处理完成 ✅
====== 再测试风险过高中断 ======
① 登录校验
② 风控校验
❌ 风险过高,流程中断
链路中断
🌈 后续拓展
这个链你可以很轻松地改造成:
Spring Bean 自动注册 → 每个 ChainHandler 注入到 Spring 容器
链路配置 → 从数据库/配置文件读取 handler 顺序
异步链路 → 改为 CompletableFuture 支持异步流
责任链分组 → 多个 ChainExecutor 分组,比如风控链、审批链