前言
最近在看JavaWeb框架Spring Boot的一些东西,里面涉及到关于过滤器的设计,其实这块的思想就是责任链模式,责任链的用途还是比较广的,著名的网络请求库Okhttp,其设计的核心思想也是责任链模式,下面就简单的实现一个责任链。我们的场景是一个Request 去请求Response.然后把这个过程设计成一个责任链,并且在这个过程中可以添加过滤器。
定义一个Filter接口
先定义一个Filter接口,如果要自定义过滤器,必须要实现这个Filter接口。在这个过滤器中,可以在请求之前和请求之后添加一些过滤操作。
1
2
3
4
|
public interface Filter {
Response doFilter(FilterChain chain);
}
|
定义一个FilterChain接口
顾名思义FilterChain,就是定义的一个责任链。它负责的任务是从过滤器的集合中把过滤器取出来,执行doFilter工作,这块的设计稍微有点绕,在下面会详细介绍这块的流程。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
public interface FilterChain {
/**
* 获取请求
* @return
*/
Request request();
/**
* 执行request
* @param request
* @return
*/
Response process(Request request);
}
|
定义一些中间类
创建一个Request和Response,模拟请求和响应,以及3个用于测试的Filter类。
1
2
3
|
public class Request {
public String request;
}
|
1
2
3
|
public class Response {
public String response;
}
|
1
2
3
4
5
6
7
8
9
10
11
|
public class FirstFilter implements Filter{
@Override
public Response doFilter(FilterChain chain) {
System.out.println("FirstFilter before...");
Request request = chain.request();
Response response = chain.process(request);
System.out.println("FirstFilter after...");
return response;
}
}
|
1
2
3
4
5
6
7
8
9
10
|
public class SecondFilter implements Filter {
@Override
public Response doFilter(FilterChain chain) {
System.out.println("SecondFilter before...");
Request request = chain.request();
Response response = chain.process(request);
System.out.println("SecondFilter after...");
return response;
}
}
|
1
2
3
4
5
6
7
8
9
10
|
public class ThirdFilter implements Filter {
@Override
public Response doFilter(FilterChain chain) {
System.out.println("ThirdFilter before...");
Request request = chain.request();
Response response = chain.process(request);
System.out.println("ThirdFilter after...");
return response;
}
}
|
定义一个RequestFilterChain
RequestFilterChain是责任链模式核心的实现,也是比较绕的地方。
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
|
public class RequestFilterChain implements FilterChain{
private int mIndex;
private List<Filter> mFilterList;
private Request mRequest;
public RequestFilterChain(List<Filter> filterList, int i, Request request) {
this.mFilterList = filterList;
this.mIndex = i;
this.mRequest = request;
}
@Override
public Request request() {
return mRequest;
}
@Override
public Response process(Request request) {
if(mFilterList.size() == mIndex){
System.out.println("mFilterList.size() == mIndex: " + mIndex);
Response response = new Response();
response.response = "this is a response";
return response;
}
Filter filter = mFilterList.get(mIndex);
RequestFilterChain filterChain = new RequestFilterChain(mFilterList, mIndex + 1, request);
return filter.doFilter(filterChain);
}
}
|
场景测试
创建了一个Request和3个Filter,并且还创建了一个RequestFilterChain,然后执行RequestFilterChain的process方法,这样请求就发起了,那他是怎么一步步经过过滤器发起请求,请求成功后再一步步的经过过滤器返回响应的结果呢?下面介绍它的核心逻辑。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
public class Client {
public static void main(String[] args) {
Response response = getChainOfFilters();
System.out.println("response: " + response.response);
}
private static Response getChainOfFilters() {
Request request = new Request();
request.request = "this is a request";
List<Filter> filterList = new ArrayList<>();
Filter firstFilter = new FirstFilter();
Filter secondFilter = new SecondFilter();
Filter thirdFilter = new ThirdFilter();
filterList.add(firstFilter);
filterList.add(secondFilter);
filterList.add(thirdFilter);
RequestFilterChain chain = new RequestFilterChain(filterList, 0, request);
return chain.process(request);
}
}
|
禅定时刻
其实整个过滤器的执行类似一个递归方法栈的执行,在Client类中我们创建了一个RequestFilterChain,他有3个参数,一个就是我们定义的过滤器集合,第二个参数是这个过滤器的索引,代表是第几个过滤器。第三个参数就是Request. 然后执行RequestFilterChain的process方法。这个process方法是整个逻辑的核心,通过传入的索引,我们可以从Filter集合中取出对应的Filter,并且执行它的doFilter方法。这样我们第一个过滤器就执行了。然后我们又创建了一个RequestFilterChain实例,传入到了doFilter方法中,并且把Filter的索引加1.这里看一下我们的第一个过滤器 FirstFilter的doFilter实现,它拿到传入的FilterChain,可以从中取出Request,进行一番包装后,继续调用FilterChain的process方法,因为我们的索引已经加1了,所以这次在RequestFilterChain的process方法中取出的Filter就是第二个了,重复上面的操作,索引再加1,执行第二个Filter的doFilter操作,直到最后一个Filter,在最后一个Filter执行FilterChain的process方法的时候,Filter集合中已经没有过滤器了,这个时候我们创建一个Response,代表请求成功,这样FilterChain的process方法,又会从后往前的经过过滤器进行响应,整个过程就是一个递归方法入栈出栈的过程。
总结
责任链做大的好处就是做到了解耦,我们可以任意的添加Filter,而不会对系统造成影响。但它也有使用的场景的限制,并且每个过滤器不能出现问题,否则整个系统都会受影响。
关于我