Filter Pattern 2 (dubbo的实现方式)

前一篇FilterPattern的范式,基本和Tomcat实现的filter chain是一样的;

这里介绍一下我看完dubbo关于Filter Pattern的实现思路,自己抽象出来的代码,以及理解

相关类的UML图:


UML图


    可以从上图中看到这里的Invoker对应原来的Servlet,这里的Filter和原来的Filter只有参数签名上的区别;
Filter的第一个参数由FilterChain变成了Invoker;
Invoker和原来的Servlet的函数签名到是一点都没变,可以理解,只是名字不一样,功能性和原来一样(这里起名Invoker是为了和dubbo中的invoker保持一致)
原先的Filter调用链路是有FilterChain来串联起来,现在FilterChain变成了Invoker,可以简单的猜想,现在由Invoker串起Filter调用链路;(这里你肯定想Invoker不是用来执行具体业务逻辑的吗,怎么能串的起Filter调用链路呢,具体可以往后看)

至于是如何串起的,就要看FilterWrapper和相关Filter的代码了


public interface Invoker {


    Response invoke(Request request);
}


public class HttpInvoker implements Invoker {



    @Override
    public Response invoke(Request request) {
        Response response = new Response();

        response.setData( "RESPONSE OF [" + request.getData() + "]");

        return response;
    }
}



public class FilterWrapper {

    private List<Filter> filterList;

    public FilterWrapper(List<Filter> filterList) {
        this.filterList = filterList;
    }

    public Invoker buildInvokerChain(final Invoker invoker){

        Invoker last = invoker;

        //倒序遍历filterList,保证index最小的在最外层执行
        for (int i = filterList.size() - 1; i >= 0 ; i--) {
            final Invoker next = last;

            Filter filter = filterList.get(i);
            last = new Invoker() {
                //用匿名内部类,把filter包装成invoker,为了方便理解,就没有写成lambda表达式了
                @Override
                public Response invoke(Request request) {
                    return filter.invoke(next, request);
                }
            };
        }

        return last;

    }
}


public class PrintFilter implements Filter {

    @Override
    public Response invoke(Invoker invoker, Request request) {

        System.out.println("PrintFilter: request:" + request.getData());

        return invoker.invoke(request);
    }
}


public class ModifyDataFilter implements Filter {

    @Override
    public Response invoke(Invoker invoker, Request request) {
        request.setData(request.getData() + " modified by ModifyDataFilter!");
        return invoker.invoke(request);
    }
}


public class Main {
    public static void main(String[] args) {
        ArrayList<Filter> filterList = new ArrayList<>();
        filterList.add(new ModifyDataFilter());
        filterList.add(new PrintFilter());

        FilterWrapper filterWrapper = new FilterWrapper(filterList);

        Invoker invoker = filterWrapper.buildInvokerChain(new HttpInvoker());

        Request request = new Request("hello word!");

        Response response = invoker.invoke(request);

        System.out.println(response.getData());

    }
}

    从上面的代码可以看到,实际上是用Invoker的匿名内部类来实现调用链路的串联,就我浅薄的理解,buildInvokerInvokerChain实现的invoker应该算是柯里化
debug线程栈




然而这样写Filter Chain有什么优点呢?

  1. Filter签名参数再也不用带着FilterChain了,Invoker接口单一,更加安全

posted on 2021-07-28 17:33  mindSucker  阅读(39)  评论(0编辑  收藏  举报