责任链模式是很多对象由每个对象对其下家的引用而连接起来形成一条链,请求在这条链上传递,直到链上的某个对象处理此请求,或者每个对象都可以处理请求,并传给下一家,直到最终链上每个对象都处理完。这样可以不影响客户端而能够在链上增加任意的处理节点。
在处理用户的请求时可能要根据不同的情况对请求添加不同的处理逻辑,在这时候就可以利用责任链进行设计。当需要添加一个处理逻辑时可以很方便的添加一个处理的节点。
现在我们的需求是处理用户的请求,将用户提交的字符串信息进行层层处理,同时在处理完成之后返回结果时,也要对返回的字符串进行层层处理,而处理返回的情况时其处理的顺序和先前是正好相反的顺序。
通常责任链模式包含下面几个角色:
- Handler(抽象处理者):定义出一个处理请求的接口。如果需要,接口可以定义 出一个方法以设定和返回对下家的引用。这个角色通常由一个Java抽象类或者Java接口实现。上图中Handler类的聚合关系给出了具体子类对下家的引用,抽象方法handleRequest()规范了子类处理请求的操作。
- ConcreteHandler(具体处理者):具体处理者接到请求后,可以选择将请求处理掉,或者将请求传给下家。由于具体处理者持有对下家的引用,因此,如果需要,具体处理者可以访问下家。
一个纯的责任链模式要求一个具体的处理者对象只能在两个行为中选择一个:一是承担责任,而是把责任推给下家。不允许出现某一个具体处理者对象在承担了一部分责任后又 把责任向下传的情况。
在一个纯的责任链模式里面,一个请求必须被某一个处理者对象所接收;在一个不纯的责任链模式里面,一个请求可以最终不被任何接收端对象所接收。
纯的责任链模式的实际例子很难找到,一般看到的例子均是不纯的责任链模式的实现。有些人认为不纯的责任链根本不是责任链模式,这也许是有道理的。但是在实际的系统里,纯的责任链很难找到。如果坚持责任链不纯便不是责任链模式,那么责任链模式便不会有太大意义了。
Request和Response:
public class Request {
private String RequestStr;
public void setRequestStr(String requestStr) {
RequestStr = requestStr;
}
public String getRequestStr() {
return RequestStr;
}
}
public class Response {
private String ResponseStr;
public void setResponseStr(String responseStr) {
ResponseStr = responseStr;
}
public String getResponseStr() {
return ResponseStr;
}
}
Filter
public interface Filter {
public abstract void doFilter(Request request, Response response, FilterChain filterChain);
}
public class HTMLFilter implements Filter {
@Override
public void doFilter(Request request, Response response,
FilterChain filterChain) {
String requestStr = request.getRequestStr();
requestStr = requestStr.replaceAll("<", "[")
.replaceAll(">", "]");
request.setRequestStr(requestStr);
filterChain.doFilter(request, response, filterChain);
requestStr = request.getRequestStr() + "\n htmlfilter return;";
request.setRequestStr(requestStr);
}
}
public class SensitiveFilter implements Filter{
@Override
public void doFilter(Request request, Response response,
FilterChain filterChain) {
String requestStr = request.getRequestStr();
requestStr = requestStr.replaceAll("邪恶", "和谐")
.replaceAll("cl", "**")
.replaceAll("还钱", "来喝杯茶");
request.setRequestStr(requestStr);
filterChain.doFilter(request, response, filterChain);
requestStr = request.getRequestStr() + "\n sensitivefilter return;";
request.setRequestStr(requestStr);
}
}
测试类:
public class Test {
public static void main(String[] args) {
String requestStr = "cl,你好快还钱<script>!!";
Request request = new Request();
Response response = new Response();
request.setRequestStr(requestStr);
Filter htmlFilter = new HTMLFilter();
Filter sensitiveFilter = new SensitiveFilter();
FilterChain chain = new FilterChain();
chain.add(htmlFilter);
chain.add(sensitiveFilter);
chain.doFilter(request, response, chain);
System.out.println("request: " + request.getRequestStr());
}
}
-
我们建立的FilterChain中继承了Filter接口,所以在测试类中就可以像使用其他的过滤器一样使用FilterChain,大大提高了灵活性;
-
对于实现责任链的访问处理顺序问题,该问题的解决使用的是递归的思想,从而使先调用的结点在处理返回结果时其调用过滤器的顺序是相反的。这种解决方案在Struts和其他框架中实现过滤器和拦截器使用的较为普遍,并且十分巧妙。
