序列化与反序列化框架介绍(一)

1.1 序列化原理及常用的序列化介绍

简而言之,序列化就是把对象转化为字节序列的过程,反序列化则是将字节序列转化为对象的过程

1.1.1 解决的问题

在这里插入图片描述

1.1.2 序列化算法评价指标

在这里插入图片描述

1.2 常用序列化/反序列化实现的前导工作

为了抽象出一个序列化/反序列化通用服务,首先定义序列化/反序列化通用接口:

/**
 * @author pdc
 */
public interface ISerializer {
    /**
     * 序列化
     * @param obj
     * @param <T>
     * @return
     */
    public <T> byte[] serialize(T obj);
    /**
     * 反序列化
     * @param data
     * @param clazz
     * @param <T>
     * @return
     */
    public <T> T deserialize(byte[] data, Class<T> clazz);
}

接下来将基于该接口,给出日常开发中常见的序列化/反序列化实现

1.3 Java默认的序列化

1.3.1 原理

通过ObjectOutputStream和ObjectInputStream来实现,序列化类需要实现Serializable接口

1.3.2 抽取通用序列化/反序列化方法

/**
 * @author pdc
 */
public class DefaultJavaSerializer implements ISerializer {

    public <T> byte[] serialize(T obj) {
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        ObjectOutputStream objectOutputStream = null;
        try {
            //将对象写入byteArrayOutputStream
            objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
            objectOutputStream.writeObject(obj);
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            try {
                objectOutputStream.close();
            } catch (IOException e) {
                throw new RuntimeException("关闭ObjectOutputStream出错");
            }
        }
        return byteArrayOutputStream.toByteArray();
    }
    
    public <T> T deserialize(byte[] data, Class<T> clazz) {
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(data);
        ObjectInputStream objectInputStream = null;
        try {
            objectInputStream = new ObjectInputStream(byteArrayInputStream);
            //从byteArrayInputStream中读取对象
            return (T) objectInputStream.readObject();
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            try {
                objectInputStream.close();
            } catch (IOException e) {
                throw new RuntimeException("关闭objectInputStream出错");
            }
        }
    }
}

1.3.3 注意

关于Java序列化,需要注意如下几点:
在这里插入图片描述

1.3.4 关于自定义序列化细节

transient关键字和writeObject、readObject方法都是基于Serializable接口的序列化,如果想定制化序列化细节,则可以使用Externalizable接口,此接口扩展了Serializable

1.3.5 优缺点

在这里插入图片描述

1.4 XML序列化

实现方式有多种,这里介绍XStream与Java自带的XML序列化/反序列化两种方式

1.4.1 XStream

主要使用XStream

1.4.1.1 抽取通用序列化/反序列化方法

/**
 * @author pdc
 */
public class XmlSerializer implements ISerializer {
    /**
     * 初始化XStream对象
     */
    private static final XStream xStream = new XStream(new DomDriver());
    
    public <T> byte[] serialize(T obj) {
        return xStream.toXML(obj).getBytes();
    }
    
    public <T> T deserialize(byte[] data, Class<T> clazz) {
        String xml = new String(data);
        return (T) xStream.fromXML(xml);
    }
}

1.4.2 Java自带

主要使用XMLEncoder和XMLDecoder,内部使用ByteArrayOutputStream和ByteArrayInputStream来保存数据

1.4.2.1 抽取通用序列化/反序列化方法

/**
 * @author pdc
 */
public class XML2Serializer implements ISerializer {

    @Override
    public <T> byte[] serialize(T obj) {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        XMLEncoder xe = new XMLEncoder(out, "utf-8", true, 0);
        xe.writeObject(obj);
        xe.close();
        return out.toByteArray();
    }

    @Override
    public <T> T deserialize(byte[] data, Class<T> clazz) {
        XMLDecoder xd = new XMLDecoder(new ByteArrayInputStream(data));
        Object obj = xd.readObject();
        xd.close();
        return (T) obj;
    }
}

1.4.3 优缺点

在这里插入图片描述

1.5 JSON序列化

常用工具:Jackson、fastjson、GSON

1.5.1 比较:

在这里插入图片描述

1.5.2 抽取Jackson通用序列化/反序列化方法

/**
 * @author pdc
 */
public class JSONSerializer implements ISerializer {
    
    private static final ObjectMapper objectMapper = new ObjectMapper();

    static {
        objectMapper.configure(JsonParser.Feature.ALLOW_COMMENTS, true);
        objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
        objectMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
        objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true);
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);

        SimpleModule module = new SimpleModule("DateTimeModule", Version.unknownVersion());
     	//FDateJsonSerializer和FDateJsonDeserializer用于对Date类进行序列化格式的定制化输出
        //内部使用Json序列化接口
        module.addSerializer(Date.class, new FDateJsonSerializer());
        module.addDeserializer(Date.class, new FDateJsonDeserializer());

        objectMapper.registerModule(module);

    }

    private static ObjectMapper getObjectMapperInstance() {
        return objectMapper;
    }

    public <T> byte[] serialize(T obj) {
        if (obj == null) {
            return new byte[0];
        }
        try {
            String json = objectMapper.writeValueAsString(obj);
            return json.getBytes();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public <T> T deserialize(byte[] data, Class<T> clazz) {
        String json = new String(data);
        try {
            return (T) objectMapper.readValue(json, clazz);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
/**
 * @author pdc
 */
public class FDateJsonDeserializer extends JsonDeserializer<Date> {

    static final String PATTERN = "yyyy-MM-dd HH:mm:ss";
    static final DateTimeFormatter fmt = DateTimeFormat.forPattern(PATTERN);


    @Override
    public Date deserialize(JsonParser gen, DeserializationContext ctxt) throws IOException, JsonProcessingException {
        String date = gen.getText();
        if (StringUtils.isEmpty(date)) {
            return null;
        }
        if (StringUtils.isNumeric(date)) {
            return new Date(Long.valueOf(date));
        }
        try {
            DateTime dt = fmt.parseDateTime(date);
            return dt.toDate();
        } catch (Exception e) {
            throw new IOException(e);
        }
    }
}
/**
 * @author pdc
 */
public class FDateJsonSerializer extends JsonSerializer<Date> {

    private static final FastDateFormat DATE_FORMAT = FastDateFormat.getInstance("yyyy-MM-dd HH:mm:ss");

    @Override public void serialize(Date date, JsonGenerator jsonGenerator, SerializerProvider serializers) throws IOException, JsonProcessingException {
        jsonGenerator.writeString(date != null ? DATE_FORMAT.format(date) : "null");
    }

}

1.5.3 抽取fastjson通用序列化/反序列化方法

/**
 * @author pdc
 */
public class JSON2Serializer implements ISerializer {

    @Override
    public <T> byte[] serialize(T obj) {
        JSON.DEFFAULT_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
        return JSON.toJSONString(obj,SerializerFeature.WriteDateUseDateFormat).getBytes();
    }

    @Override
    public <T> T deserialize(byte[] data, Class<T> clazz) {
        return (T) JSON.parseObject(new String(data), clazz);
    }
}

猜你喜欢

转载自blog.csdn.net/qq_41594698/article/details/94296785