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控制台输出:

  

 

posted on 2022-03-04 00:05  花溪月影  阅读(24)  评论(0编辑  收藏  举报