责任链--双向使用

来源:互联网 发布:sql in 10minutes 编辑:程序博客网 时间:2024/09/21 09:24

客户端发送给服务器,用一条责任链来过滤数据,如果服务器反馈给客户端信息,也想要过滤信息,是再定义一组过滤器,还是复用这些已经定义好的责任链呢?当然是复用这些已经定义好的责任链。
1、Request请求经过FilterChain(过滤器链),在FilterChain中依次进行处理,再到达服务器处理。
2、Response响应,倒序经过FilterChain
处理的过程有点类似于栈。
它们处理的结果都保存在对象内部
这里写图片描述
如何实现让Response倒序调用FilterChain?FilterChain中doFilter来依次遍历Filter实现过滤,那么可以给Filter一个对于FilterChain的引用,这样可以让过滤器链中的每个Filter自己控制这个过滤链往下走。
核心思想:让每一个身处过滤器链中的Filter都有对于该过滤器的引用,过滤器链中用一个index记录执行到哪一个Filter,在每个Filter处理完成之后,FilterChain把index加1 ,执行下一个Filter,当FilterChain中的所有Filter全部走完之后,Request对象处理完成,最后一个Filter处理完成,返回到原方法中,继续执行下面的代码,即调用response。(可以通过断点查看效果)
不管是javaWeb的拦截器还是Struts2的Filter都是这么处理的

这里写图片描述

模拟Request、Respnse对象

package test;//Reuqestpublic class Request {    String requestStr;    public void setRequestStr(String requestStr){        this.requestStr=requestStr;    }    public String getRequestStr(){        return this.requestStr;    }}//Responsepublic class Response {    String responseStr;    public void setRequestStr(String responseStr){        this.responseStr=responseStr;    }    public String getResponseStr(){        return this.responseStr;    }}

Filter中拥有对FilterChain的引用

package test;public interface Filter {    //既可以处理Request的过滤,又可以实现Response过滤    //最后处理完的信息都会保存在Response对象里,Response对象应该是根据Request处理结果得到的    //先处理完成请求,再得到响应对象返回         public void doFilter(Request rq,Response rs,FilterChain fc);}

FilterChain的doFilter方法用来执行下一个Filter,并记录执行到哪一个Filter

package test;import java.util.ArrayList;import java.util.List;public class FilterChain implements Filter{    private List<Filter> filters=new ArrayList<Filter>();       //用index来记录过滤器链执行到哪一个过滤器    int index;          public FilterChain addFilter(Filter filter){        filters.add(filter);        return this;    }    @Override    public void doFilter(Request rq, Response rs,FilterChain chain) {        // 在doFilter中完成调用过滤器链中的下一个过滤器        if(index==filters.size())            return;        Filter fl=filters.get(index);        index++;        fl.doFilter(rq, rs, chain);    }   }

过滤器类中对request、response进行过滤

package test;public class HtmlFilter implements Filter {    public HtmlFilter(){}       @Override    public void doFilter(Request rq, Response rs,FilterChain chain) {               System.out.print("HtmlFilter--");        rq.requestStr=rq.requestStr.replace("傻逼", "**");        //让FilterChain马上去调用下一个Filter        chain.doFilter(rq, rs, chain);        //处理response对象        rs.responseStr+="HtmlFilter--";    }   }public class minganFilter implements Filter {    @Override    public void doFilter(Request rq, Response rs,FilterChain chain) {        // TODO Auto-generated method stub        System.out.print("minganFilter--");        rq.requestStr=rq.requestStr.replace("3-8", "??");        chain.doFilter(rq, rs, chain);        rs.responseStr+="minganFilter--";    }}

main测试

package test;public class main {    public static void main(String[] args) {        Request rq=new Request();        rq.setRequestStr("李芬是个大傻逼!超级大3-8");        Response rs=new Response();        rs.setRequestStr("response:");        FilterChain fc=new FilterChain();        fc.addFilter(new HtmlFilter())                   .addFilter(new minganFilter());        fc.doFilter(rq, rs,fc);        System.out.println(rq.getRequestStr());        System.out.println(rs.getResponseStr());    }}

思考:如果到一个过滤器过滤之后,后面的过滤器没必要执行了,该如何做?
答:即chain.doFilter(rq,rs,fc)不再调用

0 0
原创粉丝点击