Spring Cache 提供了 @Cacheable 、@CachePut 、@CacheEvict 、@Caching 等注解,在方法上使用。通过注解 Cache 可以实现类似事务一样、缓存逻辑透明的应用到我们的业务代码上,且只需要更少的代码。 核心思想:当我们调用一个方法时会把该方法的参数和返回结果最为一个键值对存放在缓存中,等下次利用同样的参数来调用该方法时将不会再执行,而是直接从缓存中获取结果进行返回。
根据方法对其返回结果进行缓存,下次请求时,如果缓存存在,则直接读取缓存数据返回;如果缓存不存在,则执行方法,并把返回的结果存入缓存中。一般用在查询方法上。 该注解的属性值如下:
value 缓存名,必填
key 可选属性,可以使用 SPEL 标签自定义缓存的key
condition 指定发生的条件
使用该注解标志的方法,每次都会执行,并将结果存入指定的缓存中。其他方法可以直接从响应的缓存中读取缓存数据,而不需要再去查询数据库。一般用在新增方法上。 该注解的属性值如下:
value 缓存名,必填
key 可选属性,可以使用 SPEL 标签自定义缓存的key
使用该注解标志的方法,会清空指定的缓存。一般用在更新或者删除方法上 该注解的属性值如下:
value 缓存名,必填
key 可选属性,可以使用 SPEL 标签自定义缓存的key
condition 指定发生的条件
allEntries 是否清空所有缓存,默认为 false。如果指定为 true,则方法调用后将立即清空所有的缓存
beforeInvocation 是否在方法执行前就清空,默认为 false。如果指定为 true,则在方法执行前就会清空缓存
该注解可以实现同一个方法上同时使用多种注解。可从其源码看出:
public @interface Caching {
Cacheable[] cacheable() default {};
CachePut[] put() default {};
CacheEvict[] evict() default {};
}
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.9.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>cn.zwqh</groupId>
<artifactId>spring-boot-cache</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-boot-cache</name>
<description>spring-boot-cache</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- Spring Cache -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<!-- jdbc -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!-- 热部署模块 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional> <!-- 这个需要为 true 热部署才有效 -->
</dependency>
<!-- mysql 数据库驱动. -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- mybaits -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
#datasource
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/db_test?useUnicode=true&characterEncoding=UTF-8&useSSL=true
spring.datasource.username=root
spring.datasource.password=123456
#mybatis
mybatis.mapper-locations=classpath:/mapper/*Mapper.xml
public class UserEntity {
private Long id;
private String userName;
private String userSex;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getUserSex() {
return userSex;
}
public void setUserSex(String userSex) {
this.userSex = userSex;
}
}
public interface UserDao {
//mapper.xml方式
/**
* 获取所有用户
* @return
*/
List<UserEntity> getAll();
/**
* 根据id获取用户
* @return
*/
UserEntity getOne(Long id);
/**
* 新增用户
* @param user
*/
void insertUser(UserEntity user);
/**
* 修改用户
* @param user
*/
void updateUser(UserEntity user);
/**
* 删除用户
* @param id
*/
void deleteUser(Long id);
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.4//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.zwqh.springboot.dao.UserDao">
<resultMap type="cn.zwqh.springboot.model.UserEntity" id="user">
<id property="id" column="id"/>
<result property="userName" column="user_name"/>
<result property="userSex" column="user_sex"/>
</resultMap>
<!-- 获取所有用户 -->
<select id="getAll" resultMap="user">
select * from t_user
</select>
<!-- 根据用户ID获取用户 -->
<select id="getOne" resultMap="user">
select * from t_user where id=#{id}
</select>
<!-- 新增用户 -->
<insert id="insertUser" parameterType="cn.zwqh.springboot.model.UserEntity">
insert into t_user (user_name,user_sex) values(#{userName},#{userSex})
</insert>
<!-- 修改用户 -->
<update id="updateUser" parameterType="cn.zwqh.springboot.model.UserEntity">
update t_user set user_name=#{userName},user_sex=#{userSex} where id=#{id}
</update>
<!-- 删除用户 -->
<delete id="deleteUser" parameterType="Long">
delete from t_user where id=#{id}
</delete>
</mapper>
public interface UserService {
/**
* 查找所有
* @return
*/
List<UserEntity> getAll();
/**
* 根据id获取用户
* @param id
* @return
*/
UserEntity getOne(Long id);
/**
* 新增用户
* @param user
*/
void insertUser(UserEntity user);
/**
* 修改用户
* @param user
*/
void updateUser(UserEntity user);
}
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserDao userDao;
@Override
@Cacheable("userList") // 标志读取缓存操作,如果缓存不存在,则调用目标方法,并将结果放入缓存
public List<UserEntity> getAll() {
System.out.println("缓存不存在,执行方法");
return userDao.getAll();
}
@Override
@Cacheable(cacheNames = { "user" }, key = "#id")//如果缓存存在,直接读取缓存值;如果缓存不存在,则调用目标方法,并将结果放入缓存
public UserEntity getOne(Long id) {
System.out.println("缓存不存在,执行方法");
return userDao.getOne(id);
}
@Override
@CachePut(cacheNames = { "user" }, key = "#user.id")//写入缓存,key为user.id,一般该注解标注在新增方法上
public void insertUser(UserEntity user) {
System.out.println("写入缓存");
userDao.insertUser(user);
}
@Override
@CacheEvict(cacheNames = { "user" }, key = "#user.id")//根据key清除缓存,一般该注解标注在修改和删除方法上
public void updateUser(UserEntity user) {
System.out.println("清除缓存");
userDao.updateUser(user);
}
}
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
/**
* 查找所有
* @return
*/
@RequestMapping("/getAll")
public List<UserEntity> getAll(){
return userService.getAll();
}
/**
* 根据id获取用户
* @return
*/
@RequestMapping("/getOne")
public UserEntity getOne(Long id){
return userService.getOne(id);
}
/**
* 新增用户
* @param user
* @return
*/
@RequestMapping("/insertUser")
public String insertUser(UserEntity user) {
userService.insertUser(user);
return "insert success";
}
/**
* 修改用户
* @param user
* @return
*/
@RequestMapping("/updateUser")
public String updateUser(UserEntity user) {
userService.updateUser(user);
return "update success";
}
}
@SpringBootApplication
@MapperScan("cn.zwqh.springboot.dao")
@EnableCaching //启动 Cache 功能
public class SpringBootCacheApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootCacheApplication.class, args);
}
}
数据库和测试数据仍旧用之前的。
通过访问 http://127.0.0.1:8080/user/
加上对应路径和参数。
Spring Cache 使用操作还是比较简单的,它对这些缓存实现都做了非常好的集成适配,所以用起来相当平滑。