紧接着上一个问题来:
为了不要跟原来的代码冲突,又新建了一个工程,将所有代码放在一起。
代码清单:(为了测试简洁,去掉了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的一些原理?
在此感谢马士兵老师的"设计模式"视频的讲解。
转载请注明出处:http://blog.csdn.net/acmman/article/details/44673483