Spring-boot整合Redis,遇到的问题

1.通过set进redis中的数据,get不到

        String cityKey ="city_"+id;
        ValueOperations<String,City> operations = this.redisTemplate.opsForValue();
        // 判断缓存中是否存在
        if (this.redisTemplate.hasKey(cityKey)){

            City city = operations.get(cityKey);
            return city;
        }
        // 从 DB 中获取
        City city = this.cityRepository.findById(id).get();

        // 添加的缓存中,时间10
        operations.set(cityKey,city,100, TimeUnit.SECONDS);

在redis-cli 中查看

192.168.6.3:6379> keys *
 xacxedx00x05tx00x06city_2

发现key值出现 xacxedx00x05tx00x06city_2 key是乱码

原因:序列化是默认用的JdkSerializationRedisSerializer 

在redis配置中添加

//设置key序列-String序列化
template.setKeySerializer(new StringRedisSerializer());

2.如果希望java对象以json的方式存储到redis中

通常会在redis配置中添加

Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);

// 设置value的序列化规则
//json序列化
template.setValueSerializer(jackson2JsonRedisSerializer);

但是进行redis缓存get时会报错:java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to com.redis.springbootredis.pojo.City

 1 java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to com.redis.springbootredis.pojo.City
 2     at com.redis.springbootredis.service.impl.CityServiceImpl.findCityById(CityServiceImpl.java:59)
 3     at com.redis.springbootredis.SpringBootRedisApplicationTests.testFindCityById(SpringBootRedisApplicationTests.java:25)
 4     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 5     at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
 6     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
 7     at java.lang.reflect.Method.invoke(Method.java:498)
 8     at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
 9     at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
10     at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
11     at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
12     at org.springframework.test.context.junit4.statements.RunBeforeTestExecutionCallbacks.evaluate(RunBeforeTestExecutionCallbacks.java:74)
13     at org.springframework.test.context.junit4.statements.RunAfterTestExecutionCallbacks.evaluate(RunAfterTestExecutionCallbacks.java:84)
14     at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
15     at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
16     at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
17     at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
18     at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251)
19     at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
20     at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
21     at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
22     at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
23     at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
24     at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
25     at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
26     at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
27     at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
28     at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
29     at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
30     at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
31     at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
32     at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
33     at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)

原因:redis中取出的对象数据为json,java.util.LinkedHashMap无法转换成city对象,

解决方式:在redis配置中添加

        //解决查询缓存转换异常的问题
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);

还有一种方式:就是每次获取到对象数据进行json转换(每一都要转换太麻烦不太建议)

            String str = JSONObject.toJSONString(operations.get(cityKey));
            City cityy = JSON.parseObject(str,City.class);

笔者的redis配置类

 1 import com.fasterxml.jackson.annotation.JsonAutoDetect;
 2 import com.fasterxml.jackson.annotation.PropertyAccessor;
 3 import com.fasterxml.jackson.databind.ObjectMapper;
 4 import org.springframework.context.annotation.Bean;
 5 import org.springframework.context.annotation.Configuration;
 6 import org.springframework.data.redis.connection.RedisConnectionFactory;
 7 import org.springframework.data.redis.core.RedisTemplate;
 8 import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
 9 import org.springframework.data.redis.serializer.StringRedisSerializer;
10 
11 /**
12  * @Author: GWL
13  * @Description: redis配置
14  * redisTemplate 序列化使用的jdkSerializeable, 存储二进制字节码, 所以自定义序列化类
15  * 一般redis的序列化方式主要有:字符串序列化、json序列化、xml序列化、jdk序列化
16  * 默认为 JdkSerializationRedisSerializer
17  * @Date: Create in 14:43 2019/5/14
18  */
19 @Configuration
20 public class RedisConfig {
21 
22     @Bean
23     public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisCollectionFactory) {
24         RedisTemplate template = new RedisTemplate();
25         template.setConnectionFactory(redisCollectionFactory);
26 
27         Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
28 
29         //解决查询缓存转换异常的问题
30         ObjectMapper om = new ObjectMapper();
31         om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
32         om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
33         jackson2JsonRedisSerializer.setObjectMapper(om);
34 
35         // 设置value的序列化规则
36         //json序列化
37         template.setValueSerializer(jackson2JsonRedisSerializer);
38         //String序列化
39 //        template.setValueSerializer(new StringRedisSerializer());
40         //jdk序列化
41 //        template.setValueSerializer(new JdkSerializationRedisSerializer());
42 
43         //设置key序列-String序列化
44         template.setKeySerializer(new StringRedisSerializer());
45 
46         template.setHashKeySerializer(new StringRedisSerializer());
47         template.setHashValueSerializer(new StringRedisSerializer());
48         template.afterPropertiesSet();
49 
50         return template;
51     }
52 
53 }
RedisConfig

再次redis中查看缓存对象:redis中中文乱码,但是存取没影响

192.168.6.3:6379> keys *
1) "city_2"
192.168.6.3:6379> get city_2
"["com.redis.springbootredis.pojo.City",{"id":2,"name":"xe5xa4xa9xe6xb4xa5","description":"xe6xacxa2xe8xbfx8exe4xbdxa0xe6x9dxa5xe6x8cxa4xe5x9cxb0xe9x93x81","createDate":["java.sql.Timestamp",1557737066000]}]"

换个姿势再来一次

如何在get时取到它的中文呢?只需要在redis-cli 后面加上 –raw

192.168.6.3:6379> QUIT
[root@localhost src]# ./redis-cli -h 192.168.6.3 -p 6379 --raw
192.168.6.3:6379> keys *
city_2
192.168.6.3:6379> get city_2
["com.redis.springbootredis.pojo.City",{"id":2,"name":"天津","description":"欢迎你来挤地铁","createDate":["java.sql.Timestamp",1557737066000]}]

有兴趣的朋友可以查看本人的spring-boot-redis:GitHub项目

原文地址:https://www.cnblogs.com/brokencolor/p/10867650.html