责任链模式适合处理"一个请求要经过多个步骤"的场景。
比如订单创建,要先校验参数,再补充数据,再算价,再落库。内容审核,要先文本审核,再图片审核,再视频审核。Web 请求进入服务前,也可能经过鉴权、限流、日志、跨域等多个过滤器。
一句话概括:责任链模式把多个处理节点串成一条链,请求沿着链向后传递,每个节点只负责自己的职责。
责任链解决什么问题
不用责任链时,订单创建可能写成这样:
java
public void createOrder(OrderInfo order) {
validate(order);
fillOrder(order);
calculateAmount(order);
saveOrder(order);
}
这段代码看起来不复杂,但问题在于流程和步骤绑死了。
如果要在算价前加一个优惠券校验,或者在落库后加返佣处理,就要修改主流程。
#mermaid-svg-FdwIvLUGzPWg2n02{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-FdwIvLUGzPWg2n02 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-FdwIvLUGzPWg2n02 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-FdwIvLUGzPWg2n02 .error-icon{fill:#552222;}#mermaid-svg-FdwIvLUGzPWg2n02 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-FdwIvLUGzPWg2n02 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-FdwIvLUGzPWg2n02 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-FdwIvLUGzPWg2n02 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-FdwIvLUGzPWg2n02 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-FdwIvLUGzPWg2n02 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-FdwIvLUGzPWg2n02 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-FdwIvLUGzPWg2n02 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-FdwIvLUGzPWg2n02 .marker.cross{stroke:#333333;}#mermaid-svg-FdwIvLUGzPWg2n02 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-FdwIvLUGzPWg2n02 p{margin:0;}#mermaid-svg-FdwIvLUGzPWg2n02 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-FdwIvLUGzPWg2n02 .cluster-label text{fill:#333;}#mermaid-svg-FdwIvLUGzPWg2n02 .cluster-label span{color:#333;}#mermaid-svg-FdwIvLUGzPWg2n02 .cluster-label span p{background-color:transparent;}#mermaid-svg-FdwIvLUGzPWg2n02 .label text,#mermaid-svg-FdwIvLUGzPWg2n02 span{fill:#333;color:#333;}#mermaid-svg-FdwIvLUGzPWg2n02 .node rect,#mermaid-svg-FdwIvLUGzPWg2n02 .node circle,#mermaid-svg-FdwIvLUGzPWg2n02 .node ellipse,#mermaid-svg-FdwIvLUGzPWg2n02 .node polygon,#mermaid-svg-FdwIvLUGzPWg2n02 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-FdwIvLUGzPWg2n02 .rough-node .label text,#mermaid-svg-FdwIvLUGzPWg2n02 .node .label text,#mermaid-svg-FdwIvLUGzPWg2n02 .image-shape .label,#mermaid-svg-FdwIvLUGzPWg2n02 .icon-shape .label{text-anchor:middle;}#mermaid-svg-FdwIvLUGzPWg2n02 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-FdwIvLUGzPWg2n02 .rough-node .label,#mermaid-svg-FdwIvLUGzPWg2n02 .node .label,#mermaid-svg-FdwIvLUGzPWg2n02 .image-shape .label,#mermaid-svg-FdwIvLUGzPWg2n02 .icon-shape .label{text-align:center;}#mermaid-svg-FdwIvLUGzPWg2n02 .node.clickable{cursor:pointer;}#mermaid-svg-FdwIvLUGzPWg2n02 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-FdwIvLUGzPWg2n02 .arrowheadPath{fill:#333333;}#mermaid-svg-FdwIvLUGzPWg2n02 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-FdwIvLUGzPWg2n02 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-FdwIvLUGzPWg2n02 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-FdwIvLUGzPWg2n02 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-FdwIvLUGzPWg2n02 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-FdwIvLUGzPWg2n02 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-FdwIvLUGzPWg2n02 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-FdwIvLUGzPWg2n02 .cluster text{fill:#333;}#mermaid-svg-FdwIvLUGzPWg2n02 .cluster span{color:#333;}#mermaid-svg-FdwIvLUGzPWg2n02 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-FdwIvLUGzPWg2n02 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-FdwIvLUGzPWg2n02 rect.text{fill:none;stroke-width:0;}#mermaid-svg-FdwIvLUGzPWg2n02 .icon-shape,#mermaid-svg-FdwIvLUGzPWg2n02 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-FdwIvLUGzPWg2n02 .icon-shape p,#mermaid-svg-FdwIvLUGzPWg2n02 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-FdwIvLUGzPWg2n02 .icon-shape .label rect,#mermaid-svg-FdwIvLUGzPWg2n02 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-FdwIvLUGzPWg2n02 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-FdwIvLUGzPWg2n02 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-FdwIvLUGzPWg2n02 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 订单创建方法
校验参数
填充订单
计算金额
订单落库
责任链的做法是把每个步骤变成独立处理器,然后把处理器串起来。
#mermaid-svg-mScwa5wpQU5SaHRs{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-mScwa5wpQU5SaHRs .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-mScwa5wpQU5SaHRs .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-mScwa5wpQU5SaHRs .error-icon{fill:#552222;}#mermaid-svg-mScwa5wpQU5SaHRs .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-mScwa5wpQU5SaHRs .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-mScwa5wpQU5SaHRs .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-mScwa5wpQU5SaHRs .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-mScwa5wpQU5SaHRs .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-mScwa5wpQU5SaHRs .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-mScwa5wpQU5SaHRs .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-mScwa5wpQU5SaHRs .marker{fill:#333333;stroke:#333333;}#mermaid-svg-mScwa5wpQU5SaHRs .marker.cross{stroke:#333333;}#mermaid-svg-mScwa5wpQU5SaHRs svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-mScwa5wpQU5SaHRs p{margin:0;}#mermaid-svg-mScwa5wpQU5SaHRs .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-mScwa5wpQU5SaHRs .cluster-label text{fill:#333;}#mermaid-svg-mScwa5wpQU5SaHRs .cluster-label span{color:#333;}#mermaid-svg-mScwa5wpQU5SaHRs .cluster-label span p{background-color:transparent;}#mermaid-svg-mScwa5wpQU5SaHRs .label text,#mermaid-svg-mScwa5wpQU5SaHRs span{fill:#333;color:#333;}#mermaid-svg-mScwa5wpQU5SaHRs .node rect,#mermaid-svg-mScwa5wpQU5SaHRs .node circle,#mermaid-svg-mScwa5wpQU5SaHRs .node ellipse,#mermaid-svg-mScwa5wpQU5SaHRs .node polygon,#mermaid-svg-mScwa5wpQU5SaHRs .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-mScwa5wpQU5SaHRs .rough-node .label text,#mermaid-svg-mScwa5wpQU5SaHRs .node .label text,#mermaid-svg-mScwa5wpQU5SaHRs .image-shape .label,#mermaid-svg-mScwa5wpQU5SaHRs .icon-shape .label{text-anchor:middle;}#mermaid-svg-mScwa5wpQU5SaHRs .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-mScwa5wpQU5SaHRs .rough-node .label,#mermaid-svg-mScwa5wpQU5SaHRs .node .label,#mermaid-svg-mScwa5wpQU5SaHRs .image-shape .label,#mermaid-svg-mScwa5wpQU5SaHRs .icon-shape .label{text-align:center;}#mermaid-svg-mScwa5wpQU5SaHRs .node.clickable{cursor:pointer;}#mermaid-svg-mScwa5wpQU5SaHRs .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-mScwa5wpQU5SaHRs .arrowheadPath{fill:#333333;}#mermaid-svg-mScwa5wpQU5SaHRs .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-mScwa5wpQU5SaHRs .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-mScwa5wpQU5SaHRs .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-mScwa5wpQU5SaHRs .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-mScwa5wpQU5SaHRs .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-mScwa5wpQU5SaHRs .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-mScwa5wpQU5SaHRs .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-mScwa5wpQU5SaHRs .cluster text{fill:#333;}#mermaid-svg-mScwa5wpQU5SaHRs .cluster span{color:#333;}#mermaid-svg-mScwa5wpQU5SaHRs div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-mScwa5wpQU5SaHRs .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-mScwa5wpQU5SaHRs rect.text{fill:none;stroke-width:0;}#mermaid-svg-mScwa5wpQU5SaHRs .icon-shape,#mermaid-svg-mScwa5wpQU5SaHRs .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-mScwa5wpQU5SaHRs .icon-shape p,#mermaid-svg-mScwa5wpQU5SaHRs .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-mScwa5wpQU5SaHRs .icon-shape .label rect,#mermaid-svg-mScwa5wpQU5SaHRs .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-mScwa5wpQU5SaHRs .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-mScwa5wpQU5SaHRs .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-mScwa5wpQU5SaHRs :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 订单请求
参数校验处理器
订单填充处理器
金额计算处理器
订单落库处理器
处理完成
每个处理器只关心自己要做什么,以及要不要把请求交给下一个处理器。
责任链的三个角色
| 角色 | 作用 |
|---|---|
| 抽象处理者 | 定义处理方法,并保存下一个处理器引用 |
| 具体处理者 | 实现自己的处理逻辑 |
| 客户端 | 组装链路,并把请求交给链头 |
抽象处理器可以这样写:
java
public abstract class Handler {
protected Handler next;
public void setNext(Handler next) {
this.next = next;
}
public abstract void process(OrderInfo order);
}
具体处理器做完自己的事后,把请求交给下一个节点:
java
public class OrderValidation extends Handler {
@Override
public void process(OrderInfo order) {
// 校验订单参数
if (next != null) {
next.process(order);
}
}
}
组装链路:
java
Handler validation = new OrderValidation();
Handler fill = new OrderFill();
Handler amount = new OrderAmountCalculate();
Handler create = new OrderCreate();
validation.setNext(fill);
fill.setNext(amount);
amount.setNext(create);
validation.process(new OrderInfo());
"订单落库" "金额计算" "订单填充" "参数校验" "客户端" "订单落库" "金额计算" "订单填充" "参数校验" "客户端" #mermaid-svg-mc6AdPvOvCcTGX8W{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-mc6AdPvOvCcTGX8W .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-mc6AdPvOvCcTGX8W .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-mc6AdPvOvCcTGX8W .error-icon{fill:#552222;}#mermaid-svg-mc6AdPvOvCcTGX8W .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-mc6AdPvOvCcTGX8W .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-mc6AdPvOvCcTGX8W .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-mc6AdPvOvCcTGX8W .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-mc6AdPvOvCcTGX8W .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-mc6AdPvOvCcTGX8W .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-mc6AdPvOvCcTGX8W .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-mc6AdPvOvCcTGX8W .marker{fill:#333333;stroke:#333333;}#mermaid-svg-mc6AdPvOvCcTGX8W .marker.cross{stroke:#333333;}#mermaid-svg-mc6AdPvOvCcTGX8W svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-mc6AdPvOvCcTGX8W p{margin:0;}#mermaid-svg-mc6AdPvOvCcTGX8W .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-mc6AdPvOvCcTGX8W text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-mc6AdPvOvCcTGX8W .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-mc6AdPvOvCcTGX8W .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-mc6AdPvOvCcTGX8W .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-mc6AdPvOvCcTGX8W .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-mc6AdPvOvCcTGX8W #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-mc6AdPvOvCcTGX8W .sequenceNumber{fill:white;}#mermaid-svg-mc6AdPvOvCcTGX8W #sequencenumber{fill:#333;}#mermaid-svg-mc6AdPvOvCcTGX8W #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-mc6AdPvOvCcTGX8W .messageText{fill:#333;stroke:none;}#mermaid-svg-mc6AdPvOvCcTGX8W .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-mc6AdPvOvCcTGX8W .labelText,#mermaid-svg-mc6AdPvOvCcTGX8W .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-mc6AdPvOvCcTGX8W .loopText,#mermaid-svg-mc6AdPvOvCcTGX8W .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-mc6AdPvOvCcTGX8W .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-mc6AdPvOvCcTGX8W .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-mc6AdPvOvCcTGX8W .noteText,#mermaid-svg-mc6AdPvOvCcTGX8W .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-mc6AdPvOvCcTGX8W .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-mc6AdPvOvCcTGX8W .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-mc6AdPvOvCcTGX8W .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-mc6AdPvOvCcTGX8W .actorPopupMenu{position:absolute;}#mermaid-svg-mc6AdPvOvCcTGX8W .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-mc6AdPvOvCcTGX8W .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-mc6AdPvOvCcTGX8W .actor-man circle,#mermaid-svg-mc6AdPvOvCcTGX8W line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-mc6AdPvOvCcTGX8W :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} "提交订单""校验通过,继续""填充完成,继续""算价完成,继续""订单创建完成"
责任链和普通流程编排有什么区别
普通流程编排通常由一个方法集中调用所有步骤:
java
validate();
fill();
calculate();
save();
责任链则把"下一个步骤是谁"交给处理器或链路配置管理。
| 对比项 | 普通流程 | 责任链 |
|---|---|---|
| 步骤关系 | 主流程硬编码 | 节点串联 |
| 扩展方式 | 修改主流程 | 新增处理器并调整链路 |
| 节点职责 | 可能混在主流程 | 每个节点职责独立 |
| 适合场景 | 流程固定且简单 | 步骤较多、可插拔、可扩展 |
责任链不是为了让所有流程都变复杂。它适合步骤多、扩展频繁、每个步骤能独立表达的场景。
Servlet Filter 也是典型责任链
Web 请求进入服务时,经常要经过多个过滤器:
- 跨域处理
- 日志记录
- 登录校验
- 权限校验
- 限流处理
- Controller 方法
#mermaid-svg-xwhMU06CmJoIDpF5{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-xwhMU06CmJoIDpF5 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-xwhMU06CmJoIDpF5 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-xwhMU06CmJoIDpF5 .error-icon{fill:#552222;}#mermaid-svg-xwhMU06CmJoIDpF5 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-xwhMU06CmJoIDpF5 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-xwhMU06CmJoIDpF5 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-xwhMU06CmJoIDpF5 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-xwhMU06CmJoIDpF5 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-xwhMU06CmJoIDpF5 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-xwhMU06CmJoIDpF5 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-xwhMU06CmJoIDpF5 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-xwhMU06CmJoIDpF5 .marker.cross{stroke:#333333;}#mermaid-svg-xwhMU06CmJoIDpF5 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-xwhMU06CmJoIDpF5 p{margin:0;}#mermaid-svg-xwhMU06CmJoIDpF5 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-xwhMU06CmJoIDpF5 .cluster-label text{fill:#333;}#mermaid-svg-xwhMU06CmJoIDpF5 .cluster-label span{color:#333;}#mermaid-svg-xwhMU06CmJoIDpF5 .cluster-label span p{background-color:transparent;}#mermaid-svg-xwhMU06CmJoIDpF5 .label text,#mermaid-svg-xwhMU06CmJoIDpF5 span{fill:#333;color:#333;}#mermaid-svg-xwhMU06CmJoIDpF5 .node rect,#mermaid-svg-xwhMU06CmJoIDpF5 .node circle,#mermaid-svg-xwhMU06CmJoIDpF5 .node ellipse,#mermaid-svg-xwhMU06CmJoIDpF5 .node polygon,#mermaid-svg-xwhMU06CmJoIDpF5 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-xwhMU06CmJoIDpF5 .rough-node .label text,#mermaid-svg-xwhMU06CmJoIDpF5 .node .label text,#mermaid-svg-xwhMU06CmJoIDpF5 .image-shape .label,#mermaid-svg-xwhMU06CmJoIDpF5 .icon-shape .label{text-anchor:middle;}#mermaid-svg-xwhMU06CmJoIDpF5 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-xwhMU06CmJoIDpF5 .rough-node .label,#mermaid-svg-xwhMU06CmJoIDpF5 .node .label,#mermaid-svg-xwhMU06CmJoIDpF5 .image-shape .label,#mermaid-svg-xwhMU06CmJoIDpF5 .icon-shape .label{text-align:center;}#mermaid-svg-xwhMU06CmJoIDpF5 .node.clickable{cursor:pointer;}#mermaid-svg-xwhMU06CmJoIDpF5 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-xwhMU06CmJoIDpF5 .arrowheadPath{fill:#333333;}#mermaid-svg-xwhMU06CmJoIDpF5 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-xwhMU06CmJoIDpF5 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-xwhMU06CmJoIDpF5 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-xwhMU06CmJoIDpF5 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-xwhMU06CmJoIDpF5 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-xwhMU06CmJoIDpF5 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-xwhMU06CmJoIDpF5 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-xwhMU06CmJoIDpF5 .cluster text{fill:#333;}#mermaid-svg-xwhMU06CmJoIDpF5 .cluster span{color:#333;}#mermaid-svg-xwhMU06CmJoIDpF5 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-xwhMU06CmJoIDpF5 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-xwhMU06CmJoIDpF5 rect.text{fill:none;stroke-width:0;}#mermaid-svg-xwhMU06CmJoIDpF5 .icon-shape,#mermaid-svg-xwhMU06CmJoIDpF5 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-xwhMU06CmJoIDpF5 .icon-shape p,#mermaid-svg-xwhMU06CmJoIDpF5 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-xwhMU06CmJoIDpF5 .icon-shape .label rect,#mermaid-svg-xwhMU06CmJoIDpF5 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-xwhMU06CmJoIDpF5 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-xwhMU06CmJoIDpF5 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-xwhMU06CmJoIDpF5 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} HTTP 请求
CorsFilter
LogFilter
AuthFilter
RateLimitFilter
Controller
过滤器通过 doFilter 决定是否继续向后传递。
java
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
// 前置处理
chain.doFilter(request, response);
// 后置处理
}
如果某个过滤器发现请求不合法,可以直接返回,不再调用后续链路。
#mermaid-svg-oQPgpii2IM20aHNQ{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-oQPgpii2IM20aHNQ .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-oQPgpii2IM20aHNQ .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-oQPgpii2IM20aHNQ .error-icon{fill:#552222;}#mermaid-svg-oQPgpii2IM20aHNQ .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-oQPgpii2IM20aHNQ .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-oQPgpii2IM20aHNQ .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-oQPgpii2IM20aHNQ .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-oQPgpii2IM20aHNQ .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-oQPgpii2IM20aHNQ .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-oQPgpii2IM20aHNQ .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-oQPgpii2IM20aHNQ .marker{fill:#333333;stroke:#333333;}#mermaid-svg-oQPgpii2IM20aHNQ .marker.cross{stroke:#333333;}#mermaid-svg-oQPgpii2IM20aHNQ svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-oQPgpii2IM20aHNQ p{margin:0;}#mermaid-svg-oQPgpii2IM20aHNQ .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-oQPgpii2IM20aHNQ .cluster-label text{fill:#333;}#mermaid-svg-oQPgpii2IM20aHNQ .cluster-label span{color:#333;}#mermaid-svg-oQPgpii2IM20aHNQ .cluster-label span p{background-color:transparent;}#mermaid-svg-oQPgpii2IM20aHNQ .label text,#mermaid-svg-oQPgpii2IM20aHNQ span{fill:#333;color:#333;}#mermaid-svg-oQPgpii2IM20aHNQ .node rect,#mermaid-svg-oQPgpii2IM20aHNQ .node circle,#mermaid-svg-oQPgpii2IM20aHNQ .node ellipse,#mermaid-svg-oQPgpii2IM20aHNQ .node polygon,#mermaid-svg-oQPgpii2IM20aHNQ .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-oQPgpii2IM20aHNQ .rough-node .label text,#mermaid-svg-oQPgpii2IM20aHNQ .node .label text,#mermaid-svg-oQPgpii2IM20aHNQ .image-shape .label,#mermaid-svg-oQPgpii2IM20aHNQ .icon-shape .label{text-anchor:middle;}#mermaid-svg-oQPgpii2IM20aHNQ .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-oQPgpii2IM20aHNQ .rough-node .label,#mermaid-svg-oQPgpii2IM20aHNQ .node .label,#mermaid-svg-oQPgpii2IM20aHNQ .image-shape .label,#mermaid-svg-oQPgpii2IM20aHNQ .icon-shape .label{text-align:center;}#mermaid-svg-oQPgpii2IM20aHNQ .node.clickable{cursor:pointer;}#mermaid-svg-oQPgpii2IM20aHNQ .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-oQPgpii2IM20aHNQ .arrowheadPath{fill:#333333;}#mermaid-svg-oQPgpii2IM20aHNQ .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-oQPgpii2IM20aHNQ .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-oQPgpii2IM20aHNQ .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-oQPgpii2IM20aHNQ .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-oQPgpii2IM20aHNQ .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-oQPgpii2IM20aHNQ .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-oQPgpii2IM20aHNQ .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-oQPgpii2IM20aHNQ .cluster text{fill:#333;}#mermaid-svg-oQPgpii2IM20aHNQ .cluster span{color:#333;}#mermaid-svg-oQPgpii2IM20aHNQ div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-oQPgpii2IM20aHNQ .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-oQPgpii2IM20aHNQ rect.text{fill:none;stroke-width:0;}#mermaid-svg-oQPgpii2IM20aHNQ .icon-shape,#mermaid-svg-oQPgpii2IM20aHNQ .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-oQPgpii2IM20aHNQ .icon-shape p,#mermaid-svg-oQPgpii2IM20aHNQ .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-oQPgpii2IM20aHNQ .icon-shape .label rect,#mermaid-svg-oQPgpii2IM20aHNQ .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-oQPgpii2IM20aHNQ .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-oQPgpii2IM20aHNQ .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-oQPgpii2IM20aHNQ :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 通过
不通过
请求进入过滤器
校验是否通过
调用下一个过滤器
直接返回错误响应
这就是责任链的典型特征:请求沿链传递,但每个节点都有机会处理、拦截或继续传递。
责任链适合哪些业务
| 场景 | 链路节点 |
|---|---|
| 订单创建 | 参数校验、补充数据、算价、落库、返佣 |
| 内容审核 | 文本审核、图片审核、视频审核、人工复核 |
| 审批流 | 组长、主管、总监、负责人 |
| Web 过滤器 | 日志、鉴权、限流、跨域 |
| 风控校验 | 黑名单、频控、设备风险、地理位置风险 |
#mermaid-svg-qyaEw16Oxm2d8RY2{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-qyaEw16Oxm2d8RY2 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-qyaEw16Oxm2d8RY2 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-qyaEw16Oxm2d8RY2 .error-icon{fill:#552222;}#mermaid-svg-qyaEw16Oxm2d8RY2 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-qyaEw16Oxm2d8RY2 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-qyaEw16Oxm2d8RY2 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-qyaEw16Oxm2d8RY2 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-qyaEw16Oxm2d8RY2 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-qyaEw16Oxm2d8RY2 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-qyaEw16Oxm2d8RY2 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-qyaEw16Oxm2d8RY2 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-qyaEw16Oxm2d8RY2 .marker.cross{stroke:#333333;}#mermaid-svg-qyaEw16Oxm2d8RY2 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-qyaEw16Oxm2d8RY2 p{margin:0;}#mermaid-svg-qyaEw16Oxm2d8RY2 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-qyaEw16Oxm2d8RY2 .cluster-label text{fill:#333;}#mermaid-svg-qyaEw16Oxm2d8RY2 .cluster-label span{color:#333;}#mermaid-svg-qyaEw16Oxm2d8RY2 .cluster-label span p{background-color:transparent;}#mermaid-svg-qyaEw16Oxm2d8RY2 .label text,#mermaid-svg-qyaEw16Oxm2d8RY2 span{fill:#333;color:#333;}#mermaid-svg-qyaEw16Oxm2d8RY2 .node rect,#mermaid-svg-qyaEw16Oxm2d8RY2 .node circle,#mermaid-svg-qyaEw16Oxm2d8RY2 .node ellipse,#mermaid-svg-qyaEw16Oxm2d8RY2 .node polygon,#mermaid-svg-qyaEw16Oxm2d8RY2 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-qyaEw16Oxm2d8RY2 .rough-node .label text,#mermaid-svg-qyaEw16Oxm2d8RY2 .node .label text,#mermaid-svg-qyaEw16Oxm2d8RY2 .image-shape .label,#mermaid-svg-qyaEw16Oxm2d8RY2 .icon-shape .label{text-anchor:middle;}#mermaid-svg-qyaEw16Oxm2d8RY2 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-qyaEw16Oxm2d8RY2 .rough-node .label,#mermaid-svg-qyaEw16Oxm2d8RY2 .node .label,#mermaid-svg-qyaEw16Oxm2d8RY2 .image-shape .label,#mermaid-svg-qyaEw16Oxm2d8RY2 .icon-shape .label{text-align:center;}#mermaid-svg-qyaEw16Oxm2d8RY2 .node.clickable{cursor:pointer;}#mermaid-svg-qyaEw16Oxm2d8RY2 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-qyaEw16Oxm2d8RY2 .arrowheadPath{fill:#333333;}#mermaid-svg-qyaEw16Oxm2d8RY2 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-qyaEw16Oxm2d8RY2 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-qyaEw16Oxm2d8RY2 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-qyaEw16Oxm2d8RY2 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-qyaEw16Oxm2d8RY2 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-qyaEw16Oxm2d8RY2 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-qyaEw16Oxm2d8RY2 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-qyaEw16Oxm2d8RY2 .cluster text{fill:#333;}#mermaid-svg-qyaEw16Oxm2d8RY2 .cluster span{color:#333;}#mermaid-svg-qyaEw16Oxm2d8RY2 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-qyaEw16Oxm2d8RY2 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-qyaEw16Oxm2d8RY2 rect.text{fill:none;stroke-width:0;}#mermaid-svg-qyaEw16Oxm2d8RY2 .icon-shape,#mermaid-svg-qyaEw16Oxm2d8RY2 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-qyaEw16Oxm2d8RY2 .icon-shape p,#mermaid-svg-qyaEw16Oxm2d8RY2 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-qyaEw16Oxm2d8RY2 .icon-shape .label rect,#mermaid-svg-qyaEw16Oxm2d8RY2 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-qyaEw16Oxm2d8RY2 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-qyaEw16Oxm2d8RY2 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-qyaEw16Oxm2d8RY2 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是
否
业务请求
处理器 1
处理器 2
处理器 3
是否需要继续
处理器 4
提前结束
常见坑
坑一:链路太长
链路太长会导致一次请求经过很多对象,性能和可读性都会下降。责任链不是越长越好。
坑二:链路顺序不清晰
责任链对顺序敏感。先算价再填充订单,结果可能就是错的。链路顺序最好配置化或集中组装,别散落在各处。
坑三:节点没有明确职责
如果一个处理器里既校验参数,又查库存,又写日志,它就不是一个清晰节点。责任链要求节点职责边界清楚。
坑四:出现循环调用
如果链路配置错误,可能出现 A 调 B,B 又调回 A。生产代码里可以在链路构建阶段做校验,避免循环。
#mermaid-svg-HB0Lb1Nq6GE2KCfN{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-HB0Lb1Nq6GE2KCfN .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-HB0Lb1Nq6GE2KCfN .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-HB0Lb1Nq6GE2KCfN .error-icon{fill:#552222;}#mermaid-svg-HB0Lb1Nq6GE2KCfN .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-HB0Lb1Nq6GE2KCfN .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-HB0Lb1Nq6GE2KCfN .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-HB0Lb1Nq6GE2KCfN .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-HB0Lb1Nq6GE2KCfN .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-HB0Lb1Nq6GE2KCfN .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-HB0Lb1Nq6GE2KCfN .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-HB0Lb1Nq6GE2KCfN .marker{fill:#333333;stroke:#333333;}#mermaid-svg-HB0Lb1Nq6GE2KCfN .marker.cross{stroke:#333333;}#mermaid-svg-HB0Lb1Nq6GE2KCfN svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-HB0Lb1Nq6GE2KCfN p{margin:0;}#mermaid-svg-HB0Lb1Nq6GE2KCfN .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-HB0Lb1Nq6GE2KCfN .cluster-label text{fill:#333;}#mermaid-svg-HB0Lb1Nq6GE2KCfN .cluster-label span{color:#333;}#mermaid-svg-HB0Lb1Nq6GE2KCfN .cluster-label span p{background-color:transparent;}#mermaid-svg-HB0Lb1Nq6GE2KCfN .label text,#mermaid-svg-HB0Lb1Nq6GE2KCfN span{fill:#333;color:#333;}#mermaid-svg-HB0Lb1Nq6GE2KCfN .node rect,#mermaid-svg-HB0Lb1Nq6GE2KCfN .node circle,#mermaid-svg-HB0Lb1Nq6GE2KCfN .node ellipse,#mermaid-svg-HB0Lb1Nq6GE2KCfN .node polygon,#mermaid-svg-HB0Lb1Nq6GE2KCfN .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-HB0Lb1Nq6GE2KCfN .rough-node .label text,#mermaid-svg-HB0Lb1Nq6GE2KCfN .node .label text,#mermaid-svg-HB0Lb1Nq6GE2KCfN .image-shape .label,#mermaid-svg-HB0Lb1Nq6GE2KCfN .icon-shape .label{text-anchor:middle;}#mermaid-svg-HB0Lb1Nq6GE2KCfN .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-HB0Lb1Nq6GE2KCfN .rough-node .label,#mermaid-svg-HB0Lb1Nq6GE2KCfN .node .label,#mermaid-svg-HB0Lb1Nq6GE2KCfN .image-shape .label,#mermaid-svg-HB0Lb1Nq6GE2KCfN .icon-shape .label{text-align:center;}#mermaid-svg-HB0Lb1Nq6GE2KCfN .node.clickable{cursor:pointer;}#mermaid-svg-HB0Lb1Nq6GE2KCfN .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-HB0Lb1Nq6GE2KCfN .arrowheadPath{fill:#333333;}#mermaid-svg-HB0Lb1Nq6GE2KCfN .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-HB0Lb1Nq6GE2KCfN .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-HB0Lb1Nq6GE2KCfN .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-HB0Lb1Nq6GE2KCfN .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-HB0Lb1Nq6GE2KCfN .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-HB0Lb1Nq6GE2KCfN .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-HB0Lb1Nq6GE2KCfN .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-HB0Lb1Nq6GE2KCfN .cluster text{fill:#333;}#mermaid-svg-HB0Lb1Nq6GE2KCfN .cluster span{color:#333;}#mermaid-svg-HB0Lb1Nq6GE2KCfN div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-HB0Lb1Nq6GE2KCfN .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-HB0Lb1Nq6GE2KCfN rect.text{fill:none;stroke-width:0;}#mermaid-svg-HB0Lb1Nq6GE2KCfN .icon-shape,#mermaid-svg-HB0Lb1Nq6GE2KCfN .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-HB0Lb1Nq6GE2KCfN .icon-shape p,#mermaid-svg-HB0Lb1Nq6GE2KCfN .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-HB0Lb1Nq6GE2KCfN .icon-shape .label rect,#mermaid-svg-HB0Lb1Nq6GE2KCfN .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-HB0Lb1Nq6GE2KCfN .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-HB0Lb1Nq6GE2KCfN .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-HB0Lb1Nq6GE2KCfN :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 责任链设计
职责单一
顺序明确
可插拔扩展
避免循环
控制链路长度
面试怎么说
可以这样回答:
我在订单创建和请求过滤这类场景里用过责任链模式。责任链会把多个处理步骤拆成独立处理器,每个处理器只负责自己的逻辑,并持有下一个处理器引用。请求从链头开始传递,节点处理完后决定继续向后传,还是直接结束。它的好处是降低请求发送者和多个处理节点之间的耦合,新增步骤时可以新增处理器并调整链路顺序。但要注意链路不能太长,顺序要明确,也要避免配置错误导致循环调用。
小结
责任链模式最适合回答"多个处理步骤怎么优雅组织"。
可以这样记:
策略模式解决多选一,责任链模式解决按顺序过多关。
当一个请求天然要经过多个关卡,而且这些关卡还可能增减调整时,责任链就很适合。