博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
责任链模式
阅读量:7114 次
发布时间:2019-06-28

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

简单介绍一下什么是责任链模式?

         如果您了解Servlet规范的话,一定会知道Filter;如果您使用过Struts2的话,一定清楚无处不在的interceptor。责任链模式顾名思义,对一个请求设计出一个链状的处理流程,处于链条上的每个类都可以处理这个请求,或者放弃对请求的处理然后交给链条上的下一个类。

如果你没有学过Filter或者interceptor,没关系,给出Filter的原理图你就会发现其实它们很简单

原理图:下面是没有使用Filter的web应用

 

下面是使用了Filter的web应用

 

 

         当客户端发出Web资源的请求时,Web服务器根据应用程序配置文件设置过滤规则进行检查,若客户请求满足过滤规则,则对客户请求/响应进行拦截,对请求头和请求数据检查或改动,并以此通过过滤器链,最后把请求/响应交给请求的Web资源处理。请求信息在过滤器链中可以被修改,也可以根据时间让请求不发往资源处理器,并直接向客户机发回一个响应。当资源处理器完成了对资源的处理后,响应信息将逐级逆向返回。同样在这个过程中,用户可以修改响应信息,从而完成一定的任务。 

实例:来源于马士兵老师的视频,这个实例简单地模拟了Servlet的Filter功能

案例1:实现了将Msg由客户端向服务器端的过滤,如下图清晰地解析了程序的执行过程

 

Main类:调用MsgProcessor类的process()方法完成对客户端信息的过滤处理

public class Main {    public static void main(String[] args) {        String msg = "大家好:),

MsgProcessor类:中间类,实际上是调用FilterChain的doFilter()方法

public class MsgProcessor {    private String msg;        //Filter[] filters = {new HTMLFilter(), new SesitiveFilter(), new FaceFilter()};    FilterChain fc;        public FilterChain getFc() {        return fc;    }    public void setFc(FilterChain fc) {        this.fc = fc;    }    public String getMsg() {        return msg;    }    public void setMsg(String msg) {        this.msg = msg;    }    public String process() {                        return fc.doFilter(msg);                    }}

定义接口类Filter

public interface Filter {    String doFilter(String str);}

3个具体实现上面接口的类

SesitiveFilter类

public class SesitiveFilter implements Filter {    @Override    public String doFilter(String str) {        //process the sensitive words        String r = str.replace("被就业", "就业")             .replace("敏感", "");                return r;    }}

FaceFilter类

public class FaceFilter implements Filter {    @Override    public String doFilter(String str) {        return str.replace(":)", "^V^");    }}

HTMLFilter类

public class HTMLFilter implements Filter {    @Override    public String doFilter(String str) {        //process the html tag <>        String r = str.replace('<', '[')                   .replace('>', ']');        return r;    }}

FilterChain类:完成对Filter类的批量处理 

import java.util.ArrayList;import java.util.List;public class FilterChain implements Filter {    List
filters = new ArrayList
(); public FilterChain addFilter(Filter f) { this.filters.add(f); return this; } public String doFilter(String str) { String r = str; for(Filter f: filters) { r = f.doFilter(r); } return r; }}

 

上面的案例只能实现单一方向的过滤,而实际上,在web应用中,客户端和服务器端的响应通常是这样的:

同一个Filter既对客户端发往服务器端的消息进行过滤处理,又对服务器端发往客户端的消息进行过滤处理。

案例2:如下图清晰地解析了程序的执行过程

                               A                 B              C

现在就真正在模拟Servlet的Filter功能或Struts的Intecerpter功能了,这里我们用Request对象封装客户端的请求信息,用Response对象封装服务器端反馈回来的信息

因为Filter是在FilterChain中,信息的过滤处理类似于栈的结构,比如在客户端往服务器端处理的过程中,是排在前面A的Filter先处理,排在后面的c后处理;而在服务器端往客户端处理过程中,是排在后面的C先处理,排在前面的A后处理,怎么处理呢?

可以这样考虑:将FilterChain的引用传递给Filter,因为FilterChain中包含了排列好了的Filter,若是信息被过滤器A执行处理,将获得FilterChain对象,信息将会按照FilterChain中的Filter的顺序执行下去

Request对象:封装客户端发送的信息

public class Request {    String requestStr;    public String getRequestStr() {        return requestStr;    }    public void setRequestStr(String requestStr) {        this.requestStr = requestStr;    }}

Response对象:封装服务器端反馈的信息

public class Response {    String responseStr;    public String getResponseStr() {        return responseStr;    }    public void setResponseStr(String responseStr) {        this.responseStr = responseStr;    }    }

接口类: Filter

public interface Filter {    void doFilter(Request request, Response response, FilterChain chain);}

实现上述接口的两个类:

SesstiveFilter:处理敏感信息 

public class SesitiveFilter implements Filter {    @Override    public void doFilter(Request request, Response response, FilterChain chain) {        request.requestStr = request.requestStr.replace("被就业", "就业")         .replace("敏感", "") + "---SesitiveFilter()";        chain.doFilter(request, response, chain);        response.responseStr += "---SesitiveFilter()";    }        } 

HTMLFilter:处理HTML标签

public class HTMLFilter implements Filter {    @Override    public void doFilter(Request request, Response response, FilterChain chain) {        //process the html tag <>        request.requestStr = request.requestStr.replace('<', '[')                   .replace('>', ']') + "---HTMLFilter()";        chain.doFilter(request, response, chain);        response.responseStr += "---HTMLFilter()";    }}

FilterChain:下面的着红色的代码解决了Response对象逆向被Filter处理

public class FilterChain implements Filter {    List
filters = new ArrayList
(); int index = 0; public FilterChain addFilter(Filter f) { this.filters.add(f); return this; } @Override public void doFilter(Request request, Response response, FilterChain chain) { if(index == filters.size()) return ; Filter f = filters.get(index); index ++; f.doFilter(request, response, chain); }}

测试代码:

public class Main {    /**     * 模拟Servlet中Request和Response的调用过程     */    public static void main(String[] args) {        String msg = "大家好:),

下面是测试结果:

大家好:),[script],,就业,网络授课没感觉,因为看不见大家伙儿---HTMLFilter()---SesitiveFilter()response---SesitiveFilter()---HTMLFilter()

转载地址:http://uqghl.baihongyu.com/

你可能感兴趣的文章
Servlet的Listener的使用
查看>>
Handler学习小结
查看>>
HEVC算法和体系结构:编码结构之编码时的分层处理架构
查看>>
Kettle定时执行
查看>>
泛函编程(14)-try to map them all
查看>>
使用meta实现页面的定时刷新或跳转
查看>>
[华为机试练习题]3.分解字符串
查看>>
2018.03.08、View的事件分发机制笔记
查看>>
使用工具类DbUtils连接数据库,并简单操作数据库
查看>>
vue/cli3+最全生产环境优化方法
查看>>
(译)使用Spring Boot和Axon实现CQRS&Event Sourcing
查看>>
微软整合实验(四):迁移FSMO操作主机角色,基于Server 2008 R2
查看>>
Cisco IPSec_×××详细配置
查看>>
我的友情链接
查看>>
git 修改账号密码
查看>>
2017 未来架构师<设计思考> 翻转式课堂
查看>>
eNSP园区网络结构图配置
查看>>
Windows 8 数学输入板
查看>>
PHP网站开发工程师的职业发展规划与技能条件
查看>>
我的友情链接
查看>>