Redis系列--7、RedisTemplate和 Serializer詳解
<bean id="redisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate"> <property name="connectionFactory" ref="connectionFactory" /> <!--如果不配置Serializer,那麽存儲的時候智能使用String,如果用User類型存儲,那麽會提示錯誤User can‘t cast to String!!! --> <property name="keySerializer"> <bean class="org.springframework.data.redis.serializer.StringRedisSerializer" /> </property> <property name="valueSerializer"> <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer" /> </property> </bean>
可以看到我在代碼中註釋掉了一段代碼,現在可以解釋上面留下的兩個問題了,第一個是在redis.xml中配置redistemplate的時候,同時配置了兩個Serializer:keySerializer實現了StringRedisSerializer,valueSerializer實現了JdkSerializationRedisSerializer。
一、為什麽要使用Serializer
因為redis是以key-value的形式將數據存在內存中,key就是簡單的string,key似乎沒有長度限制,不過原則上應該盡可能的短小且可讀性強,無論是否基於持久存儲,key在服務的整個生命周期中都會在內存中,因此減小key的尺寸可以有效的節約內存,同時也能優化key檢索的效率。
value在redis中,存儲層面仍然基於string,在邏輯層面,可以是string/set/list/map,不過redis為了性能考慮,使用不同的“encoding”數據結構類型來表示它們。(例如:linkedlist,ziplist等)。
所以可以理解為,其實redis在存儲數據時,都把數據轉化成了byte[]數組的形式,那麽在存取數據時,需要將數據格式進行轉化,那麽就要用到序列化和反序列化了,這也就是為什麽需要配置Serializer的原因。
二、SDR支持的序列化策略:
(詳細可查閱API文檔)
JdkSerializationRedisSerializer:
StringRedisSerializer
JacksonJsonRedisSerializer:
OxmSerializer:
其中JdkSerializationRedisSerializer和StringRedisSerializer是最基礎的序列化策略,其中“JacksonJsonRedisSerializer”與“OxmSerializer”都是基於stirng存儲,因此它們是較為“高級”的序列化(最終還是使用string解析以及構建java對象)。
基本推薦使用JdkSerializationRedisSerializer和StringRedisSerializer,因為其他兩個序列化策略使用起來配置很麻煩,如果實在有需要序列化成Json和XML格式,可以使用java代碼將String轉化成相應的Json和XML。
三、使用Serializer
在本項目中,是在配置文件中直接配置了相應的Serializer,key用的是StringRedisSerializer,value用的是JdkSerializationRedisSerializer,因為在此項目中,key為userId,為String類型,value為user為java類,即POJO,所以使用JdkSerializationRedisSerializer。
在redistemplate中直接配置Serializer當然比較方便,因為在後面想redis中存取數據時,就不用再次配置Serializer,但是這僅限於只有一種數據類型的情況,比如在本項目中只有<String userId,User user>類型的數據需要存儲,如果有多種數據類型時,在配置文件中配置就顯得不方便了,那麽我們可以在存取數據時,即Service的實現類存取數據操作時分別指定相應的Serializer。
所以在編程時有兩種選擇:
1.在redistemplate中配置Serializer(本項目即采用這種方式)
ValueOperations<String, User> valueops = redisTemplate.opsForValue(); valueops.set(user.getId(), user);
2.不在redistemplate中配置Serializer,而是在Service的實現類中單獨指定Serializer。就如同UserOperationsServiceImpl.java註釋的代碼:
boolean result = redisTemplate.execute(new RedisCallback<Boolean>() { public Boolean doInRedis(RedisConnection redisConnection) throws DataAccessException { RedisSerializer<String> redisSerializer = redisTemplate .getStringSerializer(); byte[] key = redisSerializer.serialize(user.getId()); byte[] value = redisSerializer.serialize(user.getName()); return redisConnection.setNX(key, value); } }); return result; }
本文出自 “風之痕_雪虎” 博客,請務必保留此出處http://snowtiger.blog.51cto.com/12931578/1932732
Redis系列--7、RedisTemplate和 Serializer詳解