zoukankan      html  css  js  c++  java
  • 责任链模式

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

             如果您了解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 = "大家好:),<script>,敏感,被就业,网络授课没感觉,因为看不见大家伙儿";
            MsgProcessor mp = new MsgProcessor();
            mp.setMsg(msg);
            FilterChain fc = new FilterChain();
            fc.addFilter(new HTMLFilter())
              .addFilter(new SesitiveFilter())
              ;
            FilterChain fc2 = new FilterChain();
            fc2.addFilter(new FaceFilter());
            
            fc.addFilter(fc2);
            mp.setFc(fc);
            String result = mp.process();
            System.out.println(result);
        }
    
    }

    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<Filter> filters = new ArrayList<Filter>();
        
        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<Filter> filters = new ArrayList<Filter>();
        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>,敏感,被就业,网络授课没感觉,因为看不见大家伙儿";
            Request request = new Request();
            request.setRequestStr(msg);
            Response response = new Response();
            response.setResponseStr("response");
            FilterChain fc = new FilterChain();
            fc.addFilter(new HTMLFilter())
              .addFilter(new SesitiveFilter())
              ;
            
            fc.doFilter(request, response, fc);
            System.out.println(request.getRequestStr());
            System.out.println(response.getResponseStr());
        }
    
    }

    下面是测试结果:

    大家好:),[script],,就业,网络授课没感觉,因为看不见大家伙儿---HTMLFilter()---SesitiveFilter()
    response---SesitiveFilter()---HTMLFilter()
  • 相关阅读:
    8086汇编 学习1
    微信小程序 websocket+node.js(ws)
    kali安装google 浏览器
    bugkuctf Easy_Re
    课设记录-Day06
    GitLab使用教程
    课设记录-Day05
    课设记录-Day04
    课设记录-Day03
    课设记录-Day02
  • 原文地址:https://www.cnblogs.com/ITtangtang/p/2476881.html
Copyright © 2011-2022 走看看