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);
}
}