什么是责任链模式
当请求端Client发出请求时,为了降低请求者Client
与处理对象们Handlers
之间的耦合;同时满足众多Handlers
都能有机会参与到对请求的处理,将Handler
对象组成一条链。而请求随着链不断传递,直到被处理并返回结果。
通过定义可以发现,责任链其实有三个部分组成:
- 客户端请求类
Client
:发起请求,相当于开启责任链,提交任务到责任链等待处理结果。
- 处理类的抽象接口
Handler
或者抽象类:包含处理请求方法的定义,通常也包含后继链指向。
- 具体的
Handler
的实现类ConcreteHandler
:根据自身能力的大小对Client
的请求的具体实现,有可能刚好匹配那么直接处理返回结果链的调用结束,否则将请求转发到后继链继续处理直到请求处理完成。
UML图如下:

代码示例:
Client:
1 2 3 4 5 6 7 8 9
| public class Main { public static void main(String[] args) { Msg msg = new Msg(); msg.setMsg("大家好:),<script>,欢迎访问www.oldman.run,大家都是996"); new HTMLFilter().doFilter(msg); new SensitiveFilter().doFilter(msg); System.out.println(msg); } }
|
Handler:
1 2 3
| public interface Filter { void doFilter(Msg msg); }
|
ConcreteHandler:
1 2 3 4 5 6 7 8 9
| public class HTMLFilter implements Filter{ @Override public void doFilter(Msg msg) { String s = msg.getMsg(); s = s.replace('<', '['); s = s.replace('>', ']'); msg.setMsg(s); } }
|
1 2 3 4 5 6 7 8
| public class SensitiveFilter implements Filter{ @Override public void doFilter(Msg msg) { String s = msg.getMsg(); s = s.replaceAll("996", "955"); msg.setMsg(s); } }
|
改造:
新增FilterChain类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public class FilterChain { List<Filter> filters = new ArrayList<>();
public FilterChain add(Filter f) { filters.add(f); return this; }
public void doFilter(Msg m) { for (Filter f : filters) { f.doFilter(m); } } }
|
1 2 3 4 5 6 7 8 9 10 11 12
| public class Main { public static void main(String[] args) { Msg msg = new Msg(); msg.setMsg("大家好:),<script>,欢迎访问www.oldman.run,大家都是996");
FilterChain chain = new FilterChain(); chain.add(new HTMLFilter()).add(new SensitiveFilter()); chain.doFilter(msg); System.out.println(msg); } }
|
假如我新建另一条链,那怎么样才能连在一起
1 2 3 4 5 6 7 8
| public class FaceFilter implements Filter{ @Override public void doFilter(Msg msg) { String s = msg.getMsg(); s = s.replace(":)", "^V^"); msg.setMsg(s); } }
|
1 2 3 4 5 6 7 8
| public class URLFilter implements Filter{ @Override public void doFilter(Msg msg) { String s = msg.getMsg(); s = s.replace("www.oldman.run", "https://www.oldman.run"); msg.setMsg(s); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public class Main { public static void main(String[] args) { Msg msg = new Msg(); msg.setMsg("大家好:),<script>,欢迎访问www.oldman.run,大家都是996");
FilterChain chain = new FilterChain(); chain.add(new HTMLFilter()).add(new SensitiveFilter());
FilterChain chain2 = new FilterChain(); chain2.add(new FaceFilter()).add(new URLFilter());
chain.doFilter(msg); chain2.doFilter(msg); System.out.println(msg); } }
|
改造后:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public class FilterChain implements Filter{ List<Filter> filters = new ArrayList<>();
public FilterChain add(Filter f) { filters.add(f); return this; }
@Override public void doFilter(Msg m) { for (Filter f : filters) { f.doFilter(m); } } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public class Main { public static void main(String[] args) { Msg msg = new Msg(); msg.setMsg("大家好:),<script>,欢迎访问www.oldman.run,大家都是996");
FilterChain chain = new FilterChain(); chain.add(new HTMLFilter()).add(new SensitiveFilter());
FilterChain chain2 = new FilterChain(); chain2.add(new FaceFilter()).add(new URLFilter());
chain.add(chain2); chain.doFilter(msg); System.out.println(msg); } }
|
由FilterChain中的某个Filter来决定链条是否继续,改造代码:
1 2 3
| public interface Filter { boolean doFilter(Msg msg); }
|
所有实现Filter接口的类都修改doFilter方法返回值为boolean,默认返回true,其中SensitiveFilter默认返回false:
1 2 3 4 5 6 7 8 9
| public class SensitiveFilter implements Filter{ @Override public boolean doFilter(Msg msg) { String s = msg.getMsg(); s = s.replaceAll("996", "955"); msg.setMsg(s); return false; } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| public class FilterChain implements Filter{ List<Filter> filters = new ArrayList<>();
public FilterChain add(Filter f) { filters.add(f); return this; }
@Override public boolean doFilter(Msg m) { for (Filter f : filters) { if(!f.doFilter(m)){ return false; } } return true; } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| public class Main { public static void main(String[] args) { Msg msg = new Msg(); msg.setMsg("大家好:),<script>,欢迎访问www.oldman.run,大家都是996");
FilterChain chain = new FilterChain(); chain.add(new HTMLFilter()).add(new SensitiveFilter());
FilterChain chain2 = new FilterChain(); chain2.add(new FaceFilter()).add(new URLFilter());
chain.add(chain2); chain.doFilter(msg); System.out.println(msg); } }
|
这时运行程序会发现,HTMLFilter、SensitiveFilter、FaceFilter、URLFilter四个过滤器中,只执行了第一个HTMLFilter,到第二个SensitiveFilter过滤器时返回了false,就停止执行后面两个过滤器了。
责任链能解决什么问题
缺点:
- 当职责的增加,链的长度增加,调用栈深度加深则会影响系统的效率。
- 职责的具体实现类如果较多,增加了一定的维护成本,同时
Client
端开启链时复杂度提高。
后面我们再来还原一下javax.servlet包下的Filter和FilterChain是怎么实现过滤器的。