责任链模式(Chain of Responsibility)的目标是使多个对象都有机会处理请求从而避免请求的发送者和接收者之间的耦合关系将这些对象连成一条链并沿着这条链传递请求直到有一个对象处理它为止
在处理用户的请求时可能要根据不同的情况对请求添加不同的处理逻辑在这时候就可以利用责任链进行设计当需要添加一个处理逻辑时可以很方便的添加一个处理的节点
现在我们的需求是处理用户的请求将用户提交的字符串信息进行层层处理同时在处理完成之后返回结果时也要对返回的字符串进行层层处理而处理返回的情况时其处理的顺序和先前是正好相反的顺序
首先建立用户的请求和接收对象Request和Response
packagecomlcqfilter;
publicclassRequest{
StringrequestStr;
publicStringgetRequestStr(){
returnrequestStr;
}
publicvoidsetRequestStr(StringrequestStr){
thisrequestStr=requestStr;
}
}
packagecomlcqfilter;
publicclassResponse{
StringresponseStr;
publicStringgetResponseStr(){
returnresponseStr;
}
publicvoidsetResponseStr(StringresponseStr){
thisresponseStr=responseStr;
}
}
我们将处理用户信息的逻辑抽象成为一个个的过滤器进一步抽象出过滤器接口Filter
packagecomlcqfilter;
publicinterfaceFilter{
publicvoiddoFilter(RequestrequestResponseresponseFilterChainchain);
}
注意在Filte接口中doFilter方法参数中有FilterChain的一个变量我们再建立FilterChain类
packagecomlcqfilter;
importjavautilArrayList;
importjavautilList;
publicclassFilterChainimplementsFilter{
List<Filter>filters=newArrayList<Filter>();
intindex=;
publicFilterChainaddFilter(Filterf){
thisfiltersadd(f);
returnthis;
}
@Override
publicvoiddoFilter(RequestrequestResponseresponseFilterChainchain){
if(index==filterssize())
return;
Filterf=filtersget(index);
index++;
fdoFilter(requestresponsechain);
}
}
在FilterChain中继承了Filter接口从而实现了doFilter方法在FilterChain中又有一个index变量该变量是用来标记当前访问的是哪一个过滤器这些过滤器是存放在ArrayList中的这样用户在使用的时候就可以实现自己的过滤器编写自己的处理逻辑从而将自己的过滤器添加到ArrayList中再调用FilterChain的doFilter方法遍历整个责任链
下面我们编写三个过滤器
HTMLFilter类
packagecomlcqfilter;
/**
*过滤HTML中的脚本元素
*@authorlcq
*
*/
publicclassHTMLFilterimplementsFilter{
@Override
publicvoiddoFilter(RequestrequestResponseresponseFilterChainchain){
requestrequestStr=requestgetRequestStr()replace(<[)
replace(>]HTMLFilter);
chaindoFilter(requestresponsechain);
responseresponseStr+=HTMLFilter;
}
}
SesitiveFilter类
packagecomlcqfilter;
publicclassSesitiveFilterimplementsFilter{
@Override
publicvoiddoFilter(RequestrequestResponseresponseFilterChainchain){
requestrequestStr=requestgetRequestStr()replace(敏感)
replace(猫猫hahaSesitiveFilter);
chaindoFilter(requestresponsechain);
responseresponseStr+=SesitiveFilter;
}
}
FaceFilter类
packagecomlcqfilter;
publicclassFaceFilterimplementsFilter{
@Override
publicvoiddoFilter(RequestrequestResponseresponseFilterChainchain){
requestrequestStr=requestgetRequestStr()replace(:)
^V^FaceFilter);
chaindoFilter(requestresponsechain);
responseresponseStr+=FaceFilter;
}
}
最后编写测试类
packagecomlcqfilter;
publicclassMain{
publicstaticvoidmain(String[]args){
Stringmessage=敏感词汇重庆<script>躲猫猫:);
Requestrequest=newRequest();
requestsetRequestStr(message);
Responseresponse=newResponse();
responsesetResponseStr(response);
FilterChainfc=newFilterChain();
fcaddFilter(newHTMLFilter())addFilter(newSesitiveFilter());
FilterChainfc=newFilterChain();
fcaddFilter(newFaceFilter());
fcaddFilter(fc);
fcdoFilter(requestresponsefc);
Systemoutprintln(request=+requestgetRequestStr());
Systemoutprintln(response=+responsegetResponseStr());
}
}
在上面的实例中应该注意两个地方
我们建立的FilterChain中继承了Filter接口所以在测试类中就可以像使用其他的过滤器一样使用FilterChain大大提高了灵活性
对于实现责任链的访问处理顺序问题该问题的解决使用的是递归的思想从而使先调用的结点在处理返回结果时其调用过滤器的顺序是相反的这种解决方案在Struts和其他框架中实现过滤器和拦截器使用的较为普遍并且十分巧妙