紧接着上一个问题来:

为了不要跟原来的代码冲突,又新建了一个工程,将所有代码放在一起。
代码清单:(为了测试简洁,去掉了FaceFilter.java)
Filter.java
FilterChain.java
HTMLFilter.java
Main.java
MsgProcessor.java
Request.java
Response.java
SesitiveFilter.java


因为新加入了Response和Request类,我们要改写几个类:
改写Filter.java:

package cn.edu.hpu.filter.web;

public interface Filter {

void doFilter(Request request,Response response);
}


参数该成request和response



改写FilterChian:


package cn.edu.hpu.filter.web;


import java.util.List;
import java.util.ArrayList;


public class FilterChain implements Filter{
List<Filter> filters=new ArrayList<Filter>();

//返回值是FilterChain只为了在Main中满足链条式的编程
public FilterChain addFilter(Filter f) {
this.filters.add(f);
return this;
}

@Override
public void doFilter(Request request,Response response) {
for(Filter f:filters){
f.doFilter(request,response);
}
}
}


具体的各种Filter我们就应该这么做了(先处理request请求):


HTMLFilter:


package cn.edu.hpu.filter.web;


public class SesitiveFilter implements Filter {
@Override
public void doFilter(Request request, Response response) {
String r=request.getRequestStr().replace("偷盗", "和谐")
.replace("抢劫", "帮助");
request.setRequestStr(r);
}
}


HTMLFilter:


package cn.edu.hpu.filter.web;

public class HTMLFilter implements Filter {


@Override
public void doFilter(Request request, Response response) {
//先处理带尖括号的信息
String str=request.getRequestStr().replace('<', '[')
.replace('>', ']');
request.setRequestStr(str);
}


}


如果我们既想处理request又想处理response,处理反馈这种东西,应该在所有请求处理完毕之后,


再来处理我们这个反馈。因为我们反馈的信息肯定是根据请求最后处理的结果来决定的。



我们先删除掉MsgProcessor.java(因为现在这个类有些多余,不如将东西都放在Main类中去做)



在Main中:


package cn.edu.hpu.filter.web;


public class Main {
public static void main(String[] args) {
String msg="大家好:),<script>,偷盗,抢劫,我们要把设计模式学好";
Request request=new Request();
request.setRequestStr(msg);
Response response=new Response();
//response对象无反馈信息之前先设一个暂时的信息"response"
response.setResponseStr("response");
FilterChain fc=new FilterChain();
fc.addFilter(new HTMLFilter())
.addFilter(new SesitiveFilter());//链条式写法


fc.doFilter(request, response);
System.out.println(request.getRequestStr());
System.out.println(response.getResponseStr());
}
}

测试结果:


大家好:),[script],和谐,帮助,我们要把设计模式学好


response



现在我们只处理了request的信息,还没有处理response的信息



对于request和response我们要求的顺序是这样的:


当我们的一个request传过来的时候,被第一个Filter处理,接下来被第二、第三个Filter处理,


处理完成之后,会有response对象从服务器端反馈信息给我,这个反馈信息被处理的过程是,首先


被第三个进行处理,接下来被第二个处理,最后被第一个处理(有些像堆栈)。



上面说的实现起来要需要一些技巧。



我们先给HTMLFilter和SesitiveFilter类的request和response处理分别加上标记,


来观察一下过滤链的运行顺序:


HTMLFilter:


package cn.edu.hpu.filter.web;


public class HTMLFilter implements Filter {


@Override
public void doFilter(Request request, Response response) {
//先处理带尖括号的信息
String str=request.getRequestStr().replace('<', '[')
.replace('>', ']');
request.setRequestStr(str+"----HTMLFilter");

str=response.getResponseStr()+"----HTMLFilter";
response.setResponseStr(str);
}


}


SesitiveFilter:


package cn.edu.hpu.filter.web;


public class SesitiveFilter implements Filter {
@Override
public void doFilter(Request request, Response response) {
String r=request.getRequestStr().replace("偷盗", "和谐")
.replace("抢劫", "帮助");
request.setRequestStr(r+"----SesitiveFilter");

r=response.getResponseStr()+"----SesitiveFilter";
response.setResponseStr(r);
}
}

Main的测试结果:


大家好:),[script],和谐,帮助,我们要把设计模式学好----HTMLFilter----SesitiveFilter


response----HTMLFilter----SesitiveFilter



对于request请求这个过滤顺序是对的,但是对于response这个过滤顺序就不是刚刚我们所说的想要的


那种顺序,说明我们不可以在处理request的下面去直接处理response。想要完成这个功能,就需要一些扎实的编程技巧。



我们在Filter接口的doFilter方法中加入FilterChain的参数,这样一来,我们就可以在doFilter方法


中去控制使用FilterChain中各种Filter的顺序了。


Filter:


package cn.edu.hpu.filter.web;


public interface Filter {

void doFilter(Request request,Response response,FilterChain fc);
}


其他各类加上此参数即可。


当我们处理完request信息之后,我可以拿FilterChain使用。


要改写一下FilterChain,好让它能去主动一个一个调用Filter,而不是像之前


的一次遍历着去处理信息:


package cn.edu.hpu.filter.web;

import java.util.List;
import java.util.ArrayList;


public class FilterChain implements Filter{
List<Filter> filters=new ArrayList<Filter>();
//记录运行到哪一个Filter了
int index=0;

//返回值是FilterChain只为了在Main中满足链条式的编程
public FilterChain addFilter(Filter f) {
this.filters.add(f);
return this;
}

@Override
public void doFilter(Request request,Response response,FilterChain fc) {
if(index==filters.size()) return;

Filter f=filters.get(index);
index++;
f.doFilter(request, response, fc);

}
}


处理完request之后我们马上让FilterChain去调用下一个Filter:


package cn.edu.hpu.filter.web;

public class SesitiveFilter implements Filter {
@Override
public void doFilter(Request request, Response response,FilterChain fc) {
String r=request.getRequestStr().replace("偷盗", "和谐")
.replace("抢劫", "帮助");
request.setRequestStr(r+"----SesitiveFilter");

fc.doFilter(request, response, fc);

r=response.getResponseStr()+"----SesitiveFilter";
response.setResponseStr(r);
}
}


package cn.edu.hpu.filter.web;

public class HTMLFilter implements Filter {


@Override
public void doFilter(Request request, Response response,FilterChain fc) {
//先处理带尖括号的信息
String str=request.getRequestStr().replace('<', '[')
.replace('>', ']');
request.setRequestStr(str+"----HTMLFilter");


fc.doFilter(request, response, fc);

str=response.getResponseStr()+"----HTMLFilter";
response.setResponseStr(str);
}

}


我们来测试Main,测试结果为:


大家好:),[script],和谐,帮助,我们要把设计模式学好----HTMLFilter----SesitiveFilter


response----SesitiveFilter----HTMLFilter



刚好达到我们想要的结果,使response的处理是逆向的(request是从栈顶到站底,response是从栈底到栈顶)!



大家可能还没摸清头脑,我们分析一下:


看Main:


package cn.edu.hpu.filter.web;


public class Main {
public static void main(String[] args) {
String msg="大家好:),<script>,偷盗,抢劫,我们要把设计模式学好";
Request request=new Request();
request.setRequestStr(msg);
Response response=new Response();
//response对象无反馈信息之前先设一个暂时的信息"response"
response.setResponseStr("response");
FilterChain fc=new FilterChain();
fc.addFilter(new HTMLFilter())
.addFilter(new SesitiveFilter());//链条式写法


fc.doFilter(request, response,fc);
System.out.println(request.getRequestStr());
System.out.println(response.getResponseStr());
}
}

我们首先调用的是FilterChain的doFilter方法,这个时候,FilterChain中的index是0,也就是说调用了第一个Filter即HTMLFilter,这个时候在HTMLFilter中处理了request的信息之后(此时是request信息被第一次处理,并且加了标记"----HTMLFilter"),调用了FilterChain的doFilter方法,此时在FilterChain的doFilter方法中又进一步调用了下一个Filter,这样下来,最终调取了最后的SesitiveFilter,在SesitiveFilter中进一步处理了request的信息(此时是request信息被第二次处理,并且加了标记"----SesitiveFilter"),然后继续执行FilterChain的doFilter方法,发现index已经到头了,方法结束,这个时候开始执行下面的处理Response的代码(此时response信息被第一次处理,并且加了标记"----SesitiveFilter"),处理完毕时候跳出了递归,最后又回到了HTMLFilter中,接下去处理response(此时response信息被第二次处理,并且加了标记"----HTMLFilter"),




其实运行一下,仔细思考一下(前提是你理解递归的概念),理解起来并不难。难得的是,JavaWeb中对Servlet的过滤器就是采用类似这种机制来完成请求和反馈的过滤的(其实还不如刚刚我们设计的那种)。




至此责任链就探讨完了,大家是不是也理解了Filter的一些原理?


在此感谢马士兵老师的"设计模式"视频的讲解。