责任链模式

本文最后更新于 2025年7月28日 下午

责任链模式将处理请求的对象连城一条链,沿着这条链传递该请求,直到有一个对象处理请求为止,这使得多个对象有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。

角色

  1. 抽象处理者 : 定义一个请求处理的接口
  2. 具体处理者 :实现处理请求的接口,可以选择自己处理或者传递给下一个接收者。包含对下一个接收处理者的引用。

优点

  1. 解耦请求发送者与接收者 ,便于扩展与复用
  2. 链结构灵活 ,可以动态添加、移除处理节点
  3. 增强封装性 ,每个处理器专注于自身逻辑

缺点

  1. 请求可能得不到处理 (若链尾未处理)
  2. 调试困难 ,请求流转链路不清晰时可能增加定位成本
  3. 性能问题 ,链过长或处理器逻辑复杂时可能影响效率

场景

数据流转处理,如敏感词过滤、输入校验、日志处理等

权限校验链、责任审批流程等需要动态组合处理链的场景

实现责任链模式

基础实现 :

  1. 定义拦截器接口 (filter)
  2. 定义拦截器实现类 (xxxfilter)
  3. 创建拦截器容器,装载所有拦截器对象。
  4. 遍历容器中的对象,执行拦截方法。
  5. 每个拦截方法都对请求体进行处理,处理后将修改写入请求
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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
public interface Filter{
void doFilter(Request request);
}

//
public class HtmlFilter implements Filter{
@Override
public void doFilter(Request request){
String msg = request.getMsg();
msg = msg.replaceAll("<","[");
msg = msg.replaceAll(">","]");
request.setMsg(msg);
}
}

//
public class SensitiveFilter implements Filter{
@Override
public void doFilter(Request request){
String msg = request.getMsg();
msg = msg.replaceAll("hit","*");
request.setMsg(msg);
}
}

public class MsgProcessor{
List<Filter> filters = new ArrayList<>();

public void addFilter(Filter filter){
filters.add(filter);
}

public void process(Request request){
for(Filter filter:filters){
filter.doFilter(request);
}
}
}

// 调用
public class Test{
public static void main(String[] args){
Request request = new Request("");
MsgProcessor msgProcessor = new MsgProcessor();

msgProcessor.addFilter(new HtmlFilter());
msgProcessor.addFilter(new SensitiveFilter());
msgProcessor.addFilter(new FaceFilter());
msgProcessor.process(request);
String newMsg = request.getMsg();
System.out.println(newMsg);
}
}

增强

当一个业务流程中存在多个拦截器时,可以通过定义一个chain对象来对一组拦截器进行统一管理。

这时需要进行的定义 :

  1. 定义一个FilterChain对象 ,其中包含一个容器对象用于存储拦截器对象,一个添加方法
  2. 为保持一致性,实现filter接口,允许将FilterChain对象添加到容器中
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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
// 用于管理filter 
public class FilterChain{
List<Filter>filters = new ArrayList<>();
public void addFilter(Filter filter){
filters.add(filter);
}
@Override
public void doFilter(Request request){
for(Filter filter:filters){
filter.doFilter(request);
}
}
}
//将FilterChain交给MsgProcessor处理
public class MsgProcessor{
private FilterChain filterChain;
public void setFilterChain(FilterChain filterChain){
this.filterChain = filterChain ;
}
public void process(Request request){
filterChain.doFilter(request);
}
}

//
public class Client{
public static void main(String[] args){
Request request = new Request("msg");
MsgProcessor msgProcessor = new MsgProcessor();

FilterChain filterChain = new FilterChain();
filterChain.addFilter(new HtmlFilter());
filterChain.addFilter(new SensitiveFilter());

FilterChain filterChain2 = new FilterChain();
filterChain2.addFilter(new FaceFilter());

filterChain.addFilter(filterChain2);
msgProcessor.setFilterChain(filterChain);
msgProcessor.process(request);
String newMsg = request.getMsg();
System.out.println(newMsg);

}
}

public class FilterChain implements Filter{
List<Filter>filters = new ArrayList<>();

@Override
public void doFilter(Request request){
for(Filter filter:filters){
filter.doFilter(request);
}
}
}

因为 filterchain 已经具备了 filter的管理和调用能力,所以去除MsgProcessor,改为由filterchain 管理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Client2 {
public static void main(String[] args){
Request request = new Request("msg");
FilterChain filterChain = new FilterChain();
filterChain.addFilter(new HtmlFilter());
filterChain.addFilter(new SensitiveFilter());

FilterChain filterChain2 = new FilterChain();
filterChain.addFilter(new FaceFilter());

filterChain.doFilter(request);
String newMsg = request.getMsg();
System.out.println(newMsg);
}
}

双向拦截

在上述功能实现后,可以通过添加一个Response来对最终相应的数据进行处理。

  1. 定义Response 类
  2. 将response 参数添加到Filter的doFilter中
  3. 向相关的方法中添加response对象
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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
public class Response {
private String msg ;
public Response(String msg){
this.msg = msg ;
}

public String getMsg(){
return msg ;
}

public void setMsg(String msg){
this.msg = msg ;
}
}

//添加Response到addFilter中
public interface Filter{
void doFilter(Request request , Response response);
}

public class SensitiveFilter implements Filter{
@Override
public void doFilter(Request request , Response response){
String msg = request.getMsg();
msg = msg.replaceAll("hit","*");
request.setMsg(msg);

response.setMsg(response.getMsg()+"-SensitiveFilter");
}
}

// 修改对应的FilterChain中的addFilter 实现
@Override
public void doFilter(Request request , Response response){
for(Filter filter : filters ){
filter.doFilter(request,response);
}
}
// 调用
public class Client2{
public static void main(String[] args){
Request request = new Request("msg");
Response response = new Response("I love you");

FilterChain filterChain = new FilterChain();
filterChain.addFilter(new HtmlFilter());
filterChain.addFilter(new SensitiveFilter());

FilterChain filterChain2 = new FilterChain();
filterChain2.addFilter(new SensitiveFilter());
filterChain2.addFilter(filterChain2);

filterChain.doFilter(request,response);
String newMsg = request.getMsg();
System.out.println(newMsg);
System.out.println(response.getMsg());
}
}

在添加后在doFilter中 具备两个对象可以被拦截器操作。

通过遍历执行所有拦截器的doFilter方法,其调用链如下:

1
2
3
4
5
6
7
8
// 前述的调用逻辑 
Client
- FilterChain.doFilter()
- FilterChain.doFilter.doFilter();
- FilterChain.doFilter.doFilter.HtmlFilter();
- FilterChain.doFilter.doFilter.SensitiveFilter();
- ...
-

当我们需要在 正向处理 请求的解码过程,逆向处理响应的编码过程时,需要通过嵌套调用doFilter方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 双向拦截的请求
Client
- FilterChain.doFiler()
- FilterChain.doFilter.resolve_request1()
-FilterChain.doFilter()
- FilterChain.doFilter.resolve_request2()
- FilterChain.doFilter()
- FilterChain.doFilter.resolve_request3()
- FilterChain.doFilter.resolve_response3()
-
- FilterChain.doFilter.resolve_response2()
-
- FilterChain.doFilter.resolve_response1()
-

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
// 向拦截器的doFilter方法中传入chain对象
public void doFilter(Request request , Response response , FilterChain filterChain){
String msg = request.getMsg();
msg = msg.replaceAll("<","[");
msg = msg.replaceAll(">","]");
request.setMsg(msg);

filterChain.doFilter(request,response,filterChain);

//过滤.. response
response.setMsg(reponse.getMsg()+"-HtmlFilter");
}

// 定义FilterChain 中的doFilter方法,传入chain对象,通过chain对象的处理改为使用index进行遍历
public class FilterChain implements Filter{
List<Filter>filters = new ArrayList<>();
private int index = 0 ;

public void addFilter(Filter filter){
filters.add(filter);
}

@Override
public void doFilter(Request request , Response response , FilterChain filterChain){
if(index == filters.size()) return ;
Filter filter = filters.get(index);
index++;
filter.doFilter(request,response,filterChain);
}
}

责任链模式

责任链模式是一种非常实用的行为型设计模式,它天然适用于“流水线”式的处理流程,尤其在框架级别的请求预处理、响应后处理机制中广泛使用。通过链式结构实现灵活组合、解耦与扩展,使得系统处理流程更加可控、可组合、可扩展。


责任链模式
http://gadoid.io/2025/07/28/责任链模式/
作者
Codfish
发布于
2025年7月28日
许可协议