一、介绍
从3.1开始,Spring引入了对Cache的支持。其使用方法和原理都类似于Spring对事务管理的支持。即可以使用注解的方式以及通过XML配置然后通过AOP切面来实现在具体的位置进行缓存。Spring Cache可以作用在类或方法上,对于Spring如果是注解的方式,则需要在配置文件中开启cache支持,并在相应的方法上使用cache注解。如果是XML配置,就需要配置XML和切面。对于Spring Boot而言,使用注解的方式则需要在启动类上开启cache,然后在具体业务逻辑代码中使用cache。
对于cache其核心思想是这样的:当我们在调用一个缓存方法时会把该方法参数和返回结果作为一个键值对存放在缓存中,等到下次利用同样的参数来调用该方法时将不再执行该方法,而是直接从缓存中获取结果进行返回。所以在使用Spring Cache的时候我们要保证我们缓存的方法对于相同的方法参数要有相同的返回结果。
在 spring-context 包中定义了org.springframework.cache.Cache 和 org.springframework.cache.
CacheManager 两个接口来统一不同的缓存技术。Cache 接口包含缓存的常用操作:增加、删除、读取等。CacheManager 是 Spring 各种缓存的抽象接口。常用的CacheManager的实现类有:
SimpleCacheManager:使用简单的 Collection 来存储缓存
ConcurrentMapCacheManager:使用 java.util.ConcurrentHashMap 来实现缓存
NoOpCacheManager:仅测试用,不会实际存储缓存
EhCacheCacheManger:使用EhCache作为缓存技术。EhCache 是一个纯 Java 的进程内缓存框架,特点快速、精干,是 Hibernate 中默认的 CacheProvider,也是 Java 领域应用最为广泛的缓存
JCacheCacheManager:支持JCache(JSR-107)标准的实现作为缓存技术
CaffeineCacheManager:使用 Caffeine 作为缓存技术。用于取代 Guava 缓存技术。
RedisCacheManager:使用Redis作为缓存技术
HazelcastCacheManager:使用Hazelcast作为缓存技术
CompositeCacheManager:用于组合 CacheManager,可以从多个 CacheManager 中轮询得到相应的缓存
二、Spring Cache注解
Spring Cache主要有一下注解:1
2
3
4
5
6
7
8
9
10
11 :开启缓存功能,用于主启动类上
"cacheName"})注解在 class 之上来统一指定value的值,用来区分不同namespace的缓存,在清除时,可以用到缓存名进行清除 :使用 (cacheNames = {
@Cacheable:用在方法上,标明方法可以使用缓存,并将查询结果放入缓存。一般用于查询方法
@CachePut:使用该注解标志的方法,每次都会执行,并将结果存入指定的缓存中。其他方法可以直接从响应的缓存中读取缓存数据,在spring boot中用在insert中会有问题,建议使用@CacheEvict
@CacheEvict:使用该注解标志的方法,会清空指定的缓存。一般用在更新或者删除方法上,根据cachename和key清除,同上面的改动,也是根据cachename和key
@Caching:在一个方法上使用多种类型的注解,源码如下
public @interface Caching {
Cacheable[] cacheable() default {};
CachePut[] put() default {};
CacheEvict[] evict() default {};
}
1.Cacheable的属性详解:
2.@CachePut
3.@CacheEvict
三、Spring boot使用
1.pom.xml1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-cache -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
<version>2.4.0</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.4</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
2.application.yml1
2
3
4
5
6
7
8
9
10
11
12spring:
application:
name: spring-cache
datasource:
username: root
password: 123456
url: jdbc:mysql://localhost:3306/person?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
driver-class-name: com.mysql.cj.jdbc.Driver
mybatis:
configuration:
cache-enabled: true
3.pojo1
2
3
4
5
6
7
8
9
true) (chain =
public class User implements Serializable {
private int id;
private String name;
private String auth;
}
4.mapper1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19package com.zhaixin.mapper;
import com.zhaixin.pojo.User;
import org.apache.ibatis.annotations.*;
import org.springframework.stereotype.Repository;
public interface UserMapper {
"select * from user where id = #{id}") (
User getUserById(@Param(value = "id") int id);
"insert into user (name,auth) values (#{name},#{auth})") (
"id", useGeneratedKeys = true) (keyProperty =
void insertUser(User user);
"update user set name = #{name} where id = #{id}") (
void updateUser(User user);
}
5.service1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57package com.zhaixin.service;
import com.zhaixin.pojo.User;
public interface UserService {
User getUserById(int id);
void insertUser(User user);
void updateUser(User user);
}
package com.zhaixin.service;
import com.zhaixin.mapper.UserMapper;
import com.zhaixin.pojo.User;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
"userCache") (cacheNames =
public class UserServiceImpl implements UserService{
UserMapper userMapper;
UserServiceImpl(UserMapper userMapper) {
this.userMapper = userMapper;
}
"user", key = "#id") (cacheNames =
public User getUserById(int id) {
System.out.println("调用getUserById");
return userMapper.getUserById(id);
}
//@CachePut 出现问题,缓存的只是结果,获取insert数据时,只是插入的结果1
"user", key = "#user.id") (cacheNames =
public void insertUser(User user) {
System.out.println("调用insert");
userMapper.insertUser(user);
}
"user", key = "#user.id") (cacheNames =
public void updateUser(User user) {
System.out.println("调用update");
userMapper.updateUser(user);
}
"userCache", allEntries = true) (value =
public void deleteCache() {
System.out.println("清除所有缓存");
}
}
6.controller1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29package com.zhaixin.controller;
import com.zhaixin.pojo.User;
import com.zhaixin.service.UserServiceImpl;
import org.springframework.web.bind.annotation.*;
public class UserController {
UserServiceImpl userService;
UserController(UserServiceImpl userService) {
this.userService = userService;
}
"/user/{id}") (
public User getUserById(@PathVariable int id){
return userService.getUserById(id);
}
"/user/insert") (
public void insertUser(@RequestBody User user){
userService.insertUser(user);
}
"/user/update") (
public void updateUserById(@RequestBody User user){
userService.updateUser(user);
}
}
7.主启动类1
2
3
4
5
6
7
8
9
10
11
12
13
14
15package com.zhaixin;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
public class SpringCacheApplication {
public static void main(String[] args) {
SpringApplication.run(SpringCacheApplication.class, args);
}
}
参考:
https://juejin.cn/post/6844903966615011335
https://www.cnblogs.com/fashflying/p/6908028.html
https://my.oschina.net/u/4362704/blog/3308079