一、什么是责任链模式
想象一下你在一家大型企业工作,需要申请一笔采购经费。这张申请单需要经过部门经理、财务总监、副总经理层层审批,每个环节都可能修改或驳回请求。这种"流水线式"的处理方式,就是责任链模式在现实生活中的体现。
在编程世界里,责任链模式(Chain of Responsibility)是一种行为设计模式,它允许你将请求沿着处理者链进行传递。每个处理者都可以决定是否处理该请求,或者将请求传递给链中的下一个处理者。这种模式最大的好处是解耦了请求发送者和接收者,让多个对象都有机会处理请求。
二、责任链模式的结构
让我们用Java代码来解剖这个模式的核心结构。假设我们要实现一个Web请求过滤器链:
// 1. 首先定义一个处理请求的抽象类
public abstract class Handler {
protected Handler nextHandler; // 下一个处理者
// 设置下一个处理者
public void setNext(Handler handler) {
this.nextHandler = handler;
}
// 处理请求的抽象方法
public abstract void handleRequest(Request request);
}
// 2. 实现具体的处理者
public class AuthenticationHandler extends Handler {
@Override
public void handleRequest(Request request) {
if (request.getToken() == null) {
System.out.println("认证失败:缺少token");
return;
}
System.out.println("认证通过");
// 传递给下一个处理者
if (nextHandler != null) {
nextHandler.handleRequest(request);
}
}
}
public class AuthorizationHandler extends Handler {
@Override
public void handleRequest(Request request) {
if (!request.getUserRole().equals("admin")) {
System.out.println("授权失败:权限不足");
return;
}
System.out.println("授权通过");
if (nextHandler != null) {
nextHandler.handleRequest(request);
}
}
}
// 3. 请求对象
public class Request {
private String token;
private String userRole;
// 省略getter/setter
}
这个结构展示了责任链模式的三个关键部分:
- 抽象处理者(Handler):定义处理请求的接口和设置下一个处理者的方法
- 具体处理者(AuthenticationHandler等):实现具体的处理逻辑
- 客户端代码:构建处理链并触发请求
三、过滤器链的完整实现
让我们用一个更完整的Web请求过滤器示例来演示。假设我们要处理一个HTTP请求,需要经过以下过滤步骤:
- IP黑名单检查
- 用户认证
- 请求限流
- 敏感词过滤
// 1. 定义过滤器接口
public interface Filter {
void doFilter(HttpRequest request, FilterChain chain);
}
// 2. 实现过滤器链
public class FilterChain {
private List<Filter> filters = new ArrayList<>();
private int index = 0;
public FilterChain addFilter(Filter filter) {
filters.add(filter);
return this; // 支持链式调用
}
public void doFilter(HttpRequest request) {
if (index < filters.size()) {
Filter filter = filters.get(index++);
filter.doFilter(request, this);
} else {
// 所有过滤器通过,执行业务逻辑
System.out.println("执行业务处理...");
}
}
}
// 3. 实现具体过滤器
public class IpFilter implements Filter {
@Override
public void doFilter(HttpRequest request, FilterChain chain) {
if (isInBlackList(request.getIp())) {
System.out.println("IP被列入黑名单");
return;
}
System.out.println("IP检查通过");
chain.doFilter(request);
}
private boolean isInBlackList(String ip) {
// 模拟黑名单检查
return "192.168.1.100".equals(ip);
}
}
public class AuthFilter implements Filter {
@Override
public void doFilter(HttpRequest request, FilterChain chain) {
if (request.getToken() == null) {
System.out.println("未授权请求");
return;
}
System.out.println("认证通过");
chain.doFilter(request);
}
}
// 4. 客户端使用
public class Client {
public static void main(String[] args) {
FilterChain chain = new FilterChain()
.addFilter(new IpFilter())
.addFilter(new AuthFilter())
.addFilter(new RateLimitFilter())
.addFilter(new SensitiveWordFilter());
HttpRequest request = new HttpRequest("192.168.1.1", "token123");
chain.doFilter(request);
}
}
这个实现展示了责任链模式的动态性 - 我们可以随时添加或移除过滤器,而不需要修改其他过滤器的代码。
四、Spring中的责任链实践
在Spring框架中,责任链模式被广泛应用。让我们看看如何在Spring中实现一个过滤器链:
// 1. 定义过滤器接口
public interface OrderFilter {
void filter(Order order, FilterChain chain);
int getOrder(); // 用于确定过滤器的执行顺序
}
// 2. 实现过滤器链
@Service
public class OrderFilterChain {
@Autowired
private List<OrderFilter> filters;
public void doFilter(Order order) {
// 按优先级排序
List<OrderFilter> sortedFilters = filters.stream()
.sorted(Comparator.comparingInt(OrderFilter::getOrder))
.collect(Collectors.toList());
new DefaultFilterChain(sortedFilters).doFilter(order);
}
private static class DefaultFilterChain {
private final List<OrderFilter> filters;
private int position = 0;
public DefaultFilterChain(List<OrderFilter> filters) {
this.filters = filters;
}
public void doFilter(Order order) {
if (position < filters.size()) {
OrderFilter filter = filters.get(position++);
filter.filter(order, this);
} else {
// 所有过滤器通过
System.out.println("订单处理完成");
}
}
}
}
// 3. 实现具体过滤器
@Service
public class InventoryCheckFilter implements OrderFilter {
@Override
public void filter(Order order, FilterChain chain) {
if (!checkInventory(order)) {
throw new RuntimeException("库存不足");
}
chain.doFilter(order);
}
@Override
public int getOrder() {
return 1; // 第一个执行
}
}
Spring的这种实现方式充分利用了IoC容器的优势,通过自动注入和排序简化了过滤器链的构建过程。
五、应用场景分析
责任链模式特别适合以下场景:
- Web请求处理:如Servlet Filter、Spring Interceptor等
- 审批流程:如请假审批、采购审批等多级审批系统
- 日志处理:不同级别的日志由不同的处理器处理
- 错误处理:异常捕获链,每个处理器尝试处理特定类型的异常
- 数据验证:多层次的校验规则
比如在电商系统中,下单流程可能需要:
- 验证用户身份
- 检查商品库存
- 验证优惠券有效性
- 计算运费
- 风险控制检查
每个步骤都可以是一个独立的处理器,通过责任链串联起来。
六、技术优缺点
优点:
- 解耦:发送者不需要知道具体由哪个处理器处理请求
- 灵活性:可以动态添加、删除或重新排序处理器
- 单一职责:每个处理器只关注自己的处理逻辑
- 可扩展性:新增处理器不需要修改现有代码
缺点:
- 性能:长链可能导致性能下降
- 调试困难:请求可能被链中的多个处理器处理,调试时难以跟踪
- 不确定性:请求可能最终没有被任何处理器处理
七、注意事项
- 控制链的长度:过长的处理链会影响性能,必要时可以考虑其他模式
- 避免循环引用:处理器之间相互引用可能导致无限循环
- 明确终止条件:确保请求不会无限传递下去
- 错误处理:考虑处理器抛出异常时的处理策略
- 线程安全:如果链在运行时可能被修改,需要考虑线程安全问题
八、总结
责任链模式是处理复杂业务流程的利器,它像流水线一样将处理逻辑分解为多个独立的步骤,每个步骤专注于自己的职责。在Java生态中,从Servlet Filter到Spring Interceptor,责任链模式无处不在。
当你的系统需要处理需要经过多个检查或处理步骤的请求时,不妨考虑使用责任链模式。它能让你的代码更加灵活、可维护,也更容易应对未来的需求变化。记住,好的架构不是一开始就完美无缺的,而是能够优雅地应对变化。
评论