最近在spring-data-redis用redis緩存對象時,若是保存是String的話,沒有問題,可是若是保存對象時,發現就沒法正常顯示。利用redis-cli查看發現保存的均是二進制,沒法正常的查看。java
127.0.0.1:6379> keys * 1) "\xac\xed\x00\x05t\x00\x05test1" 2) "\xac\xed\x00\x05t\x00\atest122" 3) "\xac\xed\x00\x05t\x00\auser001" 4) "\xac\xed\x00\x05t\x00\ttest12245" 5) "\xac\xed\x00\x05t\x00\x1auser0000000000000000000001" 6) "\xac\xed\x00\x05t\x00\x10user000000000001"
查資料發現,spring-data-redis的RedisTemplate<K, V>模板類在操做redis時默認使用JdkSerializationRedisSerializer來進行序列,而spring-data-redis支持。git
JacksonJsonRedisSerializer Jackson2JsonRedisSerializer OxmSerializer
如今咱們實現Jackson2JsonRedisSerializer序列化,直接上代碼,主要看objRedisTemplate方法github
package com.xxfy.demo.config; import java.lang.reflect.Method; import org.springframework.cache.CacheManager; import org.springframework.cache.annotation.CachingConfigurerSupport; import org.springframework.cache.annotation.EnableCaching; import org.springframework.cache.interceptor.KeyGenerator; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.cache.RedisCacheManager; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.databind.ObjectMapper; /** * redis配置 * @author Administrator * */ @Configuration @EnableCaching public class RedisConfig extends CachingConfigurerSupport{ /** * redis緩存管理 * @param redisTemplate * @return */ @Bean public CacheManager cacheManager( @SuppressWarnings("rawtypes") RedisTemplate redisTemplate) { return new RedisCacheManager(redisTemplate); } @SuppressWarnings("unchecked") @Bean public RedisTemplate<String, String> redisTemplate( RedisConnectionFactory factory) { StringRedisTemplate template = new StringRedisTemplate(factory); @SuppressWarnings("rawtypes") Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(String.class); ObjectMapper om = new ObjectMapper(); om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); jackson2JsonRedisSerializer.setObjectMapper(om); template.setValueSerializer(jackson2JsonRedisSerializer); template.afterPropertiesSet(); return template; } /** * 序列化方式 * @param redisConnectionFactory * @return */ @SuppressWarnings({ "rawtypes", "unchecked" }) @Bean public RedisTemplate<Object, Object> objRedisTemplate(RedisConnectionFactory redisConnectionFactory){ RedisTemplate<Object, Object> template = new RedisTemplate<>(); template.setConnectionFactory(redisConnectionFactory); Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); ObjectMapper om = new ObjectMapper(); om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); jackson2JsonRedisSerializer.setObjectMapper(om); //key直接採用String的序列化 template.setKeySerializer(new StringRedisSerializer()); //key直接採用jackson2JsonRedisSerializer序列化 template.setValueSerializer(jackson2JsonRedisSerializer); template.afterPropertiesSet(); return template; } /** * redis的key生成策略 * @return */ @Bean KeyGenerator wiselyKeyGenerator() { return new KeyGenerator() { @Override public Object generate(Object target, Method method, Object... params) { StringBuilder sb = new StringBuilder(); sb.append(target.getClass().getName()); sb.append(method.getName()); for (Object obj : params) { sb.append(obj.toString()); } return sb.toString(); } }; } }
寫一個測試類進行測試:redis
package com.xxfy.demo.spring_boot_demo; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.test.context.junit4.SpringRunner; import com.xxfy.demo.vo.UserVo; import junit.framework.TestCase; @RunWith(SpringRunner.class) @SpringBootTest public class RedisTest extends TestCase{ @Autowired private StringRedisTemplate stringRedisTemplate; @Autowired private RedisTemplate<Object, Object> objRedisTemplate; @Test public void test() { //保存字符串 stringRedisTemplate.opsForValue().set("aaa", "中文"); System.out.println(stringRedisTemplate.opsForValue().get("aaa")); } @Test public void test2() { UserVo vo = new UserVo(); vo.setUserId("001"); vo.setPassword("123456"); objRedisTemplate.opsForValue().set("user0001", vo); System.out.println(((UserVo) objRedisTemplate.opsForValue().get("user0001")).getPassword()); } }
從測試代碼能夠看到:若是redis的Key,value都是String的話,直接使用StringRedisTemplate便可,而若是不是的話,則使用了RedisConfig中咱們定義的RedisTemplate<Object, Object>,利用它進行序列化,這樣就不會顯示亂碼了。而且咱們使用的是Object,全部從此使用POJO的話,不須要從新寫RedisTemplate。spring
源碼可參考:https://github.com/xiaojun90/spring-boot-demo.git緩存