之前在介紹Spring Redis進行存儲的時候,都是通過RedisTemplate中的defaultSerializer,即JdkSerializationRedisSerializer。通過Jdk的序列化比較簡單,但是有時候線上調試的時候通過控制台查看,完全看不出來存儲了什么東西。而且在空間占用和性能上,相比Jackson,完全沒有優勢。
有過兩次線上出問題,定位的時候知道緩存有錯,卻不知道到底出在那個緩存的字段上,調試非常不方便。於是序列化統統換成了Jackson。
代碼如下:
import java.lang.reflect.ParameterizedType; import java.util.concurrent.TimeUnit; import javax.annotation.Resource; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.HashOperations; import org.springframework.data.redis.core.ListOperations; import org.springframework.data.redis.core.RedisCallback; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.SetOperations; import org.springframework.data.redis.core.ValueOperations; import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.RedisSerializer; /** * key統一為String,省略.HK為hash類型的hashkey類型,HV為value類型或者hashvalue類型(這兩個不可能同時存在,所以只取一個) * @author Han */ public class BaseRedisDao<HK, HV> implements InitializingBean{ //實際參數的class start private Class<HK> hkClass; private Class<HV> hvClass; private Class<HK> getHKClass(){ if (hkClass == null) { hkClass = (Class<HK>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]; } return hkClass; } private Class<HV> getHVClass(){ if (hvClass == null) { hvClass = (Class<HV>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[1]; } return hvClass; } // end @Autowired private RedisTemplate<String, HV> redisTemplate; protected ValueOperations<String, HV> valueOperations; // protected HashOperations<String, HK, HV> hashOperations; // protected ListOperations<String, HV> listOperations; protected SetOperations<String, HV> setOperations; /** * * @param key * @param value * @param expire * @return */ protected void set(String key, HV value, long expire) { valueOperations.set(key, value, expire, TimeUnit.SECONDS); } /** * get value * * @param key * @return */ protected HV get(String key) { return valueOperations.get(key); } /** * key delete * @param key */ protected void delete(String key){ getRedisTemplate().delete(key); } /** * key exist * @param key * @return */ protected boolean hasKey(String key){ return getRedisTemplate().hasKey(key); } /** *key expire * @param key * @param timeout * @param unit * @return */ protected Boolean expire(String key,long timeout,TimeUnit unit){ return getRedisTemplate().expire(key, timeout, unit); } /** * redistemplate是全局唯一的,子類不要出現對redistemplate的成員變量的設置(比如keyserializer,) * @return */ RedisTemplate<String, HV> getRedisTemplate() { return redisTemplate; } /** * 當需要更改serializer,可以直接通過connection.set等方法實現 * @param callback * @return */ protected <T> T execute(RedisCallback<T> callback){ return redisTemplate.execute(callback); } /** * 獲取stringserializer */ protected RedisSerializer<String> getStringSerializer(){ return redisTemplate.getStringSerializer(); } /** * 獲取JdkSerializationRedisSerializer */ @SuppressWarnings("unchecked") protected <T> RedisSerializer<T> getDefaultSerializer(){ return (RedisSerializer<T>) redisTemplate.getDefaultSerializer(); } /** * 獲取stringserializer * @return */ @SuppressWarnings("unchecked") protected RedisSerializer<String> getKeySerializer(){ return (RedisSerializer<String>) redisTemplate.getKeySerializer(); } /** * 獲取jackson2jsonredisserializer * @return */ protected RedisSerializer<HV> getValueSerializer(){ return (RedisSerializer<HV>) redisTemplate.getValueSerializer(); } /** * 獲取jackson2jsonredisserializer * @return */ @SuppressWarnings("unchecked") protected RedisSerializer<HK> getHashKeySerializer() { return (RedisSerializer<HK>) redisTemplate.getHashKeySerializer(); } /** * 獲取jackson2jsonredisserializer * @return */ @SuppressWarnings("unchecked") protected RedisSerializer<HV> getHashValueSerializer() { return (RedisSerializer<HV>) redisTemplate.getHashValueSerializer(); } @Override public void afterPropertiesSet() throws Exception { if(getHKClass() == null || getHVClass() == null){ throw new IllegalArgumentException("獲取泛型class失敗"); } // valueOperations = redisTemplate.opsForValue(); hashOperations = redisTemplate.opsForHash(); listOperations = redisTemplate.opsForList(); setOperations = redisTemplate.opsForSet(); // redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<HV>(getHVClass())); redisTemplate.setHashKeySerializer(new Jackson2JsonRedisSerializer<HK>(getHKClass())); redisTemplate.setHashValueSerializer(new Jackson2JsonRedisSerializer<HV>(getHVClass())); } }
對於key的序列化,直接在配置文件定義
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate" scope="prototype"> <property name="connectionFactory" ref="jedisConnectionFactory" /> <property name="keySerializer" ref="stringKeySerializer"/> <property name="enableTransactionSupport" value="true"/><!-- 配置true可以使用transactional控制事務,spring已經提供支持 --> </bean>