最近在作項目的時候須要使用持久化功能,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