最近在作项目的时候须要使用持久化功能,1.0版本中使用的akka自带的持久化功能,使用的是akka persist支持的redis插件,在使用的过程当中踩了一些坑。所以,在而2.0版本中考虑本身往redis中持久化。要作持久化,必须考虑对象的序列化问题。序列化的方法不少,可使用java自带的序列化机制,可是时间效率不太好。所以在kryo和protobuffer之间徘徊。由于之前使用过grpc,须要手动编写proto文件,而后利用插件生成代码,以为很麻烦。可是经过搜索了解到还有一个protostuff不须要编写proto文件这个麻烦的步骤,而且效率还很好。所以,学习了下。java
<dependency> <groupId>io.protostuff</groupId> <artifactId>protostuff-core</artifactId> <version>1.6.0</version> </dependency> <dependency> <groupId>io.protostuff</groupId> <artifactId>protostuff-runtime</artifactId> <version>1.6.0</version> </dependency>
编写须要序列化和反序列化的对象git
public class User { private String name; private int age; public User(String name, int age) { this.name = name; this.age = age; } } public class Group { private String id; private String name; private List<User> users; public Group(String id, String name, List<User> users) { this.id = id; this.name = name; this.users = users; } }
public class ProtostuffUtils { /** * 避免每次序列化都从新申请Buffer空间 */ private static LinkedBuffer buffer = LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE); /** * 缓存Schema */ private static Map<Class<?>, Schema<?>> schemaCache = new ConcurrentHashMap<Class<?>, Schema<?>>(); /** * 序列化方法,把指定对象序列化成字节数组 * * @param obj * @param <T> * @return */ @SuppressWarnings("unchecked") public static <T> byte[] serialize(T obj) { Class<T> clazz = (Class<T>) obj.getClass(); Schema<T> schema = getSchema(clazz); byte[] data; try { data = ProtostuffIOUtil.toByteArray(obj, schema, buffer); } finally { buffer.clear(); } return data; } /** * 反序列化方法,将字节数组反序列化成指定Class类型 * * @param data * @param clazz * @param <T> * @return */ public static <T> T deserialize(byte[] data, Class<T> clazz) { Schema<T> schema = getSchema(clazz); T obj = schema.newMessage(); ProtostuffIOUtil.mergeFrom(data, obj, schema); return obj; } @SuppressWarnings("unchecked") private static <T> Schema<T> getSchema(Class<T> clazz) { Schema<T> schema = (Schema<T>) schemaCache.get(clazz); if (schema == null) { //这个schema经过RuntimeSchema进行懒建立并缓存 //因此能够一直调用RuntimeSchema.getSchema(),这个方法是线程安全的 schema = RuntimeSchema.getSchema(clazz); if (schema == null) { schemaCache.put(clazz, schema); } } return schema; } public static void main(String[] args){ final User user1 = new User("aaa",20); final User user2 = new User("bbb",21); List<User> users = new ArrayList<User>(){{add(user1);add(user2);}}; Group group = new Group("id_1","group1",users); byte[] bytes = ProtostuffUtils.serialize(group); System.out.println("序列化后: " + bytes.length); Group group1 = ProtostuffUtils.deserialize(bytes,Group.class); System.out.println("反序列化后: " + group1.getName()); }
运行结果以下:github
序列化后: 32 反序列化后: group1
工具类参考博客:https://blog.csdn.net/oppo5630/article/details/80173520
protostuff的github地址:https://github.com/protostuff/protostuffredis