SpringBoot2.x操作缓存的新姿势
一、介绍
spring cache 是spring3版本之后引入的一项技术,可以简化对于缓存层的操作,spring cache与springcloud stream类似,都是基于抽象层,可以任意切换其实现。其核心是CacheManager、Cache这两个接口,所有由spring整合的cache都要实现这两个接口、Redis的实现类则是 RedisCache 和 RedisManager。
二、使用
Ⅰ、查询
需要导入的依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
编写对于cache的配置
@EnableCaching
@SpringBootConfiguration
public class CacheConfig { @Autowired
private RedisConnectionFactory connectionFactory; @Bean // 如果有多个CacheManager的话需要使用@Primary直接指定那个是默认的
public RedisCacheManager cacheManager() {
RedisSerializer<String> redisSerializer = new StringRedisSerializer();
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class); ObjectMapper om = new ObjectMapper();
// 防止在序列化的过程中丢失对象的属性
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
// 开启实体类和json的类型转换
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om); // 配置序列化(解决乱码的问题)
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig() .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer)) .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))
// 不缓存空值
.disableCachingNullValues()
// 1分钟过期
.entryTtl(Duration.ofMinutes(1))
;
RedisCacheManager cacheManager = RedisCacheManager.builder(connectionFactory)
.cacheDefaults(config)
.build();
return cacheManager;
}
}
进行以上配置即可使用springboot cache了,还有一个key的生成策略的配置(可选)
@Bean
public KeyGenerator keyGenerator() {
return (target, method, params) -> {
StringBuffer key = new StringBuffer();
key.append(target.getClass().getSimpleName() + "#" + method.getName() + "(");
for (Object args : params) {
key.append(args + ",");
}
key.deleteCharAt(key.length() - 1);
key.append(")");
return key.toString();
};
}
注意:如果配置了KeyGenerator ,在进行缓存的时候如果不指定key的话,最后会把生成的key缓存起来,如果同时配置了KeyGenerator 和key则优先使用key。
在controller或者service的类上面添加 @CacheConfig ,注解里面的参数详情见下表:
| 参数名 | 参数值 | 作用 |
|---|---|---|
| cacheNames | 可以随意填写,一般是一个模块或者一个很重要的功能名称 | 无具体作用,只是用来区分缓存,方便管理 |
| keyGenerator | 就是自己配置的KeyGenerator的名称 | 全局key都会以他的策略去生成 |
| cacheManager | 自己配置的CacheManager | 用来操作Cache对象的,很多对于缓存的配置也由他去管理 |
在标有@CacheConfig的类里面编写一个查询单个对象的方法并添加 @Cacheable注解
@Cacheable(key = "#id", unless = "#result == null")
@PatchMapping("/course/{id}")
public Course courseInfo(@PathVariable Integer id) {
log.info("进来了 .. ");
return courseService.getCourseInfo(id);
}
执行完该方法后,执行结果将会被缓存到Redis:

@Cacheable注解中参数详情见下表:
| 参数名 | 作用 |
|---|---|
| cacheNames | 被缓存的时候的命名空间 |
| key | 这里的key的优先级是最高的,可以覆盖掉全局配置的key,如果不配置的话使用的就是全局的key |
| keyGenerator | 指定的缓存的key的生成器,默认没有 |
| cacheManager | 指定要使用哪个缓存管理器。默认是底层自动配置的管理器 |
| condition | 满足什么条件会进行缓存,里面可以写简单的表达式进行逻辑判断 |
| unless | 满足什么条件不进行缓存,里面可以写简单的表达式进行逻辑判断 |
| sync | 加入缓存的这个操作是否是同步的 |
Ⅱ、 修改
编写一个修改的方法,参数传对象,返回值也改成这个对象
@PutMapping("/course")
public Course modifyCoruse(@RequestBody Course course) {
courseService.updateCourse(course);
return course;
}
在方法上面添加 @CachePut(key = "#course.id") 注解,这个注解表示将方法的返回值更新到缓存中,注解中的参数和 @Cacheable 中的一样,这里就略过了。
Ⅲ、 删除
编写删除方法,在方法上添加@CacheEvict 注解
@CacheEvict(key = "#id")
@DeleteMapping("/course/{id}")
public void removeCourse(@PathVariable Integer id) {
courseService.remove(id);
}
@CacheEvict 的参数信息见下表:
| 参数名 | 描述 |
|---|---|
| allEntries | 是否删除该命名空间下面的全部缓存,默认是false |
| beforeInvocation | 在执行删除方法前就执行清空缓存操作,默认是false,如果删除方法执行报错该注解则不执行 |
三、 基于代码的Cache的使用
因为我们有配置的CacheManager,所以可以利用RedisCacheManager对象去手动操作cache,首先将CacheManager注入进来:
@Resource
private CacheManager cacheManager; @PatchMapping("/course2/{id}")
public Course course2(@PathVariable Integer id) {
// 获取指定命名空间的cache
Cache cache = cacheManager.getCache("course");
// 通过key获取对应的value
Cache.ValueWrapper wrapper = cache.get(2);
if (wrapper == null) {
// 查询数据库
Course course = courseService.getCourseInfo(id);
// 加入缓存
cache.put(course.getId(), course);
return course;
} else {
// 将缓存的结果返回
// 因为配置了enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
// 所以在进行强转的时候不会报错
return (Course) wrapper.get();
}
}
如果还看不明白,请去码云拉取源码 https://gitee.com/tianmaoliln/Spring-Boot-Cache.git
你想成为什么样的人,就会成为什么样的人!
SpringBoot2.x操作缓存的新姿势的更多相关文章
- 【转+自己研究】新姿势之Docker Remote API未授权访问漏洞分析和利用
0x00 概述 最近提交了一些关于 docker remote api 未授权访问导致代码泄露.获取服务器root权限的漏洞,造成的影响都比较严重,比如 新姿势之获取果壳全站代码和多台机器root权限 ...
- Broadcom BCM94352z/DW1560驱动新姿势
转自:https://blog.daliansky.net/Broadcom-BCM94352z-DW1560-drive-new-posture.html Broadcom WiFi/BlueToo ...
- vue组件通信新姿势
在vue项目实际开发中我们经常会使用props和emit来进行子父组件的传值通信,父组件向子组件传递数据是通过prop传递的, 子组件传递数据给父组件是通过$emit触发事件来做到的.例如: Vue. ...
- Java计时新姿势
为获得更好的阅读体验,请访问原文:传送门 前言: 最近公司来了个大佬,从他那里学到不少东西,其中一个就是计时 的新姿势「StopWatch」,赶紧来一起了解了解吧! 一.最简单的计时 在我们的程序中不 ...
- FJNU 1159 Fat Brother’s new way(胖哥的新姿势)
FJNU 1159 Fat Brother’s new way(胖哥的新姿势) Time Limit: 1000MS Memory Limit: 257792K [Description] [题目 ...
- [Cache] C#操作缓存--CacheHelper缓存帮助类 (转载)
点击下载 CacheHelper.zip CacheHelper 缓存帮助类 C#怎么操作缓存 怎么设置和取缓存数据,都在这个类里面呢 下面看一下代码吧 /// <summary> /// ...
- JSON CSRF新姿势
以前做渗透测试,遇到过很多次POST数据为JSON数据的CSRF,一直没有搞定,最近发现一个新姿势, 本文作者:Mannix@安全文库 微信公众号:安全文库 测试的时候,当应用程序验证了Cont ...
- 转载 Python 操作 MySQL 的正确姿势 - 琉璃块
Python 操作 MySQL 的正确姿势 收录待用,修改转载已取得腾讯云授权 作者 |邵建永 编辑 | 顾乡 使用Python进行MySQL的库主要有三个,Python-MySQL(更熟悉的名字可能 ...
- bzoj1656: [Usaco2006 Jan] The Grove 树木 (bfs+新姿势)
题目大意:一个n*m的图中,“.”可走,“X”不可走,“*”为起点,问从起点开始绕所有X一圈回到起点最少需要走多少步. 一开始看到这题,自己脑洞了下怎么写,应该是可过,然后跑去看了题解,又学会了一 ...
随机推荐
- (1)解锁 MongoDB replica set核心姿势
副本集Replica Set是一个术语,定义具有多节点的数据库集群,这些节点具有主从复制(master-slave replication) 且节点之间实现了自动故障转移. 这样的结构通常需要具有奇数 ...
- docker使用阿里云加速器
1 登录阿里云获得地址 登录https://cr.console.aliyun.com ,点击"镜像加速器",会给我一个地址. 2 写入/etc/docker/daemon.jso ...
- cogs 3008. 朋友圈
3008. 朋友圈 ★★ 输入文件:friendscircle.in 输出文件:friendscircle.out 简单对比时间限制:1 s 内存限制:256 MB [题目描述] NO ...
- JVM性能优化系列-(2) 垃圾收集器与内存分配策略
2. 垃圾收集器与内存分配策略 垃圾收集(Garbage Collection, GC)是JVM实现里非常重要的一环,JVM成熟的内存动态分配与回收技术使Java(当然还有其他运行在JVM上的语言,如 ...
- python中各种文件打开模式
在python中,总的来说有三种大的模式打开文件,分别是:a, w, r 当以a模式打开时,只能写文件,而且是在文件末尾添加内容. 当以a+模式打开时,可以写文件,也可读文件,可是在读文件的时候,会发 ...
- dp-完全背包
( 推荐 : http://blog.csdn.net/insistgogo/article/details/11081025 ) 问题描述 : 已知一个容量为 V 的背包 和 N 件物品 , 第 ...
- Java8 新特性(三) - 日期时间对象以及一些其他特性
日期时间对象 关于日期时间的操作可以分为两种: 转换:与字符串的互相转换,与时间戳的互相转换 计算:计算两个时间点之间的间隔.时间点与时间段的计算(计算下周N.下个月D日.去年M月D日等等) Java ...
- 关于爬虫的日常复习(14)—— 爬虫beautifulsoup的初级高级的基本用法
- 代码审计之CVE-2017-6920 Drupal远程代码执行漏洞学习
1.背景介绍: CVE-2017-6920是Drupal Core的YAML解析器处理不当所导致的一个远程代码执行漏洞,影响8.x的Drupal Core. Drupal介绍:Drupal 是一个由 ...
- (树形DP)Strategic game POJ - 1463
题意: 给你一棵树,树的每一个节点可以守护与其相连的所有边,问你最少用多少个节点可以守护这整棵树 思路: 仔细思考不难发现,要想守护一条边,边的两个端点必须有一个可以被选(两个都选也可以),然后这个问 ...