JDK自带的序列化效率很低,速度慢且序列化后的字节数组占空间大。通常推荐使用第三方的序列化工具,比如Protostuff库,它是基于Google的Protobuf实现的序列化方法。原生的Protobuffer使用起来相当麻烦,首先要写.proto文件,然后编译.proto文件,生成对应的.java文件。Protostuff在几乎不损耗性能的情况下做到了不需要再写.proto文件来实现序列化。
使用Protostuff库需要引入的Maven依赖:1
2
3
4
5
6
7
8
9
10<dependency>
<groupId>io.protostuff</groupId>
<artifactId>protostuff-runtime</artifactId>
<version>1.6.0</version>
</dependency>
<dependency>
<groupId>io.protostuff</groupId>
<artifactId>protostuff-core</artifactId>
<version>1.6.0</version>
</dependency>
代码示例:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58package com.lzumetal.serialize.protostuff;
import io.protostuff.LinkedBuffer;
import io.protostuff.ProtobufIOUtil;
import io.protostuff.ProtostuffIOUtil;
import io.protostuff.Schema;
import io.protostuff.runtime.RuntimeSchema;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author liaosi
* @date 2018-08-18
*/
public class ProtostuffUtil {
private static Map<Class<?>, Schema<?>> cachedSchema = new ConcurrentHashMap<>();
private static <T> Schema<T> getSchema(Class<T> cls) {
Schema<T> schema = (Schema<T>) cachedSchema.get(cls);
if (schema == null) {
schema = RuntimeSchema.createFrom(cls);
cachedSchema.put(cls, schema);
}
return schema;
}
public static <T> byte[] serializer(T obj) {
Class<T> clazz = (Class<T>) obj.getClass();
LinkedBuffer buffer = LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE); //使用LinkedBuffer分配一块默认大小的buffer空间
try {
//RuntimeSchema是一个包含业务对象所有信息的类,包括类信息、字段信息
Schema<T> schema = RuntimeSchema.getSchema(clazz); //通过对象的类构建对应的schema
return ProtobufIOUtil.toByteArray(obj, schema, buffer); //使用给定的schema将对象序列化为一个byte数组,并返回
} catch (Exception e) {
throw new IllegalStateException(e.getMessage(), e);
} finally {
buffer.clear();
}
}
public static <T> T deserializer(byte[] bytes, Class<T> clazz) {
T obj = null;
try {
obj = clazz.newInstance();
Schema schema = RuntimeSchema.getSchema(obj.getClass());
ProtostuffIOUtil.mergeFrom(bytes, obj, schema);
} catch (InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
return obj;
}
}
构建schema的过程可能会比较耗时,因此希望使用过的类对应的schema能被缓存起来。代码如下:1
2
3
4
5
6
7
8
9
10private static Map<Class<?>, Schema<?>> cachedSchema = new ConcurrentHashMap<>();
private static <T> Schema<T> getSchema(Class<T> cls) {
Schema<T> schema = (Schema<T>) cachedSchema.get(cls);
if (schema == null) {
schema = RuntimeSchema.createFrom(cls);
cachedSchema.put(cls, schema);
}
return schema;
}