客户端发送给服务器,用一条责任链来过滤数据,如果服务器反馈给客户端信息,也想要过滤信息,是再定义一组过滤器,还是复用这些已经定义好的责任链呢?当然是复用这些已经定义好的责任链。
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;
//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<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)不再调用