FastJsonRedisSerializer 對 Java Object 寫入和讀取redis的操作支持
場景
開始學習redis
剛開始學習的時候用的是 redis 的 RedisTemplate,這個比較好上手:
@Autowired private RedisTemplate redisTemplate;
ValueOperations<String, String> vo = redisTemplate.opsForValue();
vo.set("mykey", "this is a value");//存到redis
這是一個 Stirng 的 key ,存了一個 String 的 value。當時我在做一個單點登錄系統,想要存入的 value 是一個 Java Object,這時遇到了一個問題,就是怎麼通過這個進行 Java Object 的寫入和讀取。
問題出現
寫入的時候很簡單,就是將 Java Object 進行 toString() 方法的重寫,然後就可以以 String 的方式寫入 redis ,但是讀取的時候出現了一個麻煩的問題,我是用 Java 默認生成的 toString() 重寫方法,出來的是這個格式:
SessionUser{id='1', token='c6f91e444dd3e7ab91541394bc5aa5f8', createTime=1529374760832, lastLoginTime=1529374941717}
因爲後續的操作是要用到 Java Object,所以這個字符串讀取出來要還原成 Java Object 是一個很頭痛的問題,默認方法生成的字符串不是 json 格式,所以不可以通過 json解析獲取對象,如果將自己定一個 json 生成的 toString() 方法,工作量大而且對 model 的修改不是很好,萬一後面 model 因爲數據庫表的修改而重新生成,那麼 model 又要再來一遍修改。
解決方法
在閱讀資料的時候,方向有一個解決方法是用一個序列化工具類來解決,核心思想是用原生的 Jedis 來操作,同時寫入的 key 和 value 都是 byte[] 類型。這時在 fastjson 包中找到了一個支持序列化和反序列化的類 FastJsonRedisSerializer 。
寫入和讀取的使用很簡單,
寫入:
FastJsonRedisSerializer fastJsonRedisSerializer = new FastJsonRedisSerializer(SessionUser.class);
jedis.set(user.getId().getBytes(), fastJsonRedisSerializer.serialize(sessionUser));
讀取:
FastJsonRedisSerializer fastJsonRedisSerializer = new FastJsonRedisSerializer(SessionUser.class);
SessionUser sessionUser = (SessionUser) fastJsonRedisSerializer.deserialize(vo.get(userId).getBytes());
這是最直接的使用方法,可以通過封裝成工具類來使用。
public static byte[] getByteArrFromObj(Object obj, Class clazz) {
FastJsonRedisSerializer fastJsonRedisSerializer = new FastJsonRedisSerializer(clazz);
return fastJsonRedisSerializer.serialize(obj);
}
public static Object getObjFromByteArr(byte[] byteArr, Class clazz) {
FastJsonRedisSerializer fastJsonRedisSerializer = new FastJsonRedisSerializer(clazz);
return fastJsonRedisSerializer.deserialize(byteArr);
}
PS
Java 自帶的序列化和反序列化據說效率不行,佔用空間也大,故不做推薦。
序列化
Object obj = new Object();//準備序列化的 object
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(object);
byte[] bytes = baos.toByteArray();
return bytes;
反序列化
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
ObjectInputStream ois = new ObjectInputStream(bais);
return ois.readObject();