使用自定义序列化策略:FastJsonRedisSerializer
背景:
@Configuration
@ConditionalOnClass(RedisOperations.class)
@EnableConfigurationProperties(RedisProperties.class)
public class RedisConfig {
@Bean
@ConditionalOnMissingBean(name = "redisTemplate")
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
//使用fastjson序列化
FastJsonRedisSerializer fastJsonRedisSerializer = new FastJsonRedisSerializer(Object.class);
// value值的序列化采用fastJsonRedisSerializer
template.setValueSerializer(fastJsonRedisSerializer);
template.setHashValueSerializer(fastJsonRedisSerializer);
// key的序列化采用StringRedisSerializer
template.setKeySerializer(new StringRedisSerializer());
template.setHashKeySerializer(new StringRedisSerializer());
template.setConnectionFactory(redisConnectionFactory);
return template;
}
@Bean
@ConditionalOnMissingBean(StringRedisTemplate.class)
public StringRedisTemplate stringRedisTemplate(
RedisConnectionFactory redisConnectionFactory) {
StringRedisTemplate template = new StringRedisTemplate();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
}
在查询时:
List<String> normIdList = data.stream().map(d -> d.getNormId()).collect(Collectors.toList());
List<Map> results = redisTemplate.executePipelined((RedisCallback<Object>) connection -> {
for (String id : normIdList) {
connection.hGetAll((KEY_ + id).getBytes());
}
return null;
});
results = results.stream().filter(e -> e.keySet().size() > 0).collect(Collectors.toList());
if (results.size() == 0)
return;
List<HXCacheDto> hxCacheDtoList = JSON.parseArray(JSON.toJSONString(results), HXCacheDto.class);
1、此时 redisTemplate.executePipelined执行失败:
2022-11-11 17:58:00,164 [DESKTOP-K8FJ2UU] [ERROR] [http-nio-8080-exec-3] [683f5747-ff84-43fc-9a18-30c465bca8d2] [com.chinaunicom.planning.handler.GlobalExceptionHandler:33] Could not deserialize: syntax error, pos 1, line 1, column 2台州市玉环市分公司城关标准网格; nested exception is com.alibaba.fastjson.JSONException: syntax error, pos 1, line 1, column 2台州市玉环市分公司城关标准网格
org.springframework.data.redis.serializer.SerializationException: Could not deserialize: syntax error, pos 1, line 1, column 2台州市玉环市分公司城关标准网格; nested exception is com.alibaba.fastjson.JSONException: syntax error, pos 1, line 1, column 2台州市玉环市分公司城关标准网格
at com.alibaba.fastjson.support.spring.FastJsonRedisSerializer.deserialize(FastJsonRedisSerializer.java:67)
at org.springframework.data.redis.serializer.SerializationUtils.deserialize(SerializationUtils.java:100)
at org.springframework.data.redis.core.RedisTemplate.deserializeMixedResults(RedisTemplate.java:620)
at org.springframework.data.redis.core.RedisTemplate.lambda$executePipelined$1(RedisTemplate.java:328)
at org.springframework.data.redis.core.RedisTemplate$$Lambda$1026/306140947.doInRedis(Unknown Source)
at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:222)
at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:189)
at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:176)
at org.springframework.data.redis.core.RedisTemplate.executePipelined(RedisTemplate.java:317)
at org.springframework.data.redis.core.RedisTemplate.executePipelined(RedisTemplate.java:307)
解决方案:字符串类型需要在存入时用引号修饰
// 缓存字段类型是否转换string
static List<String> cacheFieldType = Arrays.asList("provCode", "provName", "cityCode", "cityName");
private void insertHX(List<Map> insertList) {
redisTemplate.executePipelined(new RedisCallback<List<Map>>() {
@Override
public List<Map> doInRedis(RedisConnection connection) throws DataAccessException {
for (Map<String, String> hashMap : insertList) {
String communityId = hashMap.get("normId");
hashMap.forEach((k, v) -> {
if (StringUtils.isNotBlank(v)) {
String d = v.replace("\\", "");
if (cacheFieldType.contains(k)) {
connection.hSet((KEY_ + communityId).getBytes(), k.getBytes(), ("'" + d + "'").getBytes());
} else {
connection.hSet((KEY_ + communityId).getBytes(), k.getBytes(), d.getBytes());
}
connection.expire((KEY_ + communityId).getBytes(), 60 * 60 * 22);
}
});
}
return null;
}
});
}
2、此时 redisTemplate.executePipelined执行依旧失败:
Could not deserialize: not close json text, token : int
解决方案:
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<!-- <version>1.2.83</version> 升级 -->
<version>2.0.10</version>
</dependency>
参考:https://blog.csdn.net/qq_21067307/article/details/126037615