zoukankan      html  css  js  c++  java
  • 模拟实现Tomcat过滤器链,Struts2拦截器链-设计模式之责任链模式(任务链模式)

    模拟实现Tomcat过滤器链,Struts2拦截器链-设计模式之责任链模式(任务链模式)

    在javaWeb项目中,大家应该经常会用到这样的代码;

    Sevlet  Filter

    下方代码作用:用于过滤请求,修改Request对象和Response对象的编码

    public void doFilter(ServletRequest arg0, ServletResponse arg1,
    FilterChain arg2) throws IOException, ServletException {
    
            HttpServletRequest req=(HttpServletRequest) arg0;
            HttpServletResponse resp=(HttpServletResponse) arg1;
            req.setCharacterEncoding("utf-8");
            resp.setCharacterEncoding("utf-8");
            resp.setContentType("text/html;charset=UTF-8");
            arg2.doFilter(req, resp);
    }

    Struts2 拦截器

    下方代码作用:用于实现自定义拦截器功能,实现最为普遍的登陆验证。

     protected String doIntercept(ActionInvocation invocation) throws Exception {
             //获取session对象(经过struts2包装过)
             Map session = ActionContext.getContext().getSession();
             //获取session作用域内是否有值
             Users user = (Users) session.get("user");
             if(user!=null){//合法访问
                 return invocation.invoke();
             }else{//user为空说明未经过登陆,保存错误提示信息,跳到登陆页面
                 ActionContext.getContext().put("noright", "请先登陆再进行操作!");
                 return Action.LOGIN;
             }
         }

    当我们使用多个Filter和 Interceptor时,就会组成一个任务链,什么是任务链呢?  

    过滤器链——FilterChain的执行流程

    组过滤器对某些web资源进行拦截,那么这组过滤器就称为过滤器链。过滤器的执行顺序和<filter-mapping>有关(谁在前先执行谁)。

    那么我们怎么模拟一个这样的功能呢?

     下面我们就用代码简单的模拟一下Sevlet中的FilterChain

    项目文件

    其中myfilter下的各种filter都实现了Filter接口的doFilter方法,模拟web项目中自定义的Filter对象

    下面展示各部分代码:

    --------------------------------------------------------------------------------------------关键代码开始----------------------------------------------------------------------------------------

    Filter.java

    package com.bigfire.chain;
    
    /*
    时间:2019年2月26日    10点47分
    内容:设计模式--责任链模式
    作者:大火yzs
    */
    //定义接口模拟javax.servlet.Filter接口
    public interface Filter {
        void doFilter(Request req,Response res,FilterChain chain);
    }

    Tomcat.java

    package com.bigfire.chain;
    
    import com.bigfire.chain.myfilter.CORSFilter;
    import com.bigfire.chain.myfilter.LoginFilter;
    import com.bigfire.chain.myfilter.URLEcodeFilter;
    import com.bigfire.chain.myfilter.UTF8Filter;
    
    /*
    时间:2019年2月26日    10点47分
    内容:设计模式--责任链模式
    作者:大火yzs
    */
    //定义类模拟Tomcat容器,产生一些对象。
    public class Tomcat {
    
        public static void main(String[] args) {
            Request req = new Request("RequestMsg");//模拟Tomcat产生Request对象
            Response res = new Response("ResponseMsg");//模拟Tomcat产生Response对象
            
            FilterChain chain1 = new FilterChain();//创建任务链1
            FilterChain chain2 = new FilterChain();//创建任务链2
    
            chain2.addFilter(new UTF8Filter())    //在任务链2中添加UTF-8过滤器
            .addFilter(new URLEcodeFilter())    //在任务链2中添加URLEcode过滤器
            .addFilter(new URLEcodeFilter());    //在任务链2中添加URLEcode过滤器
            
            chain1.addFilter(new CORSFilter())    //在任务链1中添加跨域过滤器
            .addFilter(chain2)                    //在任务链1中添加任务链2
            .addFilter(new LoginFilter());        //在任务链1中添加登陆过滤器
    
            
            chain1.doFilter(req, res, chain1);    //执行任务链1
            
            System.out.println(req.msg);        //输出过滤后的结果
            System.out.println(res.msg);        //输出过滤后的结果
        }
    
    }

    Request

    package com.bigfire.chain;
    /*
    时间:2019年2月26日    10点47分
    内容:设计模式--责任链模式
    作者:大火yzs
    */
    //定义类模拟javax.servlet.ServletRequest类
    public class Request {
        public String msg;//模拟Request中的消息
        public Request() {}
        public Request(String msg) {
            this.msg = msg;
        }
    }

    Res

    package com.bigfire.chain;
    /*
    时间:2019年2月26日    10点47分
    内容:设计模式--责任链模式
    作者:大火yzs
    */
    //定义类模拟javax.servlet.ServletResponse类
    public class Response {
        public String msg;//模拟Response中的消息
        public Response() {}
        public Response(String msg) {
            this.msg = msg;
        }
    }

    FilterChain.java

    package com.bigfire.chain;
    
    import java.util.ArrayList;
    import java.util.List;
    /*
    时间:2019年2月26日    10点47分
    内容:设计模式--责任链模式
    作者:大火yzs
    */
    /*
         定义类模拟javax.servlet.FilterChain类
        过滤器链核心类
    */
    public class FilterChain implements Filter{//实现Filter接口
        
        List<Filter> list = new ArrayList<Filter>();//存放过滤器的集合
        int index = 0;//计数器
        public int layer = 0;//责任链进入的层数
        @Override
        public void doFilter(Request req, Response res, FilterChain chain) {
            
            if (index == list.size()) return;//如果已经冲到list的结尾了就返回
            Filter filter = list.get(index);//没有到结尾就拿一个filter;
            index++;//自增
            filter.doFilter(req, res, chain);//往里执行
        }
        //用于添加过滤器,返回值是本对象,方便链式添加
        public FilterChain addFilter(Filter filter) {
            if (filter instanceof FilterChain) {//添加的时候判断添加的是否是责任链
                List<Filter> temlist=((FilterChain) filter).list;//获取子链中的Filter放到主链容器中
                for (Filter filter2 : temlist) {
                    this.list.add(filter2);
                }
            }else    this.list.add(filter);//普通过滤器添加
            return this;
        }
    }

    --------------------------------------------------------------------------------------------关键代码结束----------------------------------------------------------------------------------------

    myfilter包下的过滤器

    --------------------------------------------------------------------------------------------自定义过滤器代码开始----------------------------------------------------------------------------------------

    CORSFilter.java

    package com.bigfire.chain.myfilter;
    
    import com.bigfire.chain.Filter;
    import com.bigfire.chain.FilterChain;
    import com.bigfire.chain.Request;
    import com.bigfire.chain.Response;
    /*
    时间:2019年2月26日    10点47分
    内容:设计模式--责任链模式
    作者:大火yzs
    */
    //定义过滤器用于解决跨域问题
    public class CORSFilter implements Filter{
        @Override
        public void doFilter(Request req, Response res, FilterChain chain) {
            System.out.println(chain.layer++);
            req.msg+="--跨域--";
            chain.doFilter(req, res, chain);
            System.out.println(--chain.layer);
            res.msg+="--跨域--";
        }
    }

    LoginFilter.java

    package com.bigfire.chain.myfilter;
    
    import com.bigfire.chain.Filter;
    import com.bigfire.chain.FilterChain;
    import com.bigfire.chain.Request;
    import com.bigfire.chain.Response;
    /*
    时间:2019年2月26日    10点47分
    内容:设计模式--责任链模式
    作者:大火yzs
    */
    //定义过滤器用于验证账号密码,过滤一些敏感词。
    public class LoginFilter implements Filter{
    
        @Override
        public void doFilter(Request req, Response res, FilterChain chain) {
            System.out.println(chain.layer++);
            req.msg+="--登陆--";
            chain.doFilter(req, res, chain);
            System.out.println(--chain.layer);
            res.msg+="--登陆--";
        }
    }

    URLEcodeFilter.java

    package com.bigfire.chain.myfilter;
    
    import com.bigfire.chain.Filter;
    import com.bigfire.chain.FilterChain;
    import com.bigfire.chain.Request;
    import com.bigfire.chain.Response;
    /*
    时间:2019年2月26日    10点47分
    内容:设计模式--责任链模式
    作者:大火yzs
    */
    //定义过滤器用于URL编码
    public class URLEcodeFilter implements Filter{
        @Override
        public void doFilter(Request req, Response res, FilterChain chain) {
            System.out.println(chain.layer++);
            req.msg+="--URLEcode--";
            chain.doFilter(req, res, chain);
            System.out.println(--chain.layer);
            res.msg+="--URLEcode--";
        }
    }

    UTF8Filter.java

    package com.bigfire.chain.myfilter;
    
    import com.bigfire.chain.Filter;
    import com.bigfire.chain.FilterChain;
    import com.bigfire.chain.Request;
    import com.bigfire.chain.Response;
    /*
    时间:2019年2月26日    10点47分
    内容:设计模式--责任链模式
    作者:大火yzs
    */
    //定义过滤器用于修改请求的编码方式为UTF-8。
    public class UTF8Filter implements Filter{
        @Override
        public void doFilter(Request req, Response res, FilterChain chain) {
            System.out.println(chain.layer++);
            req.msg+="--UTF8--";
            chain.doFilter(req, res, chain);
            System.out.println(--chain.layer);
            res.msg+="--UTF8--";
        }
    }

    --------------------------------------------------------------------------------------------自定义过滤器代码结束----------------------------------------------------------------------------------------

     运行结果:

    0    //任务链第0层
    1
    2
    3
    4    //任务链第4层 
    4
    3
    2
    1
    0
    RequestMsg--跨域----UTF8----URLEcode----URLEcode----登陆--
    ResponseMsg--登陆----URLEcode----URLEcode----UTF8----跨域--

     任务链的这种结构和栈的结构十分相似。

  • 相关阅读:
    iOS遍历程序内某个文件夹下所有文件的属性
    CATransition 转场动画
    Xcode安装的推送证书所在目录
    UIMenuController 实现长按显示自定义菜单功能
    ios调用第三方程序打开文件,以及第三方调用自己的APP打开文件
    购物车界面,不同section,点击增减物品,确定取消选中的逻辑判断
    iOS UINavigationController
    iOS9 URL Schme 白名单
    iOS9 HTTPS
    iOS9 后台定位
  • 原文地址:https://www.cnblogs.com/bigfire/p/10442442.html
Copyright © 2011-2022 走看看