分布式架构基础(二)序列化与反序列化

序列化与反序列化

序列化

序列化:将对象转化成特定的形态,然后以数据流的形式进行传输。
序列化格式:XML、Json
序列化过程:Object -> Json -> 传输(json字符串转化的数据流)
序列化目的:减少对象的大小,实现对象的跨平台,跨语言传输

反序列化

反序列化过程:数据流 -> Json -> Object

序列化Demo

服务端:
public static void main (String[] args) {
	
	ServiceSocket serviceSocket = new ServiceSocket(8080);
	Socket socket = serviceSocket.accept();
	
	ObjectInputStream inputStream  = new ObjectInputStream(socket.getInputStream());
	User user = (User)inputStream.readObject();
	……
}
客户端:
public static void main (String args) {
	
	Socket socket = new Socket("localhost", 8080);
	ObjectOutputStream outputStream = new ObjectOutinputStream(socket.getOutputStream());
	User user = new User();
	user.setName("Tom");
	outputStream.writer(user);
	outputStream.flush();
}
对象:
public class User implements Serializable {
	
	private String name:
	public void setName(String name) {
		this.name = name;
	}
	public String getName(){
		return name;
	}
}

Java中的序列化与反序列化

SerializableDemo

Serializable接口:
public instance ISerializable {
	
	//序列化
	<T> byte[] serialize(T object);
	
	//反序列化
	<T> T deSerialize(byte[] data);
}
Serializable接口的实现类:
public class JavaSerialize implements ISerializable {
	
	@Override
	public <T> byte[] serialize (T object) {
		
		ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
		
		try {
			ObjectOutputStream outputStream = new ObjectOutputStream(byteArrayOutputStream);
			outputStream.writerObject(objject);
			return byteArrayOutPutStream.toByteArrray();
		} catch (Execption e) {
			e.printStackTrace();
		}

		 return new byte[0];
	}

	@Override
	public <T> T deSerialize (byte[] data) {
		ByteArrayInputStream byteArrayInputStream = new ByteArrayInputSteam(data);
		try{
                ObjectInputStream objectInputStream = new ObjectInputSteam(byteArrayInputStream);
                return (T)objectInputStream.readObject();
            } catch(Exception e) {
                e.printStackTrace();
            }
           return null;
	} 
}
Serializable测试:

public static void main(String[] args) {
	User user = new User();
	user.setName("Tom");

	//将User进行序列化
    ISerializer serializer = new JavaSerializer();
    byte[] bytes = serializer.serialize(user);
    
    //反序列化
    User userRever = serializer.deSerialize(bytes);
}

serialVersionUID

用于确保类序列化与反序列化的兼容性问题的,如果序列化和反序列化过程中这两个值不一样,那么将导致序列化失败

serialVersionUID发生改变的三种情况:

  1. 手动去修改导致当前的 serialVersionUID 与序列化前的不一样。
  2. 我们根本就没有手动去写这个 serialVersionUID 常量,那么 JVM 内部会根据类结构去计算得到这个 serialVersionUID 值,在类结构发生改变时(属性增加,删除或者类型修改了)这种也是会导致 serialVersionUID 发生变化。
  3. 假如类结构没有发生改变,并且没有定义 serialVersionUID ,但是反序列和序列化操作的虚拟机不一样也可能导致计算出来的 serialVersionUID 不一样。

transient

被修饰的字段不进行序列化,重写了writeObjcet\readObject的时候可以将字段进行序列化。(类似钩子方法)

public class User{
    
    private String name;
    
    private transient int age;
    
    private void wirteObject(ObjectOutputStream out){
        out.defaultWriteObjcet();
        out.writeInt(age);
    }
    
    private void readObject(ObjcetInputStream in) {
		in.defaultReadObjcet();
        age = in.readInt();
    }
}

分布式架构下的序列化技术

  • XML 序列化框架: XStream 和 Java 自带的 XML
  • JSON 序列化框架:序列化效率很快(转化效率和传输效率)
  • hessian 序列化框架:性能、易用,比默认的序列化方式更好
  • dubbo -> hession2
  • Avro 序列化
  • kyro 序列化框架
  • Protobuf 序列化框架

选型建议

  1. 对性能要求不高的场景,可以采用基于 XML 的 SOAP 协议
  2. 对性能和间接性有比较高要求的场景,那么 Hessian、Protobuf、Thrift、Avro 都可以。
  3. 基于前后端分离,或者独立的对外的 api 服务,选用 JSON 是比较好的,对于调试、可读
    性都很不错
  4. Avro 设计理念偏于动态类型语言,那么这类的场景使用 Avro 是可以的

猜你喜欢

转载自blog.csdn.net/baidu_41934937/article/details/114583153