1. 程式人生 > >spring-redis序列化

spring-redis序列化

 

(一)spring data redis 提供了多種可選擇策略(RedisSerializer)

  • JdkSerializationRedisSerializer:POJO物件的存取場景,使用JDK本身序列化機制,將pojo類通過ObjectInputStream/ObjectOutputStream進行序列化操作,最終redis-server中將儲存位元組序列。是目前最常用的序列化策略。
  •  
  • StringRedisSerializer:Key或者value為字串的場景,根據指定的charset對資料的位元組序列編碼成string,是“new String(bytes, charset)”和“string.getBytes(charset)”的直接封裝。是最輕量級和高效的策略。
  •  
  • JacksonJsonRedisSerializer:jackson-json工具提供了javabean與json之間的轉換能力,可以將pojo例項序列化成json格式儲存在redis中,也可以將json格式的資料轉換成pojo例項。因為jackson工具在序列化和反序列化時,需要明確指定Class型別,因此此策略封裝起來稍微複雜。【需要jackson-mapper-asl工具支援】
  •  
  • OxmSerializer:提供了將javabean與xml之間的轉換能力,目前可用的三方支援包括jaxb,apache-xmlbeans;redis儲存的資料將是xml工具。不過使用此策略,程式設計將會有些難度,而且效率最低;不建議使用。【需要spring-oxm模組的支援】

 

(出自: Spring data redis-StringRedisTemplate 用法

 

 

 spring-data-redis提供了多種serializer策略,這對使用jedis的開發者而言,實在是非常便捷。sdr提供了4種內建的serializer:

  • JdkSerializationRedisSerializer:使用JDK的序列化手段(serializable介面,ObjectInputStrean,ObjectOutputStream),資料以位元組流儲存
  • StringRedisSerializer:字串編碼,資料以string儲存
  • JacksonJsonRedisSerializer:json格式儲存
  • OxmSerializer:xml格式儲存

    其中JdkSerializationRedisSerializer和StringRedisSerializer是最基礎的序列化策略,其中“JacksonJsonRedisSerializer”與“OxmSerializer”都是基於stirng儲存,因此它們是較為“高階”的序列化(最終還是使用string解析以及構建java物件)。

    RedisTemplate中需要宣告4種serializer,預設為“JdkSerializationRedisSerializer”:

    1) keySerializer :對於普通K-V操作時,key採取的序列化策略
    2) valueSerializer:value採取的序列化策略
    3) hashKeySerializer: 在hash資料結構中,hash-key的序列化策略
    4) hashValueSerializer:hash-value的序列化策略

    無論如何,建議key/hashKey採用StringRedisSerializer。

    接下來,通過例項描述如何使用它們,可以首先參考“spring-data-redis特性”:

 

取自:

pring-data-redis: serializer例項

 

 

(二)嘗試其中三種

 

 
  1. @Bean

  2. public RedisTemplate<String, Object> jdkRedisTemplate(

  3. RedisConnectionFactory factory) {

  4. RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();

  5. template.setConnectionFactory(factory);

  6.  
  7. Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);

  8. ObjectMapper om = new ObjectMapper();

  9. om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);

  10. om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);

  11. jackson2JsonRedisSerializer.setObjectMapper(om);

  12.  
  13. JdkSerializationRedisSerializer jdkSerializationRedisSerializer = new JdkSerializationRedisSerializer();

  14.  
  15. StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();

  16.  
  17. template.setValueSerializer(jdkSerializationRedisSerializer);

  18. template.setKeySerializer(stringRedisSerializer);

  19.  
  20. template.setHashKeySerializer(stringRedisSerializer);

  21. template.setHashValueSerializer(jdkSerializationRedisSerializer);

  22.  
  23. template.afterPropertiesSet();

  24. return template;

  25. }


 

 
  1. @Resource(name = "jdkRedisTemplate") // if stringRedisTemplate, result in SmsCheck cannot be cast to java.lang.String

  2. private RedisTemplate<String, Object> jdkRedisTemplate;



 

 
  1. @RequestMapping(value = "testRedis", method = RequestMethod.POST)

  2. @ResponseBody

  3. @ApiImplicitParams({})

  4. @ApiOperation(value="testRedis")

  5. public Object testRedis() {

  6.  
  7. SmsCheck smsCheck = new SmsCheck();

  8. smsCheck.setMobile("xxx");

  9.  
  10. // 設定快取

  11. jdkRedisTemplate.opsForValue().set("test",smsCheck);

  12.  
  13.  
  14. return null;

  15. }

 

 
  1. @Entity

  2. public class SmsCheck implements Serializable {

  3. private static final long serialVersionUID = 1L;

  4.  
  5. @Id

  6. @GeneratedValue(strategy = GenerationType.AUTO)

  7. @Column(name = "sms_check_id")

  8. private int smsCheckId;

  9.  
  10. private String mobile;

  11.  
  12. 。。。。。。



 

僅對value操作,保持key為string序列化

 

1.jdk序列化方案

 

get test 顯示

 

"\xac\xed\x00\x05sr\x00\x1ecom.ilex.xxx.model.SmsCheck\x00\x00\x00\x00\x00\x00\x00\x01\x02\x00\x05I\x00\nsmsCheckIdL\x00\acontentt\x00\x12Ljava/lang/String;L\x00\ncreateDatet\x00\x10Ljava/util/Date;L\x00\x06mobileq\x00~\x00\x01L\x00\x04typeq\x00~\x00\x01xp\x00\x00\x00\x00ppt\x00\x03xxxp"

 

注意:若這裡的SmsCheck未實現Serializable介面,會丟擲一個異常

 

 

 

2.string

 

直接丟擲異常

 

SmsCheck cannot be cast to java.lang.String

 

 

 

3 json

 

"[\"com.xxx.xx.model.SmsCheck\",{\"smsCheckId\":0,\"mobile\":\"xxx\",\"type\":null,\"content\":null,\"createDate\":null}]"

 

 

 

然後將key的序列化改為jdk

1) "\xac\xed\x00\x05t\x00\x04test"

2) "test"

 

顯示key也被jdk序列化了

 

 

 

redistemplate 預設用jdk序列化key和value

stringredistemplate預設用string序列化key和value

 

 

(三)關於序列化後redis檢視主要參考此貼:

 

 

最近在開始在學習Redis以及如何在Java當中去使用Redis,Redis是什麼我這裡就不說了。

我主要想說的是Redis和Java當中Spring結合起來的時候,使用到的RedisTemplate和StringRedisTemplate

他們兩者之間的區別,以及該怎麼使用。

 

RedisTemplate看這個類的名字字尾是Template,如果瞭解過Spring如何連線關係型資料庫的,大概不會難猜出這個類

是做什麼的 ,它跟JdbcTemplate一樣封裝了對Redis的一些常用的操作,當然StringRedisTemplate跟RedisTemplate功能類似

那麼肯定就會有人問,為什麼會需要兩個Template呢,一個不就夠了嗎?

其實他們兩者之間的區別主要在於他們使用的序列化類。

RedisTemplate使用的是JdkSerializationRedisSerializer

StringRedisTemplate使用的是StringRedisSerializer

 

RedisTemplate使用的序列類在在操作資料的時候,比如說存入資料會將資料先序列化成位元組陣列

然後在存入Redis資料庫,這個時候開啟Redis檢視的時候,你會看到你的資料不是以可讀的形式

展現的,而是以位元組陣列顯示,類似下面


當然從Redis獲取資料的時候也會預設將資料當做位元組陣列轉化,這樣就會導致一個問題,當需要獲取的

資料不是以位元組陣列存在redis當中而是正常的可讀的字串的時候,比如說下面這種形式的資料

 

  

關於RedisTemplate和StringRedisTemplate

 

 

 

(四)另外:

 

spring-data-redis是對jedis的封裝,如果直接使用jedis,需手動

1序列化物件

2轉為json字串

使用,spring自動處理了

 

jedis操作:

Redis:儲存物件的兩種方式(序列化和json字串)