博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
责任链设计模式(过滤器、拦截器)
阅读量:5278 次
发布时间:2019-06-14

本文共 5196 字,大约阅读时间需要 17 分钟。

责任链设计模式(Chain of Responsibility)的应用有:Java Web中的过滤器链、Struts2中的拦截器栈。

先看一个问题:

给定一个字符串“被就业了:),敏感信息,<script>”,对其中的HTML标记和敏感词进行过滤或替换。

本文主要以该问题设计方法的演变来讲解责任链设计模式。

第一种设计:没有任何设计模式

设计了一个MsgProcessor类,完成字符串处理的主要工作。MainClass类是本设计中的测试类。

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class MainClass {
    public static void main(String[] args) {
        //需要被过滤的语句
        String msg = "被就业了:),敏感信息,<script>";
 
        //实例化处理类
        MsgProcessor mp = new MsgProcessor(msg);
        String r = mp.process();
 
        System.out.println(r);
    }
 
}
 
public class MsgProcessor {
    private String msg;
    public MsgProcessor(String msg){
        this.msg = msg;
    }
 
    public String process(){
        String r = msg;
        //过滤msg中的HTML标记
        r = r.replace("<", "&lt;").replace(">", "&gt;");
        //过滤敏感词
        r = r.replace("敏感", "").replace("被就业", "就业");
 
        return r;
    }
}

第二种设计:增加一个Filter接口

在第一种设计中,对字符串的所有处理都放在MsgProcessor类中,扩展性极差。如果要过滤字符串中的笑脸(将”:)”替换成”^_^”),则需要改动MSgProcessor中的process方法。

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
public interface Filter {
    String doFilter(String str);
}
 
public class HtmlFilter implements Filter {
    public String doFilter(String msg) {
        String r = msg;
        //过滤msg中的HTML标记
        r = r.replace("<", "&lt;").replace(">", "&gt;");
 
        return r;
    }
}
 
public class SensitiveFilter implements Filter {
    public String doFilter(String msg) {
        String r = msg;
        //过滤敏感词
        r = r.replace("敏感", "").replace("被就业", "就业");
 
        return r;
    }
}
 
public class MsgProcessor {
    private String msg;
    private Filter[] filters = {
new HtmlFilter(),new SensitiveFilter()};
 
    public MsgProcessor(String msg){
        this.msg = msg;
    }
 
    public String process(){
        String r = msg;
        for(Filter f : filters){
            r = f.doFilter(r);
        }
        return r;
    }
}

此时,如果需要过滤字符串中的笑脸,只需要创建一个类FaceFilter实现Filter接口,并在MsgProcessor类中的filters字段中登记即可。

第三种设计:责任链模式(FilterChain)

定义:将一个事件处理流程分派到一组执行对象上去,这一组执行对象形成一个链式结构,事件处理请求在这一组执行对象上进行传递。责任链模式的主要参与角色:

① 事件处理请求对象(Request)

② 执行对象(Handler)

责任链设计模式(过滤器、拦截器)1838

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
public class FilterChain implements Filter {
 
    public List<Filter> filters= new ArrayList<Filter>();
 
    public FilterChain addFilter(Filter f){
        filters.add(f);
        return this;
    }
 
    public String doFilter(String msg) {
//执行filters中的doFilter方法即可
        String r = msg;
        for(Filter f : filters){
            r = f.doFilter(r);
        }
        return r;
    }
}
 
public class MsgProcessor {
    private String msg;
    private FilterChain chain = new FilterChain();
 
    public MsgProcessor(String msg,Filter Chain){
        this.msg = msg;
        this.chain = chain;
    }
 
    public String process(){
        return chain.doFilter(msg);
    }
}
 
public class MainClass {
    public static void main(String[] args) {
        //需要被过滤的语句
        String msg = "被就业了:),敏感信息,<script>";
 
        //搞一个过过滤链
        FilterChain chain = new FilterChain();
        chain.addFilter(new HtmlFilter()).addFilter(new SensitiveFilter());
        //实例化处理类
        MsgProcessor mp = new MsgProcessor(msg,chain);
        String r = mp.process();
 
        System.out.println(r);
    }
}

责任链模式加强版

上面的实现的过滤链可以用下图a)表示出来,整个过程只对msg过滤了一次。而JavaWeb中的过滤器链和Struts2中的拦截器栈执行的过程可以形象的表示为图b,☆很重要)。

责任链设计模式(过滤器、拦截器)2890

下面用程序模拟JavaWeb中的过滤器,实现类似于对Request和Response的过滤。主要涉及的类如下所示:

责任链设计模式(过滤器、拦截器)2950

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
public interface Filter {
    void doFilter(Request req,Response resp,FilterChain chain);
}
 
public class HtmlFilter implements Filter {
    public void doFilter(Request req, Response resp, FilterChain chain) {
        //过滤req.reqStr中的HTML标记
        req.reqStr = req.reqStr.replace("<", "&lt;").replace(">", "&gt;");
        req.reqStr += "---HtmlFilter()---";
        chain.doFilter(req, resp);
        resp.respStr += "---HtmlFilter()---";
    }
}
 
public class SensitiveFilter implements Filter {
    public void doFilter(Request req, Response resp, FilterChain chain) {
        // 过滤req.reqStr中的敏感词
        req.reqStr = req.reqStr.replace("敏感", "").replace("被就业", "就业");
        req.reqStr += "===SensitiveFilter";
        chain.doFilter(req, resp);
        resp.respStr += "===SensitiveFilter";
    }
}
 
public class FilterChain{
    private List<Filter> filters = new ArrayList<Filter>();
    //调用链上的过滤器时,记录过滤器的位置用
    private int index = 0;
 
    public FilterChain addFilter(Filter f){
        filters.add(f);
        return this;
    }
 
    public void doFilter(Request req, Response resp) {
        if(index == filters.size()) return;
        //得到当前过滤器
        Filter f = filters.get(index);
        index++;
 
        f.doFilter(req, resp, this);
    }
}
 
public class Request {
    //在Request中只保持了一个reqStr字段记录对Request的操作
    //为了方便模拟,没有将reqStr设置为private
    String reqStr;
}
 
public class Response {
    //在Response中只保持了一个respStr字段记录对Response的操作
    //为了方便模拟,没有将respStr设置为private
    String respStr;
}
package org.flyne.fiter;
 
public class MainClass {
    public static void main(String[] args) {
        // 需要被过滤的语句
        String msg = "被就业了:),敏感信息,<script>";
 
        //创建Request、Response对象
        Request req = new Request();
        Response resp = new Response();
        req.reqStr = msg;
        resp.respStr = "response";
 
        //搞一个过滤链,链上有两个过滤器
        FilterChain chain = new FilterChain();
        chain.addFilter(new HtmlFilter())
            .addFilter(new SensitiveFilter());
 
        //开始过滤
        chain.doFilter(req, resp);
 
        System.out.println(req.reqStr);
        System.out.println(resp.respStr);
    }
}

转载于:https://www.cnblogs.com/Free-Thinker/p/4139306.html

你可能感兴趣的文章
VMware
查看>>
深入了解以太坊虚拟机第5部分——一个新合约被创建后会发生什么
查看>>
io多路复用
查看>>
Cache缓存
查看>>
objective-c基础
查看>>
NET中各种加密解密方法
查看>>
HTTP协议详解-基础知识
查看>>
activity-alias详解及应用
查看>>
[51单片机] SPI nRF24L01 无线简单程序 1
查看>>
[ucgui] 对话框4——模式消息窗口
查看>>
Android之XML序列化和解析
查看>>
YPBPR_PC下图像有毛刺或者水纹干扰的处理办法
查看>>
刷题向》关于一道奇怪的贪心(田忌赛马)BZOJ1034(NORMAL-)
查看>>
SDN第五次上机作业
查看>>
常用代码收藏
查看>>
设计模式(c#)代码总结
查看>>
POJ-Common Substrings(后缀数组-长度不小于 k 的公共子串的个数)
查看>>
Linux系统查看日志信息总结
查看>>
斐波那契数列
查看>>
Jpa规范中persistence.xml 配置文件解析
查看>>