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