分布式通信之序列化

栏目: 后端 · 发布时间: 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();
		}
		
	}

}
复制代码

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

查看所有标签

猜你喜欢:

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

编译原理

编译原理

Alfred V.Aho、Jeffrey D.Ullman、Ravi Sethi / 李建中 / 机械工业出版社 / 2003-8 / 55.00元

《编译原理》作者Alfred V.Aho、Ravi Sethi和Jeffrey D.Ullman是世界著名的计算机 科学家,他们在计算机科学理论、数据库等很多领域都做出了杰出贡献。《编译原理》 是编译领域无可替代的经典著作,被广大计算机专业人士誉为“龙书”。《编译原理》一 直被世界各地的著名高等院校和科研机构(如贝尔实验室、哥伦比亚大学、普 林斯顿大学和斯坦福大学等)广泛用作本科生和研究生编译原理......一起来看看 《编译原理》 这本书的介绍吧!

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试