分布式通信之序列化

栏目: 后端 · 发布时间: 6年前

内容简介:知识点:1)序列化概念2)实现序列化手段

知识点:

1)序列化概念

2)实现序列化手段

3)序列化实现深克隆

4)主流序列化手段及操作

Java的序列化机制 Sericalize接口 存在的问题

1)序列化数据结果比较大 传输效率低

2)不能跨语言对接

后续xml编码格式的对象序列化机制成为了主流。

1)多语言

2)便于理解

Json

HTTP RESTful

基于二进制序列化框架 MessagePack

使用恰当的序列化协议不仅可以提高系统的通用性,强壮性,安全性,优化性能,同时能让系统更加易于调试和扩展。

把对象转化为字节序列的过程称为对象的序列化,反之就是对象的反序列化。

1)实现一个序列化操作 首先定义一个对象的类【实现序列化操作需要继承sericalize接口】

package com.llf.sericalizeTest;

import java.io.Serializable;

public class Person implements Serializable{

	private static final long serialVersionUID = -8102469415223443135L;
	
	private String Name;
	private int age;
	public String getName() {
		return Name;
	}
	public void setName(String name) {
		Name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
}
复制代码

写一个测试类,首先我们提供序列化它的方法

分布式通信之序列化

然后执行能在相应的地方发现这个person文件生成

分布式通信之序列化

然后我们增加其反序列化的操作,并且把文件中反序列化对象中的我们赋值的拿出来

package com.llf.sericalizeTest;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class SericalizeDemo {
	public static void main(String[] args) {
		//序列化操作
		SericalizePerson();
		//反序列化操作
		DeSericalizePerson();
	}

	/**
	 * 序列化Person类
	 */
	private static void SericalizePerson(){
		try {
			//生成序列化二进制文件的地址
			ObjectOutputStream os=new ObjectOutputStream(new FileOutputStream(new File("person")));
			Person person=new Person();
			person.setName("CQ");
			person.setAge(18);
			os.writeObject(person);
			System.out.println("序列化成功!");
			os.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	private static void DeSericalizePerson(){
		try {
			ObjectInputStream ois=new ObjectInputStream(new FileInputStream(new File("person")));
			try {
				Person person=(Person) ois.readObject();
				System.out.println("名字叫 "+person.getName());
				System.out.println("年龄是 "+person.getAge());
				System.out.println("反序列化成功!");
				ois.close();
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}
}
复制代码
分布式通信之序列化

ObjectInputStream :读取指定的字节数据转化为对象

分布式通信之序列化

serialVesionUID 的作用: 1)保证序列化对象和反序列化对象是同一个 序列化会有个版本号,如果没有这个的话,会生成新的。 2)静态变量的序列化

序列化不保存静态变量状态

序列化之后然后修改一个静态变量的值然后在反序列化发现对象的值已经变成修改后的值。

Transient 关键字

修饰的属性不参与序列化

序列化的父子类问题:

如果父类没有实现序列化,而子类实现序列化,那么父类中的成员没办法做序列化操作。

序列化的存储规则:

对同个对象进行多次写入,打印出的第一次存储结果和第二次存储结果只多了5个字节的引用关系,不会导致文件累加。

序列化实现深度克隆

1)浅克隆 :复制对象,不复制对象的引用

2)深克隆 :复制对象,复制对象的引用

序列化实现深克隆

package com.llf.sericalizeClone;

import java.io.Serializable;

public class Teacher implements Serializable{
	
	/**
	 * 
	 */
	private static final long serialVersionUID = -6957411933291636976L;
	private String Name;

	public String getName() {
		return Name;
	}

	public void setName(String name) {
		Name = name;
	}

	@Override
	public String toString() {
		return "Teacher [Name=" + Name + "]";
	}
}
复制代码
package com.llf.sericalizeClone;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class Student implements Serializable{

	/**
	 * 
	 */
	private static final long serialVersionUID = -6029082021501636342L;
	
	private String Name;
	private int age;
	
	private Teacher teacher;
	
	public String getName() {
		return Name;
	}
	public void setName(String name) {
		Name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	
	public Teacher getTeacher() {
		return teacher;
	}
	public void setTeacher(Teacher teacher) {
		this.teacher = teacher;
	}
	
	public Object deapClone(){
		ByteArrayOutputStream os=new ByteArrayOutputStream();
		ObjectOutputStream oos=null;
		ByteArrayInputStream is=null;
		ObjectInputStream ois = null;
		try {
			//序列化
			oos=new ObjectOutputStream(os);
			oos.writeObject(this);
			//反序列化
			is=new ByteArrayInputStream(os.toByteArray());
		    ois=new ObjectInputStream(is);
			try {
				return ois.readObject();
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			}
		} catch (IOException e) {
			e.printStackTrace();
		}finally {
			try {
				ois.close();
				is.close();
				oos.close();
				os.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return null;
	}
	@Override
	public String toString() {
		return "Student [Name=" + Name + ", age=" + age + "]";
	}
}
复制代码
package com.llf.sericalizeClone;

public class CloneDemo {
	public static void main(String[] args) {
		Teacher teacher=new Teacher();
		teacher.setName("LLF");
		Student student=new Student();
		student.setName("CQ");
		student.setAge(18);
		student.setTeacher(teacher);
		
		Student student2=(Student) student.deapClone();//克隆一个对象
		
		System.out.println(student);
		System.out.println(student2);
	}
}
复制代码

总结: 1)在 java 中,只要一个类实现了java.io.serializable接口,那么她就可以被序列化

2) 通过objectoutputstream和objectinputstream对对象进行序列化和反序列化

3)对象是否被反序列化,不仅取决于对象的代码是否一致,同样还有一个重要因素(UID)

4)序列化不保存静态变量

5)要想父类对象也参与序列化操作,必须要让父类也实现serializable接口

6)Transient主要是控制控制变量是否能被序列化。如果没有被序列化的成员变量反序列化后会被设置为初始值。

7)通过序列化操作实现深度克隆。

当前主流的序列化技术有哪些

JSON

Hessian(2)

xml

protobuf

kryo

msgpack

FST

thrify

protostuff

avro

演示几种序列化手段的demo

首先是JSON

1)JSON

首先pom文件中引入jar包

<dependency>
    <groupId>org.codehaus.jackson</groupId>
    <artifactId>jackson-mapper-asl</artifactId>
    <version>1.9.13</version>
</dependency>
复制代码

然后代码

package com.llf.serialiableJSON;

import java.io.IOException;

import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;

import com.llf.sericalizeTest.Person;

public class JsonDemo {
	
	//初始化对象
	private static Person init(){
		Person person=new Person();
		person.setName("张三");
		person.setAge(18);
		return person;
	}
	
	public static void main(String[] args) {
		executeWithJackson();
	}

	@SuppressWarnings("unused")
	private static void executeWithJackson(){
		Person person=init();
		ObjectMapper mapper=new ObjectMapper();
		byte[] writeBytes=null;
		long start=System.currentTimeMillis();
		for(int i=0;i<100;i++){
			try {
				//序列化
				writeBytes=mapper.writeValueAsBytes(person);
			} catch (JsonGenerationException e) {
				e.printStackTrace();
			} catch (JsonMappingException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		System.out.println("JSON 序列化 "+(System.currentTimeMillis()-start)+"ms : 总大小为-->"+writeBytes.length);
	   //反序列化
		try {
			Person person2=mapper.readValue(writeBytes, Person.class);
		} catch (JsonParseException e) {
			e.printStackTrace();
		} catch (JsonMappingException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
复制代码
分布式通信之序列化

同样的阿里也是实现了一个jar包 fastjar

分布式通信之序列化

我们比较下俩者的耗时 遍历10万次以下是jackson快而10万以上是fastjson快。

package com.llf.serialiableJSON;

import java.io.IOException;

import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;

import com.alibaba.fastjson.JSON;
import com.llf.sericalizeTest.Person;

public class JsonDemo {
	
	//初始化对象
	private static Person init(){
		Person person=new Person();
		person.setName("张三");
		person.setAge(18);
		return person;
	}
	
	public static void main(String[] args) {
		executeWithJackson();
		executeWithFastJson();
	}

	@SuppressWarnings("unused")
	private static void executeWithJackson(){
		Person person=init();
		ObjectMapper mapper=new ObjectMapper();
		byte[] writeBytes=null;
		long start=System.currentTimeMillis();
		for(int i=0;i<100000;i++){
			try {
				//序列化
				writeBytes=mapper.writeValueAsBytes(person);
			} catch (JsonGenerationException e) {
				e.printStackTrace();
			} catch (JsonMappingException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		System.out.println("jackson JSON 序列化 "+(System.currentTimeMillis()-start)+"ms : 总大小为-->"+writeBytes.length);
	   //反序列化
		try {
			Person person2=mapper.readValue(writeBytes, Person.class);
		} catch (JsonParseException e) {
			e.printStackTrace();
		} catch (JsonMappingException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	private static void executeWithFastJson(){
		Person person=init();
		String text=null;
		long start=System.currentTimeMillis();
		for(int i=0;i<100000;i++){
			//序列化
			text=JSON.toJSONString(person);
		}
		System.out.println("fastjson JSON 序列化 "+(System.currentTimeMillis()-start)+
				"ms : 总大小为-->"+text.getBytes().length);
	   //反序列化
		Person person2=JSON.parseObject(text, Person.class);
	}
}
复制代码

首先引入jar包,这是百度开发的一个jar包

<dependency>
            <groupId>com.baidu</groupId>
            <artifactId>jprotobuf</artifactId>
            <version>2.1.2</version>
        </dependency>
复制代码

我们先定义注解

分布式通信之序列化

然后序列化和反序列化

分布式通信之序列化
分布式通信之序列化

protobuf优势就是字节数少,非常适合网络传输。

hessian 序列化 定义方法

分布式通信之序列化

字节比较多,但是耗时很低

分布式通信之序列化

我们看下各个序列化手段的耗时和字节对比

分布式通信之序列化
package com.llf.sericalizeTest;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class SericalizeDemo {
	public static void main(String[] args) {
		//序列化操作
		SericalizePerson();
		//反序列化操作
		DeSericalizePerson();
	}

	/**
	 * 序列化Person类
	 */
	private static void SericalizePerson(){
		try {
			//生成序列化二进制文件的地址
			ObjectOutputStream os=new ObjectOutputStream(new FileOutputStream(new File("person")));
			Person person=new Person();
			person.setName("CQ");
			person.setAge(18);
			os.writeObject(person);
			System.out.println("序列化成功!");
			os.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	private static void DeSericalizePerson(){
		try {
			ObjectInputStream ois=new ObjectInputStream(new FileInputStream(new File("person")));
			try {
				Person person=(Person) ois.readObject();
				System.out.println("名字叫 "+person.getName());
				System.out.println("年龄是 "+person.getAge());
				System.out.println("反序列化成功!");
				ois.close();
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}

}
复制代码

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

复盘+:把经验转化为能力(第2版)

复盘+:把经验转化为能力(第2版)

邱昭良 / 机械工业出版社 / 39.00

随着环境日趋多变、不确定、复杂、模糊,无论是个人还是组织,都需要更快更有效地进行创新应变、提升能力。复盘作为一种从经验中学习的结构化方法,满足了快速学习的需求,也是有效进行知识萃取与共享的机制。在第1版基础上,《复盘+:把经验转化为能力》(第2版)做了六方面修订: ·提炼复盘的关键词,让大家更精准地理解复盘的精髓; ·基于实际操作经验,梳理、明确了复盘的"底层逻辑"; ·明确了复......一起来看看 《复盘+:把经验转化为能力(第2版)》 这本书的介绍吧!

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具