java使用动态代理Proxy.newProxyInstance,模拟谷歌汽车的场景:(装饰着模式),(装饰着模式)弊端,类加载器的介绍,使用动态代理解决网站的字符集编码问题

news/2024/5/14 5:46:05/文章来源:https://code100.blog.csdn.net/article/details/104608534

java使用动态代理Proxy.newProxyInstance,模拟谷歌汽车的场景:(装饰着模式),(装饰着模式)弊端,类加载器的介绍,使用动态代理解决网站的字符集编码问题

设计模式:

什么是设计模式,简单的来说,就是在软件开发当中遇到的一些相似问题,将问题的解决方式抽取出的模型(开发套路 ),来解决软件开发当中遇到的问题。
单列,工厂,装饰着,适配器,动态代理

模拟谷歌汽车的场景:(装饰着模式)

1、java设计了汽车开发的约定
interface ICar{start run stop}
class GoogleCar implements ICar{}
2、希望在谷歌Car接入到生态圈的平台时,做一些增强汽车启动的功能。
3、用装饰着模式
(1)二次开发的时候,无法获取到原码,无法使用继承前提下,要对已经存在一些对象上的功能进行增强。
(2)前提:可以获取到被装饰的对象GoogleCar实现的所有接口。
(3)实现的思路:自己定义一个装饰类来实现ICar接口,为自定义的一个装饰类传递被装饰类的对象

假设是Google公司定义的接口

public interface ICar {public void start();public void run();public void stop();
}

假设这是谷歌公司定义的类实现了上方的接口,并实现对应的方法

//相当于mysql的驱动包,是由谷歌汽车的开发人员来实现类
public final class GoogleCar implements ICar {@Overridepublic void start() {System.out.println("判断天气是否良好");System.out.println("路况是否良好");System.out.println("控制谷歌的汽车启动");//调用谷歌汽车提供的C语言函数}@Overridepublic void run() {System.out.println("控制谷歌的汽车运行");}@Overridepublic void stop() {System.out.println("控制谷歌汽车停止");}}

一般上方的代码是不对外公开的所以无法直接通过new的方式来创建对象并调用其中的方法,并该类是通过final 修饰的所以也无法继承。
这个时候可以通过装着模式来对其类进行功能的增加,并丰富其中的方法

public class MyCar implements ICar{//实现其GoogleCar 类电实现的接口对应的方法ICar car;//虽然无法调用Google当中的方法也无法继承GoogleCar类,将GoogleCar通过参数的形式传递到对应的方法当中,将其GoogleCar的对象传递给GoogleCar的接口,通过接口来调用实现类当中的方法public MyCar(ICar car) {this.car=car;}@Overridepublic void start() {// TODO Auto-generated method stubSystem.out.println("检查天气是否良好");System.out.println("检查路况是否拥堵");car.start();}@Overridepublic void run() {// TODO Auto-generated method stubcar.run();}@Overridepublic void stop() {// TODO Auto-generated method stubcar.start();}
}
public class TestCar {public static void main(String[] args) {ICar car = new MyCar(new GoogleCar());car.start();car.run();car.stop();}
}

输出结果为:

检查天气是否良好
检查路况是否拥堵
判断天气是否良好
路况是否良好
控制谷歌的汽车启动
控制谷歌的汽车运行
判断天气是否良好
路况是否良好
控制谷歌的汽车启动

(装饰着模式)弊端:

如果被实现的方法过多,装饰类当中的方法过多,需要动态代理的方式解决装饰着模式的弊端

动态代理模式

原理:通过虚拟机在内存当中创建类似与MyCar.class文件。
要创建这个文件MyCar.class文件要告诉虚拟机:
1、被创建的字节码文件上应该有多少方法。
2、

利用Java的反射技术(JavaReflection),在运行时创建一个实现某些给定接口的新类(也称“动态代理类”)及其实例(对象),代理的是接口(Interfaces),不是类(Class),也不是抽象类。在运行时才知道具体的实现,spring aop就是此原理。

public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)throws IllegalArgumentException;

newProxyInstance,方法有三个参数:

loader: 用哪个类加载器去加载代理对象:孤单值,告诉虚拟机字节码加载器用哪个字节码加载器加载内存当中创建出的字节码文件

interfaces:动态代理类需要实现的接口:告诉虚拟机内存当中正在被创建的字节码文件当中应该有哪些

h:获取接口当中的方法,并且动态代理方法在执行时,会调用h里面的invoke方法去

TestCar.class.getClassLoader()将下面获取到的字节码对应的接口加载到本类的字节码当中,
GoogleCar.class.getInterfaces(),告诉虚拟机创建并获取GoogleCar字节码文件当中的所有接口 ,并不能获取其特有的方法
InvocationHandler()从接口当中获取那个方法,如何获取方法,复制那个方法,并执行新增的方法和特性
最后
通过上方一系列操作创建了一个对象ICar car = (ICar)需要强转

测试类方便理解GoogleCar.class.getInterfaces();获取到的是结构是什么

import java.lang.reflect.Method;
public class Test {public static void main(String[] args) {//获取GoogleCar googleCar.class字节码文件上所有的接口吗,googleCar上可能实现了多个接口Class[] clazz = GoogleCar.class.getInterfaces();for (Class cla : clazz) {//获取到ICar.class对应的接口当中所有的方法Method[] mds = cla.getMethods();for (Method method : mds) {System.out.println(method.getName());}}}
} 

运行结果
在这里插入图片描述

动态代理模式的实现

Proxy.newProxyInstance在内存当中创建字节码

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;public class TestCar {public static void main(String[] args) {
//TestCar.class.getClassLoader()将下面获取到的字节码对应的接口加载到本类的字节码当中
//GoogleCar.class.getInterfaces(),告诉虚拟机创建并获取GoogleCar字节码文件当中的所有接口
//new InvocationHandler()从接口当中获取那个方法,如何获取接口对应方法,复制那个接口对应方法,并执行新增的方法和特性
//最后通过上方一系列操作创建了一个对象ICar car = (ICar)需要强转 ICar car = (ICar)Proxy.newProxyInstance(TestCar.class.getClassLoader(), GoogleCar.class.getInterfaces(), new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//经过测试得知:method代表当前正在执行每个方法//System.out.println(method.getName());//获取到是是字节码文件GoogleCar当中的所有方法名称//执行当前的方法//method.invoke(new GoogleCar(), args);if(method.getName().equalsIgnoreCase("start")) {//equalsIgnoreCase忽略大小写比较//执行当前method对应的方法System.out.println("判断天气是否良好");System.out.println("路况是否良好");method.invoke(new GoogleCar(), args);}else {//获取接口当中的方法,放到正在执行的方法当中method.invoke(new GoogleCar(), args);}			return null;}});car.start();car.run();car.stop();}
}
//也可以实现该接口然后将MyCC传入到第三个参数当中
class MyCC implements InvocationHandler{@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// TODO Auto-generated method stubreturn null;}
}

执行结果:

判断天气是否良好
路况是否良好
控制谷歌的汽车启动
控制谷歌的汽车运行
控制谷歌汽车停止

解析动态代理

TestCar.class.getClassLoader(), 
GoogleCar.class.getInterfaces(), 
new InvocationHandler() 

在这里插入图片描述
上方代码生成TestCar$1.class字节码文件
TestCar$1.class生成上方代码当中的ICar对象的对象car
GoogleCar.class.getInterfaces():TestCar$1.class内放了GoogleCar的一堆方法

动态代理内的参数:
TestCar.class.getClassLoader():
字节码加载器:
jdk有一些程序,专业将各种字节码文件加载到内存当中,这里程序简称为字节码加载器。

如何将字节码文件class文件加载到内存当中?
底层实现的过程,利用IO流这种技术,获取到文件当中的数据,加载到内存当中。

字节码加载器:
在这里插入图片描述
TestCar.class.getClassLoader()将下面获取到的字节码对应的接口加载到本类的字节码当中。

GoogleCar.class.getInterfaces(),告诉虚拟机创建并获取GoogleCar字节码文件当中的所有接口 ,并不能获取其特有的方法。

InvocationHandler()从接口当中获取那个方法,如何获取方法,复制那个方法,并执行新增的方法和特性

Method:正在执行的方法
args:参数
改进上方代码验证各种参数的作用:

public interface ICar {public String start(int a,int b);public void run();public void stop();
}
//相当于mysql的驱动包,是由谷歌汽车的开发人员来实现类
public class GoogleCar implements ICar {@Overridepublic String start(int a,int b) {System.out.println("控制谷歌的汽车启动");//调用谷歌汽车提供的C语言函数return "start...."+a+" "+b;}@Overridepublic void run() {System.out.println("控制谷歌的汽车运行");}@Overridepublic void stop() {System.out.println("控制谷歌汽车停止");}
}
package com.itzheng.test06;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;public class TestCar {public static void main(String[] args) {// TestCar.class.getClassLoader()将下面获取到的字节码对应的接口加载到本类的字节码当中// GoogleCar.class.getInterfaces(),告诉虚拟机创建并获取GoogleCar字节码文件当中的所有接口// new InvocationHandler()从接口当中获取那个方法,如何获取方法,复制那个方法,并执行新增的方法和特性// 最后通过上方一系列操作创建了一个对象ICar car = (ICar)需要强转ICar car = (ICar) Proxy.newProxyInstance(TestCar.class.getClassLoader(), GoogleCar.class.getInterfaces(),new InvocationHandler() {//method代表正在执行的方法//args:代表正在执行的方法的参数//Object:代表方法执行完毕之后的返回值@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// 经过测试得知:method代表当前正在执行每个方法// System.out.println(method.getName());//获取到是是字节码文件GoogleCar当中的所有方法名称// 执行当前的方法// method.invoke(new GoogleCar(), args);// 代表每个方法执行完毕之后返回的对象Object obj = null;if (method.getName().equalsIgnoreCase("start")) {// equalsIgnoreCase忽略大小写比较// 执行当前method对应的方法System.out.println("判断天气是否良好");// 打印args里面的内容System.out.println(Arrays.toString(args));System.out.println("路况是否良好");obj = method.invoke(new GoogleCar(), args);} else {// 获取接口当中的方法obj = method.invoke(new GoogleCar(), args);}return obj;}});String cc =  car.start(1, 4);System.out.println(cc);car.run();car.stop();}
}//也可以实现该接口然后将MyCC传入到第三个参数当中
class MyCC implements InvocationHandler {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// TODO Auto-generated method stubreturn null;}
}

执行结果

判断天气是否良好
[1, 4]
路况是否良好
控制谷歌的汽车启动
start…1 4
控制谷歌的汽车运行
控制谷歌汽车停止

字节码加载器:3种

1、系统引导加载器:.class.getClassLoader() java当中不存在由其他语言来实现的

public class TestClassLoader {public static void main(String[] args) {//系统引导的类加载器//获取String类的加载器ClassLoader classLoader = String.class.getClassLoader();//String类的字节码加载器System.out.println(classLoader);//由于String.class,int.class等字节码文件需要频繁的被加载到内存速度必须块,底层用其他语言来实现}
}

在这里插入图片描述
2、ExtClassLoader扩展类加载器

public class TestClassLoader {public static void main(String[] args) {	//获取ext(extendtion)包下的某个类下的字节码加载器//ExtClassLoader扩展类加载器ClassLoader classLoader2 = sun.net.spi.nameservice.dns.DNSNameService.class.getClassLoader();System.out.println(classLoader2);}
}

输出结果:
在这里插入图片描述
3、应用类加载器 AppClassLoader应用类内存当中实际存在的类
应用类:一般实现的所有类都是属于应用类(自己创建的类)

public class TestClassLoader {public static void main(String[] args) {//应用类:一般实现的所有类都是属于应用类(自己创建的类)//获取应用类加载器 AppClassLoader ClassLoader classLoader3 = TestClassLoader.class.getClassLoader();System.out.println(classLoader3);}
}

在这里插入图片描述

解决网站动态代理编码的问题

案例:动态代理解决全站乱码问题
步骤:
1、new DynamicWeb Progect > index.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body><h1>post方式提交的中文</h1><form action="/day18_v3/ServletDemo" method="post">User:<input type="" name="username"><br> <inputtype="submit" /></form><h1>get方式提交的中文</h1><form action="/day18_v3/ServletDemo" method="get">User:<input type="" name="username"><br> <inputtype="submit" /></form>
</body>
</html>

2、建立ServletDemo

public class ServletDemo extends HttpServlet {private static final long serialVersionUID = 1L;public ServletDemo() {super();}protected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {String um = request.getParameter("username");System.out.println(request.hashCode()+"      :"+um);}protected void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {String um = request.getParameter("username");System.out.println(request.hashCode()+"      :"+um);}}

无论是在post/get方法,执行以下语句不存在中文乱码问题

String um = request.getParameter("username");System.out.println(um);

3、在过滤器当中为request上的getParameter();进行增强
思路:
判断当前的请求是get/post request.getMethod();
request.getMethod();返回的如果是post,设置一句话:request.setCharacterEncoding("utf-8");//放行
如果是get,调用原先的String v = request.getParameter(name);
将v进行转码,放行

案例的实现

在这里插入图片描述
next > /EncodingFilter > /*
在这里插入图片描述
在这里插入图片描述

package cn.itcast.test00;import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;public class EncodingFilter implements Filter {public EncodingFilter() {}public void destroy() {}public void init(FilterConfig fConfig) throws ServletException {}public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {//将request转换为HttpServletRequestfinal HttpServletRequest req = (HttpServletRequest)request;//让jdk在内存当中生成一个代理对象:增强了req对象上的getParmeter(name);APIHttpServletRequest myReq = (HttpServletRequest)Proxy.newProxyInstance(EncodingFilter.class.getClassLoader(), req.getClass().getInterfaces(), new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// TODO Auto-generated method stub Object obj = null;if(method.getName().equalsIgnoreCase("getParameter")) {//获取本次请求的方式,并对其进行转码为utf-8String md = req.getMethod();if("get".equalsIgnoreCase(md)) {//get方式的请求//调用req对象上的getParameter方法String v  = (String)method.invoke(req, args);//转码String vv = new String(v.getBytes("iso-8859-1"),"utf-8");return vv;}else {//POST方式的请求req.setCharacterEncoding("UTF-8");obj = method.invoke(req, args);}}else {obj = method.invoke(req, args);}return obj;}});//打印代理对象的Hash码System.out.println(myReq.hashCode());//将代理的对象放行chain.doFilter(myReq, response);//放行}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_789192.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java Web当中使用EasyUI|快速建立漂亮的后台网站(教程+源代码)

项目源代码下载&#xff1a;https://download.csdn.net/download/qq_44757034/12726812 一、EasyUI的概述 1、什么是EasyUI jQuery EasyUI是一组基于jQuery的UI插件集合体&#xff0c;而jQuery EasyUI的目标就是帮助web开发者更轻松的打造出功能丰富并且美观的UI界面。开发者…

外链引入css有哪些方式_2020:SEO关键词优化方式具体有哪些?

今天小龙在这里和大家一起来说说关于2020SEO关键词优化方式有哪些&#xff1f;正确的优化排名方法可以让我们的网站可以更快的可以把排名做到首页&#xff0c;那么究竟是怎样的呢&#xff1f;接下来我们就一起来看看。1、关键词分析&#xff08;也叫关键词定位&#xff09;&…

用Python爬取招聘网站数据,让学习、求职信息公开透明化~

1、项目背景 随着科技的飞速发展&#xff0c;数据呈现爆发式的增长&#xff0c;任何人都摆脱不了与数据打交道&#xff0c;社会对于“数据”方面的人才需求也在不断增大。因此了解当下企业究竟需要招聘什么样的人才&#xff1f;需要什么样的技能&#xff1f;不管是对于在校生&…

用PhantomJS来给AJAX站点做SEO优化

为什么80%的码农都做不了架构师&#xff1f;>>> 转 https://www.mxgw.info/t/phantomjs-prerender-for-seo.html 腾讯问卷所有动态内容&#xff0c;全部由Ajax接口提供。 众所周知&#xff0c;大部分的搜索引擎爬虫都不会执行JS&#xff0c;也就是说&#xff0c;如…

网站运行编译器错误CS1617: 选项“6”对 /langversion 无效;必须是 ISO-1、ISO-2、3、4、5 或 Default...

运行winform程序时提示&#xff0c; CS1617: 选项“6”对 /langversion 无效&#xff1b;必须是 ISO-1、ISO-2、3、4、5 或 Default 找到网站的web.config配置文件&#xff0c;找到相关的行数。 这样就解决问题了。转载于:https://www.cnblogs.com/xiaoai123/p/7513132.html

html地址怎么写成动态_网站动态页面如何优化 - 最蜘蛛池网站收录

原出处&#xff1a;最蜘蛛池原文链接&#xff1a;网站动态页面如何优化&#xff1f; - 最蜘蛛池相信那些SEO优化的那些朋友们&#xff0c;肯定还在一股脑的想着如何让自己的网站安静下来&#xff0c;他们都把这一点列入了重中之重的位置。最蜘蛛池小编不赞成此观点&#xff0c;…

搜索重复代码_网站代码优化技巧,你还不知道吗?

代码优化就是对网站代码开展解决&#xff1a;包含编码精减提升、标识增删、编码改动增删封裝、连接构造等解决。那么网站代码要怎样优化呢&#xff1f;删除冗余代码删除冗余代码&#xff0c;也指删除垃圾代码&#xff0c;主要是指网页中非必要的代码&#xff0c;也就是说可有可…

linux下设置网站默认目录,RedHat Linux下修改站点的默认路径

近期在做linux开发&#xff0c;涉及到一些问题&#xff0c;在此写出来&#xff0c;希望能帮到和我遇到相同问题的人。环境&#xff1a;RedHat linux 5.4&#xff1b; apache 2.4.4 &#xff1b; php 5.5首先搭建好环境&#xff0c;具体搭建环境就不说&#xff0c;本人的环境路径…

个别重要的网站链接(更新中)

为什么80%的码农都做不了架构师&#xff1f;>>> centos全系列阿里云下载 http://mirrors.aliyun.com/centos/7.2.1511/isos/x86_64/ 数字动起来的js插件 CountUP.js 变形字体 http://nymphont.deviantart.com/ shadowsock 免费密码和账号 http://ss.fa4.cn/ redis安…

制作一个简单的钓鱼网站

制作一个简单的钓鱼网站 实验环境&#xff1a;一台kali虚拟机&#xff08;用作制作钓鱼网站&#xff09;&#xff0c;NAT模式上网。 一台物理机&#xff08;就是我的电脑&#xff0c;用作被攻击对象&#xff09; 首先在kali上打开要使用的工具setoolkit. 接着有6个选项&#xf…

如何 阻止员工 访问 找工作网站 变态的方法 也适合禁用其它网站

在小公司没有防火墙的情况下&#xff0c; 如何 阻止员工 访问 找工作网站 变态的方法 也适合禁用其它网站 如下图&#xff1a; 打开 C:\windows\system32\drivers\etc\ hosts 文件&#xff0c;用记事本打开 第一行为默认不能动 第二行为添加、要再添加其它网站的话&#xff0c;…

浅谈大型网站动态应用系统架构(转)

动态应用&#xff0c;是相对于网站静态内容而言&#xff0c;是指以c/c、php、Java、perl、.net等服务器端语言开发的网络应用软件&#xff0c;比如论坛、网络相册、交友、BLOG等常见应用。动态应用系统通常与数据库系统、缓存系统、分布式存储系统等密不可分。 大型动态应用系统…

基于Python-Flask实现的网站例子

概述 使用Flask写的体育网站 包括&#xff08;注册 论坛 文章评论 组建战队 后台管理&#xff09;等功能 示例地址文中有写 萌新 请多指教详细 代码下载&#xff1a;http://www.demodashi.com/demo/12380.html 项目示例地址: 网站演示 一、环境搭建 1. 安装配置python3.6 示例网…

Web应用网站CDN加速访问技术原理

CDN全称Content Delivery Network&#xff0c;即内容分发网络。其基本思路是尽可能避开互联网上有可能影响数据传输速度和稳定性的瓶颈和环节&#xff0c;使内容传输的更快、更稳定。通过在网络各处放置节点服务器所构成的在现有的互联网基础之上的一层智能虚拟网络&#xff0c…

swf游戏保存进度_告别模拟器,一个网站,让你重温所有红白机、街机游戏

相信很多人都和我一样小时候的记忆第一次接触游戏听到的第一个声音便是小霸王&#xff0c;其乐无穷还记得当时忽悠老爹给我买时说是为了学习打字不知还有没有人记得下面这些绝版游戏我承认当时买了小霸王后第一件事的确是认(zhuang)认(mu)真(zuo)真(yang)地练习打字等老爹欣慰地…

Windows Server 2008 IIS下部署网站出现的问题

1. 无法识别“targetFramework” 用的是vs2010&#xff0c;应用.NET Framework 4创建的网站放在IIS&#xff08;7.0&#xff09;下会出现如下的错误&#xff1a;版本信息显示.NET Framework和ASP.NET的版本都是2.0&#xff0c;而我们制作网站的时候使用的.NET Framework 4.0&am…

校内闲鱼网站风险分析与会议内容

风险分析 1、技术风险 前端前端所有页面统计共有11个&#xff0c;可能还有一些细节的页面没有考虑到&#xff0c;而我们团队前端技术人员只有两人&#xff0c;存在的风险是可能不能按时完工。 应对措施&#xff1a;提早开工前端页面的代码设计&#xff0c;每一天都需要实现相应…

一般人不知道的SEO术语!!!

SEO就是Search Engine Optimization的缩写,中文就是搜索引擎优化。PR 值全称为PageRank(网页级别&#xff09;,是Google用于用来标识网页的等级、重要性的一种方法&#xff0c;是Google用来衡量一个网站的好坏的重要标准之一。SEM 搜索引擎营销,SEM常常是指通过付费和广告向搜索…

如何使用阿里云快速搭建个人网站

一、准备 1.windows本地远程连接Linux主机工具&#xff1a; XShell&#xff1a;http://xshellcn.com putty&#xff1a;http://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html cmder&#xff1a;https://cmder.net/ 2.远程上传文件至Linux主机&#xff1a; winscp&am…

网站能拿到其他网站的cookie_当网站安全漏洞来袭,没有谁还能拒绝网站安全监测和加固的服务!...

当下&#xff0c;随着互联网不断的发展&#xff0c;网站出现漏洞的频率以及网站被攻击的概率越来越高&#xff0c;这时候&#xff0c;网站安全问题如何解决呢?现在我们能做的就是做好预防工作。下面&#xff0c;蒙特给大家分享一些网站预防措施&#xff0c;有多重要&#xff0…