Spring Cache

268 阅读3分钟

一、Spring Cache介绍

Spring Cache是一个框架,实现了基于注解的缓存功能,只需要简单地加一个注解,就能实现缓存功能。

Spring Cache提供了一层抽象,底层可以切换不同的cache实现。具体就是通过CacheManager接口来统一不同的缓存技术。

CacheManager是Spring提供的各种缓存技术抽象接口。

针对不同的缓存技术需要实现不同的CacheManager:

CacheManager描述
EhCacheCacheManager(用的多)使用EhCache作为缓存技术
GuavaCacheManager使用Google的GuavaCache作为缓存技术
RedisCacheManager使用Redis作为缓存技术

Spring Cache jar包导入

基础功能:

​ 在start-web依赖下的spring-webmvc下的spring-context中

整合缓存工具:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
</dependency>

二、Spring Cache常用注解

注解说明
@EnableCaching开启缓存注解功能
@Cacheable在方法执行前spring先查看缓存中是否有数据,如果有数据,则直接返回缓存数据;若没有数据,调用方法并将方法返回值放到缓存中
@CachePut将方法的返回值放到缓存中
@CacheEvict将一条或多条数据从缓存中删除

​ 在spring boot项目中,使用缓存技术只需在项目中导入相关缓存技术的依赖包,并在启动类上使用@EnableCaching开启缓存支持即可。

​ 例如,使用Redis作为缓存技术,只需要导入Spring data Redis的maven坐标即可。

​ Spring Cache根据pom.xml中导入何种缓存依赖,确定使用缓存方式。

三、使用方式

1.使用基本的功能

​ 注入CacheManager,底层默认使用ConcurrentMap实现缓存;实现类为ConcurrentMapCacheManager

1.1@EnableCaching 开启缓存注解功能

​ 该注解添加在启动类上

1.2 @CachePut 方法的返回值放到缓存中

/**
	CachePut:将方法返回值放入缓存
	value:缓存的名称(根据存入方法对key分类),每个缓存名称下面可以有多个key
	key:缓存的key,注解中key可以用#加user.id获取方法完成后的返回值,必须保证user和接收的user一样
*/
@CachePut (value = "userCache", key = "#user.id")
@PostMapping
public User save(User user){
    userService.save (user);
    return user;
}

1.3@CacheEvict 一条或多条数据从缓存中删除

/**
	清理指定缓存
	@CacheEvict:在删除时传入key
    #id保持和传入参数一致
    #p是默认,后面0指传入的第一个参数
*/
//@CacheEvict(value ="userCache",key = "#id")
//@CacheEvict(value ="userCache",key = "#root.args[0]")
@CacheEvict(value ="userCache",key = "#p0")
@DeleteMapping("/{id}")
public void delete(@PathVariable Long id){
    userService. removeById(id);
}

1.4 @Cacheable

存在缓存是不会进入方法的,直接将缓存返回;如果方法内存在断点,在有缓存情况下不会触发;

/**
	先看是否存在缓存,有直接返回,没有查,存入缓存
   	存在缓存是不会进入方法的,直接将缓存返回
   	condition:条件,满足时才缓存数据(但是可以不加,无效id缓存空key可以解决缓存穿透问题)
   	unless = "#result == null"  为空时,不缓存
*/
//@Cacheable(value ="userCache",key ="#id" condition = "#result != null")存在问题,condition不能直接使用返回结果
@Cacheable(value ="userCache",key ="#id" unless = "#result == null")
@GetMapping("/{id}")
public User getById(@PathVariable Long id){
    User user = userService.getById(id);
    return user;
}

@Cacheable (value = "userCache", key = "#user. id + ‘_’ + #user.name")

1.4.1 存在缓存击穿现象

传入不存在的id,数据库查不到,但会被存入缓存中,导致双方数据不一致。

缓存击穿:全打在一个缓存上;访问热点key

缓存穿透:访问不存在的key,查不到缓存开始请求数据库,无效请求通过缓存访问到数据库

2.整合Redis

redis:
	host: 172.17.2.00
	port: 6379
	password: root@123
	database: 0
cache:
	redis:
		time-to-live: 180000 #缓存过期时间,自行设置

使用方法同上:

Record Date :2023/03/26