java对象以json的方式存储到redis中
-
通过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 *
\xac\xed\x00\x05t\x00\x06city_2
发现key值出现 \xac\xed\x00\x05t\x00\x06city_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.
e
v
a
l
u
a
t
e
(
P
a
r
e
n
t
R
u
n
n
e
r
.
j
a
v
a
:
268
)
25
a
t
o
r
g
.
s
p
r
i
n
g
f
r
a
m
e
w
o
r
k
.
t
e
s
t
.
c
o
n
t
e
x
t
.
j
u
n
i
t
4.
s
t
a
t
e
m
e
n
t
s
.
R
u
n
B
e
f
o
r
e
T
e
s
t
C
l
a
s
s
C
a
l
l
b
a
c
k
s
.
e
v
a
l
u
a
t
e
(
R
u
n
B
e
f
o
r
e
T
e
s
t
C
l
a
s
s
C
a
l
l
b
a
c
k
s
.
j
a
v
a
:
61
)
26
a
t
o
r
g
.
s
p
r
i
n
g
f
r
a
m
e
w
o
r
k
.
t
e
s
t
.
c
o
n
t
e
x
t
.
j
u
n
i
t
4.
s
t
a
t
e
m
e
n
t
s
.
R
u
n
A
f
t
e
r
T
e
s
t
C
l
a
s
s
C
a
l
l
b
a
c
k
s
.
e
v
a
l
u
a
t
e
(
R
u
n
A
f
t
e
r
T
e
s
t
C
l
a
s
s
C
a
l
l
b
a
c
k
s
.
j
a
v
a
:
70
)
27
a
t
o
r
g
.
j
u
n
i
t
.
r
u
n
n
e
r
s
.
P
a
r
e
n
t
R
u
n
n
e
r
.
r
u
n
(
P
a
r
e
n
t
R
u
n
n
e
r
.
j
a
v
a
:
363
)
28
a
t
o
r
g
.
s
p
r
i
n
g
f
r
a
m
e
w
o
r
k
.
t
e
s
t
.
c
o
n
t
e
x
t
.
j
u
n
i
t
4.
S
p
r
i
n
g
J
U
n
i
t
4
C
l
a
s
s
R
u
n
n
e
r
.
r
u
n
(
S
p
r
i
n
g
J
U
n
i
t
4
C
l
a
s
s
R
u
n
n
e
r
.
j
a
v
a
:
190
)
29
a
t
o
r
g
.
j
u
n
i
t
.
r
u
n
n
e
r
.
J
U
n
i
t
C
o
r
e
.
r
u
n
(
J
U
n
i
t
C
o
r
e
.
j
a
v
a
:
137
)
30
a
t
c
o
m
.
i
n
t
e
l
l
i
j
.
j
u
n
i
t
4.
J
U
n
i
t
4
I
d
e
a
T
e
s
t
R
u
n
n
e
r
.
s
t
a
r
t
R
u
n
n
e
r
W
i
t
h
A
r
g
s
(
J
U
n
i
t
4
I
d
e
a
T
e
s
t
R
u
n
n
e
r
.
j
a
v
a
:
68
)
31
a
t
c
o
m
.
i
n
t
e
l
l
i
j
.
r
t
.
e
x
e
c
u
t
i
o
n
.
j
u
n
i
t
.
I
d
e
a
T
e
s
t
R
u
n
n
e
r
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
2.evaluate(ParentRunner.java:268)25atorg.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)26atorg.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)27atorg.junit.runners.ParentRunner.run(ParentRunner.java:363)28atorg.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)29atorg.junit.runner.JUnitCore.run(JUnitCore.java:137)30atcom.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)31atcom.intellij.rt.execution.junit.IdeaTestRunnerRepeater.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 *
- “city_2”
192.168.6.3:6379> get city_2
“[“com.redis.springbootredis.pojo.City”,{“id”:2,“name”:”\xe5\xa4\xa9\xe6\xb4\xa5",“description”:"\xe6\xac\xa2\xe8\xbf\x8e\xe4\xbd\xa0\xe6\x9d\xa5\xe6\x8c\xa4\xe5\x9c\xb0\xe9\x93\x81",“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]}]