• Filter&Listener11_动态代理2


    1. 增强对象的功能:

        设计模式:一些通用的解决固定问题的方式

        1. 装饰模式:动态地给一个对象添加一些额外的职责。就增加功能来说,Decorator模式相比生成子类更为灵活。

        2. 代理模块:为其他对象提供一种代理以控制对这个对象的访问。

    2. 动态模块概念

      

      1.真实对象:被代理的对象(联想公司)

      2.代理对象:西安联想代理商

      3.代理模式:代理对象代理真实对象,达到增强真实对象功能的目的。

    3. 代理模式实现方式

      1.静态代理:由一个类文件描述代理模式

      2.动态代理:在内存中形成代理类

    4. 动态代理实现步骤

      1. 代理对象和真实对象实现相同的接口

      2. 代理对象 = Proxy.newProxyInstance(真实对象.getClass().getClassLoader(), 真实对象.getClass().getInterfaces(), new InvocationHandler(){ });

      3. 使用代理对象调用方法

      4. 增强方法

    5. 动态代理增强方式

      1. 增强参数列表

      2. 增强返回值类型

      3. 增强方法体执行逻辑

    6. 代码1

      代理对象

    package cn.itcast.proxy;
    
    public interface SaleComputer {
    
        public String sale(double money);
    
        public void show();
    
    }
    package cn.itcast.proxy;
    
    /**
     * 真实类
     */
    public class Lenovo implements SaleComputer{
    
    
        @Override
        public String sale(double money) {
            System.out.println("花了"+money+"元买了一台联想电脑...");
            return "联想电脑";
        }
    
        @Override
        public void show() {
            System.out.println("展示电脑...");
        }
    }
    package cn.itcast.proxy;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    public class ProxyTest {
    
        public static void main(String[] args) {
            //1.创建真实对象
            Lenovo lenovo = new Lenovo();
    
            //2. 动态代理增强Lenovo对象
            /*
                三个参数:
                    1.类加载器:真实对象.getClass().getClassLoader()
                    2.接口数组:真实对象.getClass().getInterfaces()
                    3.处理器:new InvocationHandler() 核心业务逻辑处理
             */
            SaleComputer proxy_lenovo = (SaleComputer) Proxy.newProxyInstance(lenovo.getClass().getClassLoader(), lenovo.getClass().getInterfaces(), new InvocationHandler() {
                /*
                    代理逻辑编写的方法:代理对象调用的所有方法都会触发该方法执行
                        三个参数:
                            1.proxy:代理对象,指的就是proxy_lenovo,一般不用
                            2.method:代理对象调用的方法,被封装为的对象。即proxy_lenovo.show()中的show方法会被封装到Method对象中。
                            3.args:代理对象调用方法时,传递的实际参数
                 */
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    System.out.println("该方法执行了...");
                    System.out.println(method.getName());
                    System.out.println(args[0]);
    
    
                    return null;
                }
            });
    
            //3. 调用方法
            String computer = proxy_lenovo.sale(8000);
            System.out.println(computer);
    
    //       proxy_lenovo.show();
        }
    }

      执行,检查idea控制台输出:

      

     7. 代码2:

      使用代理对象调用方法

    package cn.itcast.proxy;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    public class ProxyTest {
    
        public static void main(String[] args) {
            //1.创建真实对象
            Lenovo lenovo = new Lenovo();
    
            //2. 动态代理增强Lenovo对象
            /*
                三个参数:
                    1.类加载器:真实对象.getClass().getClassLoader()
                    2.接口数组:真实对象.getClass().getInterfaces()
                    3.处理器:new InvocationHandler() 核心业务逻辑处理
             */
            SaleComputer proxy_lenovo = (SaleComputer) Proxy.newProxyInstance(lenovo.getClass().getClassLoader(), lenovo.getClass().getInterfaces(), new InvocationHandler() {
                /*
                    代理逻辑编写的方法:代理对象调用的所有方法都会触发该方法执行
                        三个参数:
                            1.proxy:代理对象,指的就是proxy_lenovo,一般不用
                            2.method:代理对象调用的方法,被封装为的对象。即proxy_lenovo.show()中的show方法会被封装到Method对象中。
                            3.args:代理对象调用方法时,传递的实际参数
                 */
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
                    //使用真实对象调用该方法
                    Object obj = method.invoke(lenovo, args);
    
                    return obj;//若为return null;则不会输出:联想电脑
                }
            });
    
            //3. 调用方法
            String computer = proxy_lenovo.sale(8000);
            System.out.println(computer);
    
           //proxy_lenovo.show();
        }
    }

      执行,检查idea控制台输出:

      

     8. 增强参数

    package cn.itcast.proxy;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    public class ProxyTest {
    
        public static void main(String[] args) {
            //1.创建真实对象
            Lenovo lenovo = new Lenovo();
    
            //2. 动态代理增强Lenovo对象
            /*
                三个参数:
                    1.类加载器:真实对象.getClass().getClassLoader()
                    2.接口数组:真实对象.getClass().getInterfaces()
                    3.处理器:new InvocationHandler() 核心业务逻辑处理
             */
            SaleComputer proxy_lenovo = (SaleComputer) Proxy.newProxyInstance(lenovo.getClass().getClassLoader(), lenovo.getClass().getInterfaces(), new InvocationHandler() {
                /*
                    代理逻辑编写的方法:代理对象调用的所有方法都会触发该方法执行
                        三个参数:
                            1.proxy:代理对象,指的就是proxy_lenovo,一般不用
                            2.method:代理对象调用的方法,被封装为的对象。即proxy_lenovo.show()中的show方法会被封装到Method对象中。
                            3.args:代理对象调用方法时,传递的实际参数
                 */
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    /*
    
                    System.out.println("该方法执行了...");
                    System.out.println(method.getName());
                    System.out.println(args[0]);
    */
    
                    //1. 增强参数
                    //判断是否是sale方法
                    if(method.getName().equals("sale")){
                        //1.增强参数
                        double money = (double) args[0];
                        money = money * 0.85;
                        //使用真实对象调用该方法
                        Object obj = method.invoke(lenovo, money);
                        return obj;
                    }else {
                        Object obj = method.invoke(lenovo, args);
                        return obj;
                    }
    
                }
            });
    
            //3. 调用方法
            String computer = proxy_lenovo.sale(8000);
            System.out.println(computer);
    
           proxy_lenovo.show();
        }
    }

      执行检查idea控制台输出:

      

     9. 增加返回值

    package cn.itcast.proxy;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    public class ProxyTest {
    
        public static void main(String[] args) {
            //1.创建真实对象
            Lenovo lenovo = new Lenovo();
    
            //2. 动态代理增强Lenovo对象
            /*
                三个参数:
                    1.类加载器:真实对象.getClass().getClassLoader()
                    2.接口数组:真实对象.getClass().getInterfaces()
                    3.处理器:new InvocationHandler() 核心业务逻辑处理
             */
            SaleComputer proxy_lenovo = (SaleComputer) Proxy.newProxyInstance(lenovo.getClass().getClassLoader(), lenovo.getClass().getInterfaces(), new InvocationHandler() {
                /*
                    代理逻辑编写的方法:代理对象调用的所有方法都会触发该方法执行
                        三个参数:
                            1.proxy:代理对象,指的就是proxy_lenovo,一般不用
                            2.method:代理对象调用的方法,被封装为的对象。即proxy_lenovo.show()中的show方法会被封装到Method对象中。
                            3.args:代理对象调用方法时,传递的实际参数
                 */
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    /*
    
                    System.out.println("该方法执行了...");
                    System.out.println(method.getName());
                    System.out.println(args[0]);
    */
    
                    //1. 增强参数
                    //判断是否是sale方法
                    if(method.getName().equals("sale")){
                        //1.增强参数
                        double money = (double) args[0];
                        money = money * 0.85;
                        //使用真实对象调用该方法
                        String obj = (String) method.invoke(lenovo, money);
                        //2.增加返回值
                        return obj+"_鼠标垫";
                    }else {
                        Object obj = method.invoke(lenovo, args);
                        return obj;
                    }
    
                }
            });
    
            //3. 调用方法
            String computer = proxy_lenovo.sale(8000);
            System.out.println(computer);
    
    //       proxy_lenovo.show();
        }
    }

      执行,检查idea控制台输出结果:

      

     10. 增强方法体

    package cn.itcast.proxy;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    public class ProxyTest {
    
        public static void main(String[] args) {
            //1.创建真实对象
            Lenovo lenovo = new Lenovo();
    
            //2. 动态代理增强Lenovo对象
            /*
                三个参数:
                    1.类加载器:真实对象.getClass().getClassLoader()
                    2.接口数组:真实对象.getClass().getInterfaces()
                    3.处理器:new InvocationHandler() 核心业务逻辑处理
             */
            SaleComputer proxy_lenovo = (SaleComputer) Proxy.newProxyInstance(lenovo.getClass().getClassLoader(), lenovo.getClass().getInterfaces(), new InvocationHandler() {
                /*
                    代理逻辑编写的方法:代理对象调用的所有方法都会触发该方法执行
                        三个参数:
                            1.proxy:代理对象,指的就是proxy_lenovo,一般不用
                            2.method:代理对象调用的方法,被封装为的对象。即proxy_lenovo.show()中的show方法会被封装到Method对象中。
                            3.args:代理对象调用方法时,传递的实际参数
                 */
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    /*
    
                    System.out.println("该方法执行了...");
                    System.out.println(method.getName());
                    System.out.println(args[0]);
    */
    
                    //1. 增强参数
                    //判断是否是sale方法
                    if(method.getName().equals("sale")){
                        //1.增强参数
                        double money = (double) args[0];
                        money = money * 0.85;
                        System.out.println("专车接你...");
                        //使用真实对象调用该方法
                        String obj = (String) method.invoke(lenovo, money);
                        System.out.println("免费送货...");
                        //2.增加返回值
                        return obj+"_鼠标垫";
                    }else {
                        Object obj = method.invoke(lenovo, args);
                        return obj;
                    }
    
                }
            });
    
            //3. 调用方法
            String computer = proxy_lenovo.sale(8000);
            System.out.println(computer);
    
    //       proxy_lenovo.show();
        }
    }

      执行,检查idea控制台输出结果:

      

    11. 案例:敏感词汇过滤

      需求:

        1. 对day10_case案例录入的数据进行敏感词汇过滤

        2. 敏感词汇参考《敏感词汇.txt》

        3. 如果是敏感词汇,替换为 ***

      分析:

        1. 对request对象进行增强。增强获取参数相关方法

        2. 放行。传递代理对象

        

      实现:

    package cn.itcast.web.filter;
    
    import javax.servlet.*;
    import javax.servlet.annotation.WebFilter;
    import java.io.BufferedReader;
    import java.io.FileNotFoundException;
    import java.io.FileReader;
    import java.io.IOException;
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    import java.util.ArrayList;
    import java.util.List;
    
    @WebFilter("/*")
    public class SensitiveWordsFilter implements Filter {
        public void destroy() {
        }
    
        public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
    
            //1. 创建代理对象,增强getParameter方法
            ServletRequest proxy_req = (ServletRequest) Proxy.newProxyInstance(req.getClass().getClassLoader(), req.getClass().getInterfaces(), new InvocationHandler() {
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    //增强getParameter方法
                    //判断是否是getParameter方法
                    if(method.getName().equals("getParameter")){
                        //增强返回值
                        //获取返回值
                        String value = (String) method.invoke(req, args);
                        if(value != null){
                            for (String str : list) {
                                if(value.contains(str)){
                                    value = value.replaceAll(str,"***");
                                }
                            }
                        }
                        return value;
                    }
                    //判断方法名是否是getParameterMap,因为这种方法也可以获取参数值,所以也要完成替换的动作
    
                    //判断方法名是否是getParameterValue
    
                    return method.invoke(req,args);
                }
            });
    
            //2. 放行
            chain.doFilter(proxy_req, resp);
        }
    
        private List<String> list = new ArrayList<String>();//敏感词汇集合
    
        public void init(FilterConfig config) throws ServletException {
            //1.获取文件真实路径
            ServletContext servletContext = config.getServletContext();
            String realPath = servletContext.getRealPath("/WEB-INF/classes/敏感词汇.txt");
    
            //2.读取文件
            try {
                BufferedReader br = new BufferedReader(new FileReader(realPath));
                String line = null;
                while ((line = br.readLine())!= null){
                    list.add(line);
                }
                br.close();
    
                System.out.println(list);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
    
            //3.将文件的每一行数据添加到list中
        }
    
    }
    package cn.itcast.web.servlet;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    @WebServlet("/testServlet")
    public class TestServlet extends HttpServlet {
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            String name = request.getParameter("name");
            String msg = request.getParameter("msg");
    
            System.out.println(name+":"+msg);
        }
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            this.doPost(request, response);
        }
    }

      浏览器访问http://localhost/day11/testServlet?name=张三&msg=你个笨蛋,你个大坏蛋,检查idea控制台输出:

      

  • 相关阅读:
    std::bind 详解及参数解析
    c++ 静态类成员函数(static member function) vs 名字空间 (namespace)
    继续进发
    lua闭包
    Mysql按时间段分组查询来统计会员的个数
    linux安装配置sendmail实现邮件发送
    Javascript验证用户输入URL地址是否正确
    php返回json数据函数例子
    ArrayList与List对象用法与区别
    java 获取数组(二维数组)长度实例程序
  • 原文地址:https://www.cnblogs.com/ajing2018/p/15962606.html
Copyright © 2020-2023  润新知