责任链--双向使用

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

责任链--双向使用_第2张图片

模拟Request、Respnse对象

package test;
//Reuqest
public class Request {
    String requestStr;
    public void setRequestStr(String requestStr){
        this.requestStr=requestStr;
    }
    public String getRequestStr(){
        return this.requestStr;
    }
}
//Response
public 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 filters=new ArrayList();   
    //用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)不再调用

你可能感兴趣的:(责任链--双向使用)