【缓存篇】Spring Boot Cache 组合 Redis 实践缓存

写在最前

本文在 【缓存篇】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:条件符合则缓存;

Spring Cache 组合 Redis

Demo 地址:mingyue-springboot-cache

1.添加项目依赖


<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);
    }
    

4.测试接口

第一次请求

日志输出如下:

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

【缓存篇】Spring Boot Cache 组合 Redis 实践缓存_第1张图片

常见错误

实体类没有 implements Serializable

报错如下:

 DefaultSerializer requires a Serializable payload but received an object of type

错误原因:

要缓存的 Java 对象必须实现 Serializable 接口,因为 Spring 会将对象先序列化再存入缓存中。

你可能感兴趣的:(Spring,全家桶,spring,boot,spring,cache,redis)