前言

最近在看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,而不会对系统造成影响。但它也有使用的场景的限制,并且每个过滤器不能出现问题,否则整个系统都会受影响。

关于我

  • 公众号: CodingDev