JavaWeb之动态代理解决request请求编码问题

动态代理解决编码问题

1.设计模式

出现原因:软件开发过程中,遇到相似问题,将问题的解决方法抽取模型(套路)

常见设计模式:单例,工厂,适配器,装饰者,动态代理。

2.装饰者模式简单介绍

谷歌汽车开发场景

1.Java定义了汽车开发约定

1interface ICar{start , run , stop} 2calss GooleCar implements ICar{}

2.目的:将谷歌Car接入导生态平台时,增强汽车功能

3.问题:谷歌Car的代码无法获取,且无法继承,不能直接操作其源码

装饰者模式

场景:在二次开发时,无法获取源码,且不能被继承的情况下,对以存在对象上的功能进行增强。

前提:可以获取被装饰的对象的所有实现接口

实现思路:自定义对象继承被装饰对象的接口,为自定义装饰类传递被装饰的对象

装饰者模式的弊端

如果被实现的接口中方法过的,则其所有方法都要被重写,装饰类会显得冗杂。

3.动态代理

解决装饰者模式的弊端

a.原理

通过虚拟机在内存创建类似MyCar.Class文件

要创建MyCar.Class文件来告诉虚拟机:

​ 1.被创建的字节码文件上需要哪些方法

字节码加载器

jdk有一些程序专业将各种字节码文件加载到内存,这类程序称为字节码加载器

如何将字节码文件class文件加载到内存?

底层提供IO技术,获取文件中的数据加载到内存。

字节码加载器有3种

1public class TestClassLoader { 2 public static void main(String[] args) { 3 4 //获取String类的加载器 5 ClassLoader classLoader = String.class.getClassLoader(); 6 System.out.println(classLoader); 7 //由于String.class ,int.class等字节码文件需要频繁的被加载内存,速度必须快,底层用其他语言来实现c c++ 8 9 //获取ext(extendtion)包下的某个类的字节码加载器 ExtClassLoader:扩展类加载器 10 ClassLoader classLoader2 = sun.net.spi.nameservice.dns.DNSNameService.class.getClassLoader(); 11 System.out.println(classLoader2); 12 13 //应用类:程序员实现的所有的类都属于应用类 14 //获取应用类加载器 AppClassLoader 15 ClassLoader classLoader3 = TestClassLoader.class.getClassLoader(); 16 System.out.println(classLoader3); 17 } 18}

动态代理简单案例

1import java.lang.reflect.InvocationHandler; 2import java.lang.reflect.Method; 3import java.lang.reflect.Proxy; 4import java.util.Arrays; 5 6public class TestCar { 7 public static void main(String[] args) { 8 9 //1param: 固定值: 告诉虚拟机用哪个字节码加载器加载内存中创建出的字节码文件 10 //2param: 告诉虚拟机内存中正在被创建的字节码文件中应该有哪些方法 11 //3param: 告诉虚拟机正在被创建的字节码上的各个方法如何处理 12 ICar car=(ICar)Proxy.newProxyInstance(TestCar.class.getClassLoader(), GoogleCar.class.getInterfaces(),new InvocationHandler() { 13 14 //method:代表正在执行的方法 15 //args:代表正在执行的方法中的参数 16 //Object:代表方法执行完毕之后的返回值 17 @Override 18 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 19 //经过测试得知:method代表当前正在执行的每个方法 20 //System.out.println(method.getName()); 21 //执行当前的方法 22 //method.invoke(new GoogleCar(), args); 23 24 //代表每个方法执行完毕之后返回对象 25 Object obj=null; 26 27 if(method.getName().equalsIgnoreCase("start")){ 28 System.out.println("检查天气是否良好"); 29 30 //打印args中的内容 31 System.out.println(Arrays.toString(args)); 32 33 obj=method.invoke(new GoogleCar(), args); 34 System.out.println("检查路况是否拥堵"); 35 36 }else{ 37 obj=method.invoke(new GoogleCar(), args); 38 } 39 return obj; 40 } 41 }); 42 String cc=car.start(1,4); 43 System.out.println(cc); 44 car.run(); 45 car.stop(); 46 } 47} 48 49class MyCC implements InvocationHandler{ 50 @Override 51 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 52 return null; 53 } 54}

动态代理解决servlet的get请求的中文编码问题

1import java.io.IOException; 2import java.lang.reflect.InvocationHandler; 3import java.lang.reflect.Method; 4import java.lang.reflect.Proxy; 5 6import javax.servlet.Filter; 7import javax.servlet.FilterChain; 8import javax.servlet.FilterConfig; 9import javax.servlet.ServletException; 10import javax.servlet.ServletRequest; 11import javax.servlet.ServletResponse; 12import javax.servlet.http.HttpServletRequest; 13 14public class EncodingFilter implements Filter { 15 16 public EncodingFilter() { 17 } 18 19 public void destroy() { 20 } 21 public void init(FilterConfig fConfig) throws ServletException { 22 } 23 24 25 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { 26 //将request对象转换为HttpServletRequest 27 final HttpServletRequest req=(HttpServletRequest)request; 28 //让JDK在内存中生成代理对象:增强了req对象上的getParameter(name);API 29 HttpServletRequest myReq=(HttpServletRequest)Proxy.newProxyInstance(EncodingFilter.class.getClassLoader(), req.getClass().getInterfaces(), new InvocationHandler() { 30 31 @Override 32 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 33 34 Object obj=null; 35 36 if(method.getName().equalsIgnoreCase("getParameter")){ 37 //获取本次请求方式 38 String md=req.getMethod(); 39 if("get".equalsIgnoreCase(md)){ 40 //get方式的请求 41 //调用req对象上的getParameter方法 42 String v=(String)method.invoke(req, args); 43 //转码 44 String vv=new String(v.getBytes("iso-8859-1"),"utf-8"); 45 return vv; 46 47 }else{ 48 //post方式的请求 49 req.setCharacterEncoding("utf-8"); 50 obj=method.invoke(req, args); 51 } 52 53 54 }else{ 55 obj=method.invoke(req, args); 56 } 57 return obj; 58 } 59 }); 60 //打印代理对象哈希码 61 System.out.println(myReq.hashCode()); 62 //将代理对象放行 63 chain.doFilter(myReq, response); 64 } 65}
点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

KVM调整cpu和内存

一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid

JavaWeb之动态代理解决request请求编码问题 - HelloWorld