springboot下用cache注解整合redis并使用json序列化反序列化。

cache注解整合redis

最近发现spring的注解用起来真的是很方便。随即产生了能不能吧spring注解使用redis实现的方式。

只需要在配置文件中(application.propertoes)添加如下一个配置

spring.cache.type=redis

并配置好redis的相关信息

spring.redis.database=0
spring.redis.host=
spring.redis.port=
spring.redis.password=
spring.redis.timeout=5000ms
spring.redis.lettuce.pool.max-active=8
spring.redis.lettuce.pool.max-wait=-1ms
spring.redis.lettuce.pool.max-idle=8
spring.redis.lettuce.pool.min-idle=0

springcache注解整合redis非常容易就整合完成了。

redis缓存序列化与反序列化

由于缓存数据使用的是jdk自带的序列化 需要序列化的实体类继承Serializable接口。而且序列化后的内容在redis中看起来也不是很方便。

于是萌生了需要将数据序列化成json的想法。

经过一番研究后决定写一个redis 配置文件。RedisConfig具体内容如下


@Configuration
public class RedisConfig extends CachingConfigurerSupport { @Bean
public RedisCacheConfiguration redisCacheConfiguration(){
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
RedisCacheConfiguration configuration = RedisCacheConfiguration.defaultCacheConfig();
configuration = configuration.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer)).entryTtl(Duration.ofDays(30));
return configuration;
} @Bean
public CacheManager cacheManager(RedisConnectionFactory connectionFactory) {
//初始化一个RedisCacheWriter
RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(connectionFactory);
//设置CacheManager的值序列化方式为 fastJsonRedisSerializer,但其实RedisCacheConfiguration默认使用StringRedisSerializer序列化key,
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
RedisSerializationContext.SerializationPair<Object> pair = RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer);
RedisCacheConfiguration defaultCacheConfig=RedisCacheConfiguration.defaultCacheConfig().serializeValuesWith(pair);
return new RedisCacheManager(redisCacheWriter, defaultCacheConfig);
}
}

配置完成后,数据访问序列化都非常正常,redis中也可以看到有序的json数据。

{
"name": "long",
"age": 18,
"height": 1.72
}

但是。。。。

当再次访问时出现了一个奇怪的问题。

LinkedHashMap 不能转换为实体类。

java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to com.alance.springcachedemo.entity.User

这看起来很像泛型丢失啊。

随即第三版配置文件出炉了,配置一下序列化的泛型保存

@Configuration
public class RedisConfig extends CachingConfigurerSupport { @Bean
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(factory);
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
MyObjectMapper objectMapper = new MyObjectMapper();
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.afterPropertiesSet();
return redisTemplate;
} @Bean
public CacheManager cacheManager(RedisConnectionFactory factory) {
RedisSerializer<String> redisSerializer = new StringRedisSerializer();
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
MyObjectMapper objectMapper = new MyObjectMapper();
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
// 配置序列化
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
RedisCacheConfiguration redisCacheConfiguration = config.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer)).serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer));
return RedisCacheManager.builder(factory).cacheDefaults(redisCacheConfiguration).build(); } private class MyObjectMapper extends ObjectMapper { private static final long serialVersionUID = 1L; public MyObjectMapper() {
super();
// 去掉各种@JsonSerialize注解的解析
this.configure(MapperFeature.USE_ANNOTATIONS, false);
// 只针对非空的值进行序列化
this.setSerializationInclusion(JsonInclude.Include.NON_NULL);
// 将类型序列化到属性json字符串中
this.enableDefaultTyping(DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
// 对于找不到匹配属性的时候忽略报错
this.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
// 不包含任何属性的bean也不报错
this.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
}
} }

好了这下反序列化的问题解决了,

redis中

[
"com.alance.springcachedemo.entity.User",
{
"name": "long",
"age": 18,
"height": 1.72
}
]

redis存储的json中带上了类型

至此这个问题就解决了。

后记

在愉快使用缓存注解的时候,发现缓存注解并 不能和诸如事务注解线程池注解一起使用。这是aop代理的特性决定的。而且 方法的类内部调用也不走注解

enableDefaultTyping 这个功能涉及到java著名的反序列化漏洞。各位系统之间调用数据的项目还是慎重使用.

漏洞详情

后记的后记

在写代码的过程中发现了一个更优雅的解决方案分享给大家。

只需要在配置文件中配置一下CacheManger,使用jackson的一个带泛型的序列化工具实现。

    /**
* spring cache 注解相关序列化操作
*/
@Bean
public CacheManager cacheManager(RedisConnectionFactory factory) {
GenericJackson2JsonRedisSerializer genericJackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
// 配置序列化
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
RedisCacheConfiguration redisCacheConfiguration = config
// 键序列化方式 redis字符串序列化
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(stringRedisSerializer))
// 值序列化方式 简单json序列化
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(genericJackson2JsonRedisSerializer));
return RedisCacheManager.builder(factory).cacheDefaults(redisCacheConfiguration).build(); }
大佬的启发

https://www.cnblogs.com/Kidezyq/p/8942111.html

springboot 用redis缓存整合spring cache注解,使用Json序列化和反序列化。的更多相关文章

  1. 【Spring】17、spring cache 与redis缓存整合

    spring cache,基本能够满足一般应用对缓存的需求,但现实总是很复杂,当你的用户量上去或者性能跟不上,总需要进行扩展,这个时候你或许对其提供的内存缓存不满意了,因为其不支持高可用性,也不具备持 ...

  2. springboot整合spring @Cache和Redis

    转载请注明出处:https://www.cnblogs.com/wenjunwei/p/10779450.html spring基于注解的缓存 对于缓存声明,spring的缓存提供了一组java注解: ...

  3. springboot+shiro+redis项目整合

    介绍: Apache Shiro是一个强大且易用的Java安全框架,执行身份验证.授权.密码学和会话管理.使用Shiro的易于理解的API,您可以快速.轻松地获得任何应用程序,从最小的移动应用程序到最 ...

  4. SpringBoot使用redis缓存List<Object>

    一.概述 最近在做性能优化,之前有一个业务是这样实现的: 1.温度报警后第三方通讯管理机直接把报警信息保存到数据库 2.我们在数据库中添加触发器,(BEFORE INSERT)根据这条报警信息处理业务 ...

  5. SpringBoot使用Redis缓存

    (1).添加依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId&g ...

  6. 【redis】3.Spring 集成注解 redis 项目配置使用

    spring-data-redis  项目,配合 spring 特性并集成 Jedis 的一些命令和方法. 配置redis继承到spring管理项目,使用注解实现redis缓存功能. 参考:http: ...

  7. Java SpringBoot使用Redis缓存和Ehcache

    <?xml version="1.0" encoding="UTF-8"?> <ehcache xmlns:xsi="http:// ...

  8. SpringBoot(七) - Redis 缓存

    1.五大基本数据类型和操作 1.1 字符串-string 命令 说明 set key value 如果key还没有,那就可以添加,如果key已经存在了,那会覆盖原有key的值 get key 如果ke ...

  9. spring Cache注解

    如下:不能将缓存注解加在listCate(boolean isShowHide)方法上 因为spring是使用AOP的方法获取缓存,在一个bean中再去调用别一个方法,不会应用缓存 @Cacheabl ...

随机推荐

  1. HZOJ 20190727 随(倍增优化dp)

    达哥T1 实际上还是挺难的,考试时只qj20pts,还qj失败 因为他专门给出了mod的范围,所以我们考虑把mod加入时间复杂度. $50\%$算法: 考虑最暴力的dp,设$f[i][j]$表示进行$ ...

  2. luoguP1739 表达式括号匹配 x

    P1739 表达式括号匹配 题目描述 假设一个表达式有英文字母(小写).运算符(+,—,*,/)和左右小(圆)括号构成,以“@”作为表达式的结束符.请编写一个程序检查表达式中的左右圆括号是否匹配,若匹 ...

  3. Java的当中的泛型

    Java当中的泛型 01 import java.util.ArrayList; import java.util.List; public class Demo{ public static voi ...

  4. BOM基础笔记

    BOM基础 BOM对浏览器的一些操作 1.打开.关闭窗口 •open –蓝色理想运行代码功能 window.open('http://www.baidu.com/', '_self'); <!d ...

  5. JavaWeb_(Hibernate框架)Hibernate中创建实体

    Hibernate中创建实体 创建实体五个基本规则 --提供无参的构造器 --成员变量的私有化,提供get.set方法,提供属性 --尽量使用包装类型 --主键(一定要有) --不要加final(hi ...

  6. SRS之SrsRtmpConn::publishing详解

    1. SrsRtmpConn::publishing int SrsRtmpConn::publishing(SrsSource* source) { int ret = ERROR_SUCCESS; ...

  7. HBuilder开发MUI web app溢出页面上下无法滚动问题

    因为没有对页面初始化,所以页面溢出部分不会显示,要解决此问题需要加上下面代码: JS代码: (function($){$(".mui-scroll-wrapper").scroll ...

  8. nginx的请求限制

    一.http协议的连接与请求 总结: HTTP请求是建立在一次TCP连接的基础之上. 一次TCP请求至少产生一次HTTP请求. 二.连接限制 limit_conn_module 配置语法: Synta ...

  9. numpy之数组计算

    # coding=utf-8import numpy as npimport random #数组和数字计算,进行广播计算,包括加减乘除 t8 = t8 +2 print(t8,t8.dtype,t8 ...

  10. python的XML解析

    http://www.jb51.net/article/63780.htm http://www.runoob.com/python/python-xml.html http://kb.cnblogs ...