1 什么是序列化:
Java 序列化是一个接口,实现它,就以为这该类可以被序列化;
public interface Serializable {
}
2 为什么要序列化:
如果我们在不同的机器上完成对象的数据传输,机器里各自的对象都在jvm 的堆中存在,我们肯定不能将对象的地址进行传输,所以就需要有一种方式使得可以将对象的内容按照一定的格式进行输出,然后在给与计算机完成信息传输;
并不是所以的对象都可以被传输所以,我们需要有一个标记,那些对象可以传输,那些对象不可以传输;序列化接口就是来完成这个标记的;
demo:
定义序列化接口:
public interface XulieHuaSerivce {
<T>byte[] xuliehua(T t);
<T> T fanXuliehua(byte[] bytes);
}
序列化接口实现:
import java.io.*;
public class XulieHuaSerivceImpl implements XulieHuaSerivce{
@Override
public <T> byte[] xuliehua(T t) {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream = null;
try{
// 序列化对象
objectOutputStream= new ObjectOutputStream(byteArrayOutputStream);
// objectOutputStream= new ObjectOutputStream(new FileOutputStream("user"));
objectOutputStream.writeObject(t);
return byteArrayOutputStream.toByteArray();
}catch (Exception ex){
ex.printStackTrace();
}finally {
try{
byteArrayOutputStream.close();
if (null != objectOutputStream){
objectOutputStream.close();
}
}catch (Exception ex){
}
}
return new byte[0];
}
@Override
public <T> T fanXuliehua(byte[] bytes) {
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
ObjectInputStream objectInputStream = null;
try{
// 反序列化对象
objectInputStream= new ObjectInputStream(byteArrayInputStream);
// objectInputStream= new ObjectInputStream(new FileInputStream(new File("user")));
return (T)objectInputStream.readObject();
}catch (Exception ex){
ex.printStackTrace();
}finally {
try{
byteArrayInputStream.close();
if (null != objectInputStream){
objectInputStream.close();
}
}catch (Exception ex){
}
}
return null;
}
}
User 测试类:
import lombok.Data;
import java.io.Serializable;
@Data
public class User implements Serializable {
private String name;
}
测试类:
public class XulieHuaTest {
public static void main(String[] args) {
XulieHuaSerivce xulieHuaSerivce = new XulieHuaSerivceImpl();
User user = new User();
user.setName("lisi");
byte[] bytes = xulieHuaSerivce.xuliehua(user);
System.out.println("bytes.length = " + bytes.length);
for (byte aByte : bytes) {
System.out.print(aByte+" ");
}
User user1 = (User) xulieHuaSerivce.fanXuliehua(new byte[]{});
System.out.println("user1 = " + user1);
}
}
如果User 类不实现序列化接口则报错:
3 为什么要有一个序列化id:
防止对象在传输过程中,被认为通过反序列化的方式变更对象,从而引发数据安全问题;
demo:
先将user 序列化到文件中:
public class XulieHuaTest {
public static void main(String[] args) {
XulieHuaSerivce xulieHuaSerivce = new XulieHuaSerivceImpl();
User user = new User();
user.setName("lisi");
byte[] bytes = xulieHuaSerivce.xuliehua(user);
System.out.println("bytes.length = " + bytes.length);
for (byte aByte : bytes) {
System.out.print(aByte+" ");
}
}
}
序列化到文件
package com.gupaoedu.springcloud.example.demo.xuliehua;
import java.io.*;
public class XulieHuaSerivceImpl implements XulieHuaSerivce{
@Override
public <T> byte[] xuliehua(T t) {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream = null;
try{
// objectOutputStream= new ObjectOutputStream(byteArrayOutputStream);
// 序列化到user 文件
objectOutputStream= new ObjectOutputStream(new FileOutputStream("user"));
objectOutputStream.writeObject(t);
return byteArrayOutputStream.toByteArray();
}catch (Exception ex){
ex.printStackTrace();
}finally {
try{
byteArrayOutputStream.close();
if (null != objectOutputStream){
objectOutputStream.close();
}
}catch (Exception ex){
}
}
return new byte[0];
}
@Override
public <T> T fanXuliehua(byte[] bytes) {
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
ObjectInputStream objectInputStream = null;
try{
// objectInputStream= new ObjectInputStream(byteArrayInputStream);
// 从文件反序列化回来
objectInputStream= new ObjectInputStream(new FileInputStream(new File("user")));
return (T)objectInputStream.readObject();
}catch (Exception ex){
ex.printStackTrace();
}finally {
try{
byteArrayInputStream.close();
if (null != objectInputStream){
objectInputStream.close();
}
}catch (Exception ex){
}
}
return null;
}
}
然后在User 增加email属性:
import lombok.Data;
import java.io.Serializable;
@Data
public class User implements Serializable {
private String name;
private String email;
}
然后进行反序列化,提示序列化id不相同错误:
如果我们在User类中定义serialVersionUID,则即使 后期user类发生结构变化依然可以反序列化回来:
import lombok.Data;
import java.io.Serializable;
@Data
public class User implements Serializable {
private static final long serialVersionUID = 1232112L;
private String name;
private String email;
}
测试:
public class XulieHuaTest {
public static void main(String[] args) {
XulieHuaSerivce xulieHuaSerivce = new XulieHuaSerivceImpl();
// User user = new User();
// user.setName("lisi");
// byte[] bytes = xulieHuaSerivce.xuliehua(user);
// System.out.println("bytes.length = " + bytes.length);
// for (byte aByte : bytes) {
// System.out.print(aByte+" ");
// }
User user1 = (User) xulieHuaSerivce.fanXuliehua(new byte[]{});
System.out.println("user1 = " + user1);
}
}
4 分布式架构下的序列化:
将对象序列化后完成数据传输的过程中,需要考虑到序列化后的数据是否可以跨平台,压缩的效率,和压缩后的数据大小; 压缩效率越高,意为着压缩越快,则压缩后的数据大小往往会比较大;
服务之间通信常见的序列化: