责任链就是通过一连串的过滤器(filter)来对信息进行处理:
1.最简单的实现方案,通过filter数组来实现。
filter接口,用来统一方法名。
package com.bjsxt.dp.filter;
//定义一个接口,用来指定方法的名字为doFilter
publicinterface Filter {
String doFilter(String str);
}
FacFilter实现Filter接口
package com.bjsxt.dp.filter;
publicclass FaceFilterimplements Filter {
//@Override
//把:)替换成为^V^
public String doFilter(String str) {
return str.replace(":)","^V^");
}
}
HTMLFilter实现Filter接口
package com.bjsxt.dp.filter;
publicclass HTMLFilterimplements Filter {
//@Override
//把<替换成为[,把>替换成]
public String doFilter(String str) {
//process the html tag<>
String r = str.replace('<','[')
.replace('>',']');
return r;
}
}
SesitiveFilter实现Filter接口
package com.bjsxt.dp.filter;
publicclass SesitiveFilterimplements Filter {
//@Override
//把“被就业"替换成为"就业"
//把“敏感"替换为“”
public String doFilter(String str) {
//process the sensitive words
String r = str.replace("被就业","就业")
.replace("敏感","");
return r;
}
}
如果不使用责任链,可以在使用者,当中使用一个filter的数组来保存每个filter,并且分别调用每个filter的doFilter方法。
专门的字符串处理类:
package com.bjsxt.dp.filter;
publicclass MsgProcessor1 {
private Stringmsg;
//filter数组
Filter[] filters = {new HTMLFilter(),new SesitiveFilter(),new FaceFilter()};
public String getMsg() {
returnmsg;
}
publicvoid setMsg(String msg) {
this.msg = msg;
}
public String process() {
String r = msg;
//对字符串r,调用所有的filter
for (Filter f:filters) {
r = f.doFilter(r);
}
return r;
}
}
使用者就只需要给定字符串:
package com.bjsxt.dp.filter;
publicclass Main1 {
/**
*@paramargs
*/
publicstaticvoid main(String[] args) {
//对应一条信息当中各种信息进行替换
Stringmsg ="大家好:),<script>,敏感,被就业,网络授课没感觉,因为看不见大家伙儿";
MsgProcessor mp = new MsgProcessor();
mp.setMsg(msg);
Stringresult = mp.process();
System.out.println(result);
}
}
为了实现能灵活的在当前链当中打开一个缺口,加入新的过滤器(链),就提供了责任链这样一种方式。
2.通过责任链模式
责任链的主要任务是能够灵活的设定(添加和删除)过滤器的顺序和组合。
可以有多个责任链。
责任链本身也是一个过滤器,一个大过滤器,里面包含了很多小过滤器。
Main是使用者。也就是用户,不需要知道细节的实现。
package com.bjsxt.dp.filter;
publicclass Main {
/**
*@paramargs
*/
publicstaticvoid main(String[] args) {
//对应一条信息当中各种信息进行替换
String msg = "大家好:),<script>,敏感,被就业,网络授课没感觉,因为看不见大家伙儿";
MsgProcessor mp = new MsgProcessor();
mp.setMsg(msg);
FilterChain fc = new FilterChain();
//链条式编程,可以反复添加多个filter
fc.addFilter(new HTMLFilter())
.addFilter(new SesitiveFilter())
;
//把facefilter添加到fc2当中,那么就有两个fc:fc1和fc2
FilterChain fc2 = new FilterChain();
fc2.addFilter(new FaceFilter());
//因为fc2也实现了filter接口,那么fc2本身也就是一个filter,所以可以被添加到fc当中。
//所以fc2可以灵活的添加到fc当中的任何位置,由使用者,也就是main来控制。
fc.addFilter(fc2);
mp.setFc(fc);
String result = mp.process();
System.out.println(result);
}
}
MsgProcessor是用来处理消息的,提供了一个porcess()方法。在MsgProcessor当中有一个FilterChain对象。其实这个类可有可没有。也可以把这个类整合到main里面去。
package com.bjsxt.dp.filter;
publicclass MsgProcessor {
private Stringmsg;
//把filterchain作为一个成员变量放到这边,过滤规则都是有FC来实现。
FilterChain fc;
public FilterChain getFc() {
returnfc;
}
publicvoid setFc(FilterChain fc) {
this.fc = fc;
}
public String getMsg() {
returnmsg;
}
publicvoid setMsg(String msg) {
this.msg = msg;
}
//其实调用的是filterChain的doFilter方法,还是把每个Filter拿出来,每个执行一遍doFilter方法。
//现在其实process自己什么都不做,都是FC来处理。
public String process() {
returnfc.doFilter(msg);
}
}
FilterChain当中可以添加和删除filter。本例中只实现了添加,没实现删除。要注意的是,这些filter需要根据使用者的需求(选择哪些filter,filter的顺序),在main里面由使用者来添加的。FilterChain应该是一个很灵活的类。最关键的一步,是它自己也实现了filter接口。从来能够被添加到另一个FilterChain对象当中去,成为别人的一部分。
package com.bjsxt.dp.filter;
import java.util.ArrayList;
import java.util.List;
//filterChain自己也实现了filter接口,也就是说,
//filterChain自己也可以作为一个filter对象,被添加到另外一个Filterchain当中去.
//这样就实现了灵活的添加。哪怕是把一根filterChain作为一个大的fitler添加
//到另外一个fitlerChian当中。
publicclass FilterChainimplements Filter {
//在filterChain当中加入一个arraylist来存放filter
List<Filter> filters = new ArrayList<Filter>();
//把fitler加入到arraylist当中
//注意这里有个技巧,就是把这个方法的返回值设定为这个类自身。那么返回的还是这个类,又可以调用add方法。
//那么在使用这个类的时候,就可以用 fc.addFilter(new HTMLFilter()).addFilter(newSesitiveFilter());
//这样的方法来在使用者添加对象。这种方法叫链条式编程。
public FilterChain addFilter(Filter f) {
this.filters.add(f);
returnthis;
}
//把原MsgProcessor的处理字符串的方法,放到这里来了,那么FC就是专门用来处理字符串。
//MsgProcessor和业务逻辑分开。
public String doFilter(String str) {
String r = str;
for(Filter f:filters) {
r = f.doFilter(r);
}
return r;
}
}
3.双向责任链模式(主要是顺序的控制,个人感觉是递归思想的应用,当然这里不完全是递归。)
要求:过滤的信息,从客户端上到服务器端需要通过1,2,3这样的过滤,而从服务器到客户端的过滤顺序是3,2,1.双向过滤。而我们已经实现了,从客户端上到服务器端的单项过滤。其实质是一个堆栈结构,是先进后出的顺序。
问题实现的关键是在服务器向客户端返回的时候,需要是3,2,1的顺序。
如果要在服务器到客户端的过滤顺序也实现1,2,3非常的简单,只需要在从客户端上到服务器端调用责任链的时候,也调用对response的处理就可以。那么现在需要反向调用,实现的逻辑就比较复杂。
首先是filter接口,注意现在的方法定义当中的参数。
package com.bjsxt.dp.filter;
//现在的参数,就是request,response,还有chain
//传递的时候,可以是request+空的response
//或者是response+空的request
//注意现在的返回值,不再是string类型,而是把处理完成的信息保存在request和response对象当中。
//所以返回值为void。
publicinterface Filter {
//FilterChain在这里的意义: filter在FC里面,如果给定chain,
//当调用doFilter的时候,就可以指定下一步的FC怎么走
//灵活,可以实现反向。
void doFilter(Request request, Response response, FilterChainchain);
}
HTMLFilter类,注意在doFilter当中调用了chain.doFilter(request,response, chain);
package com.bjsxt.dp.filter;
publicclass HTMLFilterimplements Filter {
//@Override
publicvoid doFilter(Request request, Response response, FilterChainchain) {
//process the html tag<>
// 首先处理的request
request.requestStr = request.requestStr.replace('<','[')
.replace('>',']') + "---HTMLFilter()";
// 在request处理完成,之后马上调用下一个filter
chain.doFilter(request, response, chain);
response.responseStr +="---HTMLFilter()";
}
}
SesitiveFilter类,注意在doFilter当中调用了chain.doFilter(request,response, chain);
package com.bjsxt.dp.filter;
publicclass SesitiveFilterimplements Filter {
//@Override
publicvoid doFilter(Request request, Response response, FilterChainchain) {
//首先处理的request
request.requestStr = request.requestStr.replace("被就业","就业")
.replace("敏感","") + "---SesitiveFilter()";
//在request处理完成,之后马上调用下一个filter
chain.doFilter(request, response, chain);
response.responseStr +="---SesitiveFilter()";
}
}
FilterChain类,大递归,反复调用doFilter方法。
package com.bjsxt.dp.filter;
import java.util.ArrayList;
import java.util.List;
publicclass FilterChainimplements Filter {
List<Filter> filters = new ArrayList<Filter>();
//记录index
intindex = 0;
public FilterChain addFilter(Filter f) {
this.filters.add(f);
returnthis;
}
//@Override
publicvoid doFilter(Request request, Response response, FilterChainchain) {
//如果index已经走到了数组的最后。
if(index ==filters.size())return ;
//通过index来控制下一个filter是谁。
Filter f = filters.get(index);
//指向下一个filter
index ++;
f.doFilter(request, response, chain);
}
}
Request类
package com.bjsxt.dp.filter;
//模拟,从客户端到服务器的信息,request
publicclass Request {
String requestStr;
public String getRequestStr() {
returnrequestStr;
}
publicvoid setRequestStr(String requestStr) {
this.requestStr = requestStr;
}
}
Response类
package com.bjsxt.dp.filter;
//模拟,从服务器到客户端的信息,response
publicclass Response {
String responseStr;
public String getResponseStr() {
returnresponseStr;
}
publicvoid setResponseStr(String responseStr) {
this.responseStr = responseStr;
}
}
main类,使用者类:
package com.bjsxt.dp.filter;
//其核心过程,非常像一个大的递归程序。一路调用自己下去,然后一路反向返回。
publicclass Main {
/**
*@paramargs
*/
publicstaticvoid main(String[] args) {
String msg = "大家好:),<script>,敏感,被就业,网络授课没感觉,因为看不见大家伙儿";
Request request = new Request();
request.setRequestStr(msg);
Response response = new Response();
response.setResponseStr("response");
FilterChain fc = new FilterChain();
fc.addFilter(new HTMLFilter())
.addFilter(new SesitiveFilter())
;
//在main里面首先,把request和response对象传进去,同时把自己也传进去。
fc.doFilter(request, response, fc);
System.out.println(request.getRequestStr());
System.out.println(response.getResponseStr());
}
}
核心逻辑:
注意方法调用运行的顺序:
在main方法当中开始运行,调用fc的doFilter。这个时候index为0,fc的size是2.
在fc的filter当中,Filter f = filters.get(index);这个时候拿到的是第一个filter。通过index++,这个时候index变成1了。
马上通过fc的doFilter当中的f.doFilter调用第一个filter。这个时候,index为0的这个fc.doFilter就暂停。程序就跳转到HTMLfilter的doFilter当中。
这里的f就是Filter f = filters.get(index);当中得到那个index=0的filter,也就是HTMLfilter,对request处理。request处理完成,马上在HTMLfilter的doFilter方法调用了chain.doFilter.这个时候,HTMLfilter的doFilter方法暂停了。程序就跳转到fc的doFilter当中。
那么重新来到了fc的doFilter方法当中,要注意现在的index是1了。在fc的doFilter当中,Filter f =filters.get(index); 这个时候拿到的是第二个filter。拿到了第二个filter之后,通过index++,这个时候index变成2了。马上通过f.doFilter调用第二个filter。这个时候,index为1的这个fc.doFilter就也暂停。程序就跳转到Sensitivefilter的doFilter当中。
这里的f是Filter f = filters.get(index);当中得到那个index=1的filter,也就是第二个filter,是Sensitivefilter,对request处理。 request处理完成,马上在Sensitivefilter的doFilter方法调用了chain.doFilter.这个时候,Sensitivefilter的doFilter方法暂停了。程序就跳转到fc的doFilter当中。
那么再一次重新来到了fc的doFilter方法当中,现在的index是2了。因为if(index == filters.size()) return ;现在index是2,所以就返回了。那么request处理完毕。
返回的位置返回到上一个没有执行完毕的方法,也就是最后一个调用chain.doFilter方法的位置。那么来到Sensitivefilter的doFilter方法当中。Sensitivefilter就继续执行,把处理response的业务逻辑完成。
Sensitivefilter的doFilter方法处理结束,就要返回到上一个没有执行完毕的方法。也就是回到调用它的方法,也就是当index等于1的时候,fc.doFilter方法当中。
index等于1的fc.doFilter顺利执行结束,那么回到调用chain.doFilter的地方,也就是HTMLfilter的doFilter方法。
同样HTMLfilter的doFilter方法继续执行,把处理response的业务逻辑完成,返回到调用它的位置。也就是当index等于0的时候,fc.doFilter方法当中。
fc.doFilter顺利执行结束, main方法结束。