【设计模式】责任链4-链接链

紧接着上一个问题来:

为了不要跟原来的代码冲突,又新建了一个工程,将所有代码放在一起。
代码清单:(为了测试简洁,去掉了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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值