本文在 【缓存篇】Spring Boot 整合 Redis 缓存数据 基础上优化 Redis 在 Spring Boot 中缓存实践!
Spring Cache 介绍Spring Cache 是 Spring 提供的一整套的缓存解决方案。虽然它本身并没有提供缓存的实现,但是它提供了一整套的接口和代码规范、配置、注解等。
Spring Cache 利用了 AOP,实现了基于注解的缓存功能,并且进行了合理的抽象,业务代码不用关心底层是使用了什么缓存框架,只需要简单地加一个注解,就能实现缓存功能了。比如 Redis、Ehcache,我们也就不用关心 *** 作缓存的细节。
支持的缓存中间件- caffeine:Caffeine 是一种高性能的缓存库,基于 Google Guava。
- couchbase:CouchBase是一款非关系型 JSON 文档数据库。
- generic:由泛型机制和 static 组合实现的泛型缓存机制。
- hazelcast:一个高度可扩展的数据分发和集群平台,可用于实现分布式数据存储、数据缓存。
- infinispan:分布式的集群缓存系统。
- jcache:JCache 作为缓存。它是 JSR107 规范中提到的缓存规范。
- redis:用 Redis 作为缓存。
- simple:用内存作为缓存。
注解 | 说明 |
---|---|
@EnableCaching | 开启缓存功能,一般放在启动类上 |
@Cacheable | 使用该注解的方法当缓存存在时,会从缓存中获取数据而不执行方法,当缓存不存在时,会执行方法并把返回结果存入缓存中。一般使用在查询方法上 |
@CachePut | 使用该注解的方法每次执行时都会把返回结果存入缓存中。一般使用在新增方法上 |
@CacheEvict | 使用该注解的方法执行时会清空指定的缓存。一般使用在更新或删除方法上 |
注解属性:
- value:缓存名称(必填),指定缓存的命名空间;
- key:用于设置在命名空间中的缓存key值,可以使用SpEL表达式定义;
- unless:条件符合则不缓存;
- condition:条件符合则缓存;
1.添加项目依赖Demo 地址:mingyue-springboot-cache
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-data-redisartifactId>
dependency>
2.开启缓存
启动类上添加 @EnableCaching 注解启动缓存功能
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
/** @author Strive */
@MapperScan("com.csp.mingyue.cache.mapper")
@SpringBootApplication
@EnableCaching
public class MingYueSpringbootCacheApplication {
public static void main(String[] args) {
SpringApplication.run(MingYueSpringbootCacheApplication.class, args);
}
}
3.修改缓存使用
-
原 Redis 缓存使用:
/** * 根据用户ID查询用户信息 * * @param userId 用户ID * @return 用户信息 */ public MingYueUser queryUserById(Long userId) { log.info("根据用户ID查询用户信息"); // 查询缓存中是否有查询的数据 String userJson = redisService.get(USER_REDIS_KEY + userId); // 缓存中没有数据则去数据库查询 if (StrUtil.isBlank(userJson)) { log.info("缓存中没有数据则去数据库查询"); MingYueUser mingYueUser = sysUserMapper.selectById(userId); // 查询的结果放入缓存 redisService.set(USER_REDIS_KEY + userId, JSONUtil.toJsonStr(mingYueUser)); // 返回查询到的数据 return mingYueUser; } log.info("缓存中有对应数据直接返回"); // 缓存中有对应数据直接返回 return JSONUtil.toBean(userJson, MingYueUser.class); }
-
改造后 Redis 缓存使用:
/** * 根据用户ID查询用户信息 * * @param userId 用户ID * @return 用户信息 */ @Cacheable( value = REDIS_KEY_DATABASE, key = USER_REDIS_KEY + "+#userId", unless = "#result==null") public MingYueUser queryUserById(Long userId) { log.info("根据用户ID查询用户信息"); return sysUserMapper.selectById(userId); }
日志输出如下:
2022-04-21 14:03:00.563 INFO 40900 --- [nio-8080-exec-2] c.c.m.cache.service.MingYueUserService : 根据用户ID查询用户信息
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@21b10bb6] was not registered for synchronization because synchronization is not active
2022-04-21 14:03:00.582 INFO 40900 --- [nio-8080-exec-2] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting...
2022-04-21 14:03:01.406 INFO 40900 --- [nio-8080-exec-2] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed.
JDBC Connection [HikariProxyConnection@1095569943 wrapping com.mysql.cj.jdbc.ConnectionImpl@1f903c0] will not be managed by Spring
==> Preparing: SELECT user_id,username FROM sys_user WHERE user_id=?
==> Parameters: 2(Long)
<== Columns: user_id, username
<== Row: 2, Strive
<== Total: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@21b10bb6]
第二次请求
logback-spring.xml 增加缓存日志输出或者配置文件增加缓存日志输出
<logger name="org.springframework.cache" level="trace"/>
logging.level.org.springframework.cache=TRACE
日志输出如下:
2022-04-21 14:05:50.566 TRACE 38512 --- [nio-8080-exec-1] o.s.cache.interceptor.CacheInterceptor : Computed cache key 'user:info:2' for operation Builder[public com.csp.mingyue.cache.model.MingYueUser com.csp.mingyue.cache.service.MingYueUserService.queryUserById(java.lang.Long)] caches=[mingyue] | key=''user:info:'+#userId' | keyGenerator='' | cacheManager='' | cacheResolver='' | condition='' | unless='#result==null' | sync='false'
2022-04-21 14:05:51.371 TRACE 38512 --- [nio-8080-exec-1] o.s.cache.interceptor.CacheInterceptor : Cache entry for key 'user:info:2' found in cache 'mingyue'
查看 Redis
常见错误
实体类没有 implements Serializable
报错如下:
DefaultSerializer requires a Serializable payload but received an object of type
错误原因:
要缓存的 Java 对象必须实现 Serializable 接口,因为 Spring 会将对象先序列化再存入缓存中。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)