职责链(Chain of Responsibility)模式
# 职责链(Chain of Responsibility)模式
为了避免请求发送者与多个请求处理者耦合在一起,于是将所有请求的处理者通过前一对象记住其下一个对象的引用而连成一条链;当有请求发生时,可将请求沿着这条链传递,直到有对象处理它为止。属于对象行为型模式
- 抽象处理者(Handler)角色:定义一个处理请求的接口,包含抽象处理方法和一个后继连接。
- 具体处理者(Concrete Handler)角色:实现抽象处理者的处理方法,判断能否处理本次请求,如果可以处理请求则处理,否则将该请求转给它的后继者。
- 客户类(Client)角色:创建处理链,并向链头的具体处理者对象提交请求,它不关心处理细节和请求的传递过程。

public class Teacher {
private String name;
public Teacher(String name) {
this.name = name;
}
private Teacher next; // 下一个处理的老师;1、链条的引用点
public Teacher getNext() {
return next;
}
public void setNext(Teacher next) {
this.next = next;
}
void handleRequest() {
System.out.println(this + "正在处理....");
///2、下一个继续
if (next != null) {
next.handleRequest();
}
}
@Override
public String toString() {
return "Teacher{" +
"name='" + name + '\'' +
", next=" + next +
'}';
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
测试
public class MainTest {
public static void main(String[] args) {
Teacher teacher = new Teacher("王武");
Teacher teacher1 = new Teacher("张三");
Teacher teacher2 = new Teacher("李四");
//3、构建链条
teacher.setNext(teacher1);
teacher1.setNext(teacher2);
teacher.handleRequest();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
# 实现一个简单的 filter 链
对象类,只是传递中的一部分
@Data
public class Request {
String msg;
public Request(String msg) {
this.msg = msg;
}
}
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
@Data
public class Response {
String content;
public Response(String content) {
this.content = content;
}
}
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
抽象处理者(Handler)角色:定义一个处理请求的接口,包含抽象处理方法和一个后继连接。
public interface Filter {
void doFilter(Request request,Response response,FilterChain chain);
}
1
2
3
2
3
具体处理者(Concrete Handler)角色:实现抽象处理者的处理方法,判断能否处理本次请求,如果可以处理请求则处理,否则将该请求转给它的后继者。
public class CharacterFilter implements Filter {
@Override
public void doFilter(Request request, Response response, FilterChain chain) {
// 功能
request.msg += "===";
System.out.println("CharacterFilter...doFilter之前");
chain.doFilter(request, response, chain);
System.out.println("CharacterFilter...doFilter之后");
}
}
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
public class EncodingFilter implements Filter {
@Override
public void doFilter(Request request, Response response, FilterChain chain) {
request.msg += "1111";
System.out.println("EncodingFilter...doFilter之前");
chain.doFilter(request, response, chain);
System.out.println("EncodingFilter...doFilter之后");
}
}
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
public class HttpFilter implements Filter {
@Override
public void doFilter(Request request, Response response, FilterChain chain) {
// 第一个filter的功能
request.msg += ">>>";
//往下放行
System.out.println("HttpFilter...doFilter之前");
chain.doFilter(request, response, chain);
System.out.println("HttpFilter...doFilter之后");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
客户类(Client)角色:创建处理链,并向链头的具体处理者对象提交请求,它不关心处理细节和请求的传递过程。
public class My {
void hello() {
System.out.println("调用my.hello()");
}
}
1
2
3
4
5
2
3
4
5
public class FilterChain implements Filter {
// filter的链条
List<Filter> filters = new ArrayList<>();
private int cursor = 0;
// 最终要执行的目标方法
@Getter
My target;
public void setTarget(My target) {
this.target = target;
}
void addFilter(Filter filter) {
filters.add(filter);
}
@Override
public void doFilter(Request request, Response response, FilterChain chain) {
//执行filter 一直往下
if (cursor < filters.size()) {
Filter filter = filters.get(cursor);
cursor++;
filter.doFilter(request, response, chain);
} else {
// filter完了 执行目标方法
target.hello();
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
测试
public class MainTest {
public static void main(String[] args) {
FilterChain chain = new FilterChain();
HttpFilter httpFilter = new HttpFilter();
chain.addFilter(httpFilter);
CharacterFilter characterFilter = new CharacterFilter();
chain.addFilter(characterFilter);
EncodingFilter encodingFilter = new EncodingFilter();
chain.addFilter(encodingFilter);
chain.setTarget(new My());
//filter如何链式执行
chain.doFilter(new Request("hello world"), new Response("test"), chain);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 应用场景
什么场景用到?
- Tomcat 的 Pipeline、Valve
- Filter 链
- Aop 责任链
SpringMVC-HandlerExecutionChain 类就使用到职责链模式

- springmvc 请求的流程图中,执行了 拦截器相关方法 interceptor.preHandler 等等
- 在处理 SpringMvc 请求时,使用到职责链模式还使用到适配器模式
- HandlerExecutionChain 主要负责的是请求拦截器的执行和请求处理,但是他本身不处理请求,只是将请求分配给链上注册处理器执行,这是职责链实现方式,减少职责链本身与处理逻辑之间的耦合,规范了处理流程
- HandlerExecutionChain 维护了 HandlerInterceptor 的集合, 可以向其中注册相应的拦截器.
# 注意事项和细节
- 将请求和处理分开,实现解耦,提高系统的灵活性
- 简化了对象,使对象不需要知道链的结构
- 性能会受到影响,特别是在 链比较长的时候,因此需控制链中最大节点数量,一般通过在 Handler 中设置一个最大节点数量,在 setNext () 方法中判断是否已经超过阀值,超过则不允许该链建立,避免出现超长链无意识地破坏系统性能
- 调试不方便。采用了类似递归的方式,调试时逻辑可能比较复杂
- 最佳应用场景:有多个对象可以处理同一个请求时,比如:多级请求、请假 / 加薪等审批流程、Java Web 中 Tomcat 对 Encoding 的处理、拦截器
编辑 (opens new window)
上次更新: 2023/12/13, 06:06:02