public class Demo2 {
public static void main(String[] args) {
String msg = "大家好 :), <script>haha</script> 我要说超级敏感的话";
MsgProcessor mp = new MsgProcessor();
mp.setMsg(msg);
System.out.println(mp.process());
}
}
class MsgProcessor{
private String msg;
private Filter[] filters = {new HtmlFilter(), new SensitiveFilter(), new ExpressionFilter()};
public String process(){
for(Filter f : filters){
msg = f.doFilter(msg);
}
return msg;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
//过滤器接口
interface Filter{
public String doFilter(String s);
}
//处理html标签
class HtmlFilter implements Filter{
-
上面的代码已经具备了责任链的模型. 在帖子发送到服务器的过程中, 它将依次经过3个过滤器, 这三个过滤器就构成一条过滤器链.
-
-
下面我们考虑, 如果我们要在帖子处理过程中加入新的过滤器链条, 加在原链条的末尾或中间, 该怎么办呢?
-
消息经过过滤器链条的过程会得到处理, 我们可以把过滤器链条看成一个过滤器, 让他也实现
Filter
接口, 那么就可以在一条过滤链中任意加入其他过滤器和过滤链了. -
下面的代码实现了过滤链
FilterChain
, 用过滤链替代原来的MsgProcessor
.
public class Demo3 {
public static void main(String[] args) {
String msg = "大家好 :), <script>haha</script> 我要说超级敏感的话";//待处理的帖子
FilterChain fc1 = new FilterChain();//创建一条过滤器链1
fc1.add(new HtmlFilter())
.add(new SensitiveFilter());//往过滤器链1中添加过滤器
FilterChain fc2 = new FilterChain();//创建一条过滤器链2
fc2.add(new ExpressionFilter());//往过滤器链2中添加过滤器
fc1.add(fc2);//把过滤器链2当作过滤器添加到过滤器链1中,(过滤器链实现了Filter接口)
msg = fc1.doFilter(msg);//使用过滤器链1对帖子进行过滤
System.out.println(msg);
}
}
class FilterChain implements Filter{
private List<Filter> list = new ArrayList<>();
public FilterChain add(Filter filter){
this.list.add(filter);
return this;
}
更精巧设计, 展现责任链模式
-
在继续优化之前, 我们考虑更现实的需求, 一个请求(发出一个帖子)作为数据报发送给服务器, 服务器除了需要对请求进行过滤外, 还需要给出响应, 并且可能要对响应也进行处理. 如下图所示
-
当一个消息(包含请求体和响应体)发往服务器时, 它将依次经过过滤器1, 2, 3. 而当处理完成后, 封装好响应发出服务器时, 它也将依次经过过滤器3, 2, 1.
-
大家可能会觉得有点像栈结构, 但是像归像, 这一逻辑应该如何实现呢?
-
首先我们可以让过滤器持有过滤器链的引用, 通过调用过滤器链依次执行每个过滤器. 为了能让过滤器依次执行每个过滤器, 过滤器会持有一个
index
序号, 通过序号控制执行顺序. 至于后面对response
的倒序请求, 则通过方法返回实现. 这部分设计纯用文字难以讲清, 请务必看下面的代码和代码后的分析, 配图. -
这个部分是责任链的精髓了, 懂了这部分代码, 看Web开发中的过滤器源码就没压力了.
public class Demo4 {
public static void main(String[] args) {
String msg = "大家好 :), <script>haha</script> 我要说超级敏感的话";//以下三行模拟一个请求
Request request = new Request();
request.setRequestStr(msg);
Response response = new Response();//响应
FilterChain fc = new FilterChain();//过滤器链
HtmlFilter f1 = new HtmlFilter();//创建过滤器
SensitiveFilter f2 = new SensitiveFilter();
ExpressionFilter f3 = new ExpressionFilter();
fc.add(f1);//把过滤器添加到过滤器链中
fc.add(f2);
fc.add(f3);
fc.doFilter(request, response, fc);//直接调用过滤器链的doFilter()方法进行处理
System.out.println(request.getRequestStr());
}
}
interface Filter{
public void doFilter(Request request, Response response, FilterChain fc);
}
class FilterChain implements Filter{
private List<Filter> list = new ArrayList<>();
private int index = 0;
public FilterChain add(Filter filter){
this.list.add(filter);
return this;
}