当前位置: 首页 > news >正文

wordpress 建站教程 下载大连公司

wordpress 建站教程 下载,大连公司,苏州制作网页服务,好看的做地图分析图的网站1、引言 《手册》第 9 页 “OOP 规约” 部分有一段关于序列化的约定 1#xff1a; 【强制】当序列化类新增属性时#xff0c;请不要修改 serialVersionUID 字段#xff0c;以避免反序列失败#xff1b;如果完全不兼容升级#xff0c;避免反序列化混乱#xff0c;那么请…1、引言 《手册》第 9 页 “OOP 规约” 部分有一段关于序列化的约定 1 【强制】当序列化类新增属性时请不要修改 serialVersionUID 字段以避免反序列失败如果完全不兼容升级避免反序列化混乱那么请修改 serialVersionUID 值。 说明注意 serialVersionUID 值不一致会抛出序列化运行时异常。 我们应该思考下面几个问题 序列化和反序列化到底是什么 它的主要使用场景有哪些 Java 序列化常见的方案有哪些 各种常见序列化方案的区别有哪些 实际的业务开发中有哪些坑点 接下来将从这几个角度去研究这个问题。 2、序列化和反序列化是什么为什么需要它 序列化是将内存中的对象信息转化成可以存储或者传输的数据到临时或永久存储的过程。而反序列化正好相反是从临时或永久存储中读取序列化的数据并转化成内存对象的过程。 那么为什么需要序列化和反序列化呢 我们都知道文本文件图片、视频和安装包等文件底层都被转化为二进制字节流来传输的对方得文件就需要对文件进行解析因此就需要有能够根据不同的文件类型来解码出文件的内容的程序。 如果要实现 Java 远程方法调用就需要将调用结果通过网路传输给调用方如果调用方和服务提供方不在一台机器上就很难共享内存就需要将 Java 对象进行传输。而想要将 Java 中的对象进行网络传输或存储到文件中就需要将对象转化为二进制字节流这就是所谓的序列化。存储或传输之后必然就需要将二进制流读取并解析成 Java 对象这就是所谓的反序列化。 序列化的主要目的是方便存储到文件系统、数据库系统或网络传输等。 实际开发中常用到序列化和反序列化的场景有 远程方法调用RPC的框架里会用到序列化。将对象存储到文件中时需要用到序列化。将对象存储到缓存数据库如 Redis时需要用到序列化。通过序列化和反序列化的方式实现对象的深拷贝。 3、常见的序列化方式 常见的序列化方式包括 Java 原生序列化、Hessian 序列化、Kryo 序列化、JSON 序列化等。 3.1 Java 原生序列化 正如前面章节讲到的对于 JDK 中有的类最好的学习方式之一就是直接看其源码。 Serializable 的源码非常简单只有声明没有属性和方法 public interface Serializable { } 先思考一个问题如果一个类序列化到文件之后类的结构发生变化还能否保证正确地反序列化呢 答案显然是不确定的。 所以每个序列化类都有一个叫 serialVersionUID 的版本号反序列化时会校验待反射的类的序列化版本号和加载的序列化字节流中的版本号是否一致如果序列化号不一致则会抛出 InvalidClassException 异常。 强烈推荐每个序列化类都手动指定其 serialVersionUID如果不手动指定那么编译器会动态生成默认的序列化号因为这个默认的序列化号和类的特征以及编译器的实现都有关系很容易在反序列化时抛出 InvalidClassException 异常。建议将这个序列化版本号声明为私有以避免运行时被修改。 实现序列化接口的类可以提供自定义的函数修改默认的序列化和反序列化行为。 //自定义序列化方法 private void writeObject(ObjectOutputStream out) throws IOException;//自定义反序列化方法 private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException; 通过自定义这两个函数可以实现序列化和反序列化不可序列化的属性也可以对序列化的数据进行数据的加密和解密处理。 3.2 Hessian 序列化 Hessian 是一个动态类型二进制序列化也是一个基于对象传输的网络协议。Hessian 是一种跨语言的序列化方案序列化后的字节数更少效率更高。Hessian 序列化会把复杂对象的属性映射到 Map 中再进行序列化。 3.3 Kryo 序列化 Kryo 是一个快速高效的 Java 序列化和克隆工具。Kryo 的目标是快速、字节少和易用。Kryo 还可以自动进行深拷贝或者浅拷贝。Kryo 的拷贝是对象到对象的拷贝而不是对象到字节再从字节到对象的恢复。Kryo 为了保证序列化的高效率会提前加载需要的类这会带一些消耗但是这是序列化后文件较小且反序列化非常快的重要原因。 3.4 JSON 序列化 JSON (JavaScript Object Notation) 是一种轻量级的数据交换方式。JSON 序列化是基于 JSON 这种结构来实现的。JSON 序列化将对象转化成 JSON 字符串JSON 反序列化则是将 JSON 字符串转回对象的过程。常用的 JSON 序列化和反序列化的库有 Jackson、GSON、Fastjson 等。 4、Java 常见的序列化方案对比 我们想要对比各种序列化方案的优劣无外乎两点一点是查资料一点是自己写代码验证。 4.1 Java 原生序列化 Java 序列化的优点是对对象的结构描述清晰反序列化更安全。主要缺点是效率低序列化后的二进制流较大。 4.2 Hessian 序列化 Hession 序列化二进制流较 Java 序列化更小且序列化和反序列化耗时更短。但是父类和子类有相同类型属性时由于先序列化子类再序列化父类因此反序列化时子类的同名属性会被父类的值覆盖掉开发时要特别注意这种情况。 Hession2.0 序列化二进制流大小是 Java 序列化的 50%序列化耗时是 Java 序列化的 30%反序列化的耗时是 Java 序列化的 20%。 4.3 Kryo 序列化 Kryo 优点是速度快、序列化后二进制流体积小、反序列化超快。但是缺点是跨语言支持复杂。注册模式序列化更快但是编程更加复杂。 4.4 JSON 序列化 JSON 序列化的优势在于可读性更强。主要缺点是没有携带类型信息只有提供了准确的类型信息才能准确地进行反序列化这点也特别容易引发线上问题。 下面给出使用 Gson 框架模拟 JSON 序列化时遇到的反序列化问题的示例代码 /*** 验证GSON序列化类型错误*/ Test public void testGSON() {MapString, Object map new HashMap();final String name name;final String id id;map.put(name, 张三);map.put(id, 20L);String jsonString GSONSerialUtil.getJsonString(map);MapString, Object mapGSON GSONSerialUtil.parseJson(jsonString, Map.class);// 正确Assert.assertEquals(map.get(name), mapGSON.get(name));// 不等 map.get(id)为Long类型 mapGSON.get(id)为Double类型Assert.assertNotEquals(map.get(id).getClass(), mapGSON.get(id).getClass());Assert.assertNotEquals(map.get(id), mapGSON.get(id)); } 下面给出使用 fastjson 模拟 JSON 反序列化问题的示例代码 /*** 验证FatJson序列化类型错误*/ Test public void testFastJson() {MapString, Object map new HashMap();final String name name;final String id id;map.put(name, 张三);map.put(id, 20L);String fastJsonString FastJsonUtil.getJsonString(map);MapString, Object mapFastJson FastJsonUtil.parseJson(fastJsonString, Map.class);// 正确Assert.assertEquals(map.get(name), mapFastJson.get(name));// 错误 map.get(id)为Long类型 mapFastJson.get(id)为Integer类型Assert.assertNotEquals(map.get(id).getClass(), mapFastJson.get(id).getClass());Assert.assertNotEquals(map.get(id), mapFastJson.get(id)); } 大家还可以通过单元测试构造大量复杂对象对比各种序列化方式或框架的效率。 如定义下列测试类为 User包括以下多种类型的属性 Data public class User implements Serializable {private Long id;private String name;private Integer age;private Boolean sex;private String nickName;private Date birthDay;private Double salary; } 4.5 各种常见的序列化性能排序 实验的版本kryo-shaded 使用 4.0.2 版本gson 使用 2.8.5 版本hessian 用 4.0.62 版本。 实验的数据构造 50 万 User 对象运行多次。 大致得出一个结论 从二进制流大小来讲JSON 序列化 Java 序列化 Hessian2 序列化 Kryo 序列化 Kryo 序列化注册模式 从序列化耗时而言来讲GSON 序列化 Java 序列化 Kryo 序列化 Hessian2 序列化 Kryo 序列化注册模式 从反序列化耗时而言来讲GSON 序列化 Java 序列化 Hessian2 序列化 Kryo 序列化注册模式 Kryo 序列化 从总耗时而言Kryo 序列化注册模式耗时最短。 注由于所用的序列化框架版本不同对象的复杂程度不同环境和计算机性能差异等原因结果可能会有出入。 5、 序列化引发的一个血案 接下来我们看下面的一个案例 前端调用服务 A服务 A 调用服务 B服务 B 首次接到请求会查 DB然后缓存到 Redis缓存 1 个小时。服务 A 根据服务 B 返回的数据后执行一些处理逻辑处理后形成新的对象存到 Redis缓存 2 个小时。 服务 A 通过 Dubbo 来调用服务 BA 和 B 之间数据通过 MapString,Object 类型传输服务 B 使用 Fastjson 来实现 JSON 的序列化和反序列化。 服务 B 的接口返回的 Map 值中存在一个 Long 类型的 id 字段服务 A 获取到 Map 取出 id 字段并强转为 Long 类型使用。 执行的流程如下 通过分析我们发现服务 A 和服务 B 的 RPC 调用使用 Java 序列化因此类型信息不会丢失。 但是由于服务 B 采用 JSON 序列化进行缓存第一次访问没啥问题其执行流程如下 如果服务 A 开启了缓存服务 A 在第一次请求服务 B 后缓存了运算结果且服务 A 缓存时间比服务 B 长因此不会出现错误。 如果服务 A 不开启缓存服务 A 会请求服务 B 由于首次请求时服务 B 已经缓存了数据服务 B 从 RedisB中反序列化得到 Map。流程如下图所示 然而问题来了 服务 A 从 Map 取出此 Id 字段强转为 Long 时会出现类型转换异常。 最后定位到原因是 Json 反序列化 Map 时如果原始值小于 Int 最大值反序列化后原本为 Long 类型的字段变为了 Integer 类型服务 B 的同学紧急修复。 服务 A 开启缓存时 虽然采用了 JSON 序列化存入缓存但是采用 DTO 对象而不是 Map 来存放属性所以 JSON 反序列化没有问题。 因此大家使用二方或者三方服务时当对方返回的是 MapString,Object 类型的数据时要特别注意这个问题。 作为服务提供方可以采用 JDK 或者 Hessian 等序列化方式 作为服务的使用方我们不要从 Map 中一个字段一个字段获取和转换可以使用 JSON 库直接将 Map 映射成所需的对象这样做不仅代码更简洁还可以避免强转失败。 代码示例 Test public void testFastJsonObject() {MapString, Object map new HashMap();final String name name;final String id id;map.put(name, 张三);map.put(id, 20L);String fastJsonString FastJsonUtil.getJsonString(map);// 模拟拿到服务B的数据MapString, Object mapFastJson FastJsonUtil.parseJson(fastJsonString,map.getClass());// 转成强类型属性的对象而不是使用map 单个取值User user new JSONObject(mapFastJson).toJavaObject(User.class);// 正确Assert.assertEquals(map.get(name), user.getName());// 正确Assert.assertEquals(map.get(id), user.getId()); } 6、课后题 给出一个 PersonTransit 类一个 Address 类假设 Address 是其它 jar 包中的类没实现序列化接口。请使用今天讲述的自定义的函数 writeObject 和 readObject 函数实现 PersonTransit 对象的序列化要求反序列化后 address 的值正常。 Data public class PersonTransit implements Serializable {private Long id;private String name;private Boolean male;private ListPersonTransit friends;private Address address; }Data AllArgsConstructor public class Address {private String detail;} 一、序列化主要有两个困难 1 transient 关键字序列化时默认不序列化该字段。新加的增加难度 2 假设 Address 是第三方 jar 包中的类不允许修改实现序列化接口。 二、分析 我们通过专栏的介绍还有序列化接口java.io.Serializable的注释可知可以自定义序列化方法和反序列化方法 private void writeObject(java.io.ObjectOutputStream out)throws IOExceptionprivate void readObject(java.io.ObjectInputStream in)throws IOException, ClassNotFoundException; 实现序列化和反序列化不可序列化的属性也可以对序列化的数据进行数据的加密和解密处理。 三、参考代码 Data public class PersonTransit implements Serializable {private Long id;private String name;private Boolean male;private ListPersonTransit friends;private transient Address address;/*** 自定义序列化写方法*/private void writeObject(ObjectOutputStream oos) throws IOException {oos.defaultWriteObject();oos.writeObject(address.getDetail());}/*** 自定义反序列化读方法*/private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException {ois.defaultReadObject();this.setAddress(new Address( (String) ois.readObject()));} } 单元测试 Test public void testJDKSerialOverwrite() throws IOException, ClassNotFoundException {PersonTransit person new PersonTransit();person.setId(1L);person.setName(张三);person.setMale(true);person.setFriends(new ArrayList());Address address new Address();address.setDetail(某某小区xxx栋yy号);person.setAddress(address);// 序列化JdkSerialUtil.writeObject(file, person);// 反序列化PersonTransit personTransit JdkSerialUtil.readObject(file);// 判断是否相等Assert.assertEquals(personTransit.getName(), person.getName());Assert.assertEquals(personTransit.getAddress().getDetail(), person.getAddress().getDetail()); } 用到的工具类 public class JdkSerialUtil {public static T void writeObject(File file, T data) throws IOException {try (ObjectOutputStream objectOutputStream new ObjectOutputStream(new FileOutputStream(file));) {objectOutputStream.writeObject(data);objectOutputStream.flush();}}public static T void writeObject(ByteArrayOutputStream outputStream, T data) throws IOException {try (ObjectOutputStream objectOutputStream new ObjectOutputStream(outputStream);) {objectOutputStream.writeObject(data);objectOutputStream.flush();}}public static T T readObject(File file) throws IOException, ClassNotFoundException {FileInputStream fin new FileInputStream(file);ObjectInputStream objectInputStream new ObjectInputStream(fin);return (T) objectInputStream.readObject();}public static T T readObject(ByteArrayInputStream inputStream) throws IOException, ClassNotFoundException {ObjectInputStream objectInputStream new ObjectInputStream(inputStream);return (T) objectInputStream.readObject();} } 通过单元测试验证了我们编写代码的正确性。 7、思考题 1.为什么我们在前端向后端发送请求时请求对象没有序列化id也可以正常使用。 因为前端向后端发送请求实际上是一个反序列化的过程反序列化不需要序列化id,是json格式转换为对象。如果一个对象在同一台服务器上那么他们可以共享内存并不需要序列化。序列一般存在网络传输和io传输的情况下 2.为什么我们在使用fegin调用接口时为什么请求对象不需要实现序列化接口也能请求成功 因为使用fegin调用接口时实际上是将java对象序列化json对象序列成java对象不需要实现序列化接口。JSON序列化是基于对象的字段和属性的反射因此只要对象的字段可以被访问并且符合JSON的数据类型要求例如字符串、数字、布尔等通常就可以成功地将对象序列化为JSON而不需要额外的接口。
http://www.hkea.cn/news/14296803/

相关文章:

  • 石家庄晋州网站建设阿里云能做网站么
  • 如何查询网站备案号网站开发人员趋势
  • 群晖可以做网站吗招商网站建设全包
  • 南京手机网站制作公司做游戏音频下载网站
  • 专门做各种产品测评的网站asp网站源码安装流程
  • 合肥网站推广优化公司个人网站logo
  • 视频网站直播怎么做的企业手机网站建设信息
  • 佛山市研发网站建设哪家好网站开发时自适应
  • 下列关于网站开发中网页上传和武夷山网站定制
  • 无锡网站制作公司哪家好廊坊seo整站优化软件
  • 网站建设售后回访话术东莞市广建建设工程有限公司
  • 网站建设年度报告注册google账号
  • 住房和城市建设厅网站2016企业网站建设方案
  • 河南专业网站建设公司排名中小企业建站是什么
  • 临海钢结构设计网站wordpress安装不了主题
  • 做网站智能工具中国建设银行网址是什么
  • 烟台网站建设4038gzs培训教育机构
  • 自动注册wordpress账号软件google企业网站seo
  • 苏州知名高端网站建设企业大庆今天最新公告
  • 河北省城乡和建设厅网站首页阀门公司网站建设
  • 阿瓦提网站建设项目投资
  • 织梦做的网站有哪些小程序制作软件下载
  • 免费网站建设福州工作室网站建设的意义
  • wordpress建站腾讯云现在pc网站的标准一般是做多大
  • 网站开速度 流失网站开发之前前后端不分离
  • 可以做系统同步时间的网站制作商城公司
  • 基础型网站价格网站设计中怎么做二级页面
  • 企业做网站平台的好处设计师个人主页
  • 深圳住房和建设局网站官网打不开综合门户网站什么意思
  • 在哪找专业做淘宝网站wap网站解析