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

责任链设计模式(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)


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,☆很重要)。

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


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);

    }

}

时间: 12-02

责任链设计模式(过滤器、拦截器)的相关文章

过滤器 拦截器 区别

转 http://www.cnblogs.com/wangyuyu/archive/2013/07/02/3167354.html 1.拦截器是基于java的反射机制的,而过滤器是基于函数回调 2.过滤器依赖与servlet容器,而拦截器不依赖与servlet容器 3.拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用 4.拦截器可以访问action上下文.值栈里的对象,而过滤器不能 5.在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次

Java设计模式之责任链设计模式

职责链模式(Chain of Responsibility):使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系,将所有处理对象连成一条链,并沿着这条链传递请求,直到有一个对象处理它为止. ? 请求传递方向:从低级到高级 ? 重点:如何形成这个责任链 ? 特点:发出处理请求的客户端并不知道是系统当中的哪一个对象最终处理这个请求,这样系统的更改可以在不影响客户端的情况下动态地重新组织和分配责任.1. 派生类中都具备的功能(1) 都要设置后继者(一样)(2) 都能实现自己职责范围

【JS设计模式】责任链设计模式的代码示例

责任链设计模式: 在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链.请求在这个链上传递,直到链上的某一个对象决定处理此请求.发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织和分配责任. 责任链模式涉及到的角色如下所示:● 抽象处理者(Handler)角色:定义出一个处理请求的接口.如果需要,接口可以定义 出一个方法以设定和返回对下家的引用.这个角色通常由一个Java抽象类或者Java接口实现.上图中Handle

PHP责任链设计模式

<?php //责任链设计模式 /** * 每个对象,储存着对自己上级的引用, * 如果自己处理不了,交给上一级. */ class board{ protected $power=1; protected $top='admin'; public function process($lev){ if($lev<=$this->power){ echo "版主删帖"; }else{ $top=new $this->top; $top->process($l

java责任链设计模式(功能链)

1.概述 网上讲述大部分责任链设计模式如下图,将责任链定义为:使多个对象都有机会处理同一个请求(下图中的数据),从而避免请求的发送者和接收者之间的耦合关系.将这些对象连成一条链(下图的A B C),并沿着这条链传递该请求,直到有一个对象处理它为止. 我所讲解的和这个不太一样,网上一般讲的是如果请求(数据)来了,对象A是否能处理?处理不了转为链条的一个对象B去处理,B处理不了则继续往下走,以此类推,并且只要有一个对象可以处理,就不会继续往下走了.比如A能处理,则处理之后就返回.我所讲的应该称为功能

JAVA责任链设计模式

<JAVA与模式>之责任链模式 在阎宏博士的<JAVA与模式>一书中开头是这样描述责任链(Chain of Responsibility)模式的: 责任链模式是一种对象的行为模式.在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链.请求在这个链上传递,直到链上的某一个对象决定处理此请求.发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织和分配责任. 从击鼓传花谈起 击鼓传花是一种热闹而又紧张的饮酒游戏

SpringBoot 过滤器, 拦截器, 监听器 对比及使用场景

1. 过滤器 (实现 javax.servlet.Filter 接口) ① 过滤器是在web应用启动的时候初始化一次, 在web应用停止的时候销毁. ② 可以对请求的URL进行过滤, 对敏感词过滤, ③ 挡在拦截器的外层 ④ Filter 是 Servlet 规范的一部分 2. 拦截器 (实现 org.springframework.web.servlet.HandlerInterceptor 接口) ① 不依赖Spring容器, 可以使用 Spring 容器管理的Bean ② 拦截器通过动态代

责任链或过滤器模式-使用过滤链

//过滤器接口 public interface Filter { public void doFilter(Request req,Response res,FilterChain c); } //客户端传递的内容到服务器 //模拟javaweb中的request public class Request { public String requestStr; } //服务器反馈的内容到客户端 //模拟javaweb中的response public class Response { publ

过滤器/拦截器/监听器 —— Filter、Interceptor、Listener

一.Filter的功能 filter功能,它使用户可以改变一个 request和修改一个response. Filter 不是一个servlet,它不能产生一个response,它能够在一个request到达servlet之前预处理request,也可以在离开 servlet时处理response.换种说法,filter其实是一个"servlet chaining"(servlet 链). 一个Filter包括: 1)在servlet被调用之前截获; 2)在servlet被调用之前检查