spring boot利用redis作为缓存

一、缓存介绍

在 Spring Boot 中,可以使用 Spring Cache abstraction 来实现缓存功能。Spring Cache abstraction 是 Spring 框架提供的一个抽象层,它对底层缓存实现(如 Redis、Ehcache、Caffeine 等)进行了封装,使得在不同的缓存实现之间切换变得更加方便。

Spring Cache Abstraction 的实现原理主要是通过在运行时动态创建代理对象来实现的。当一个带有缓存注解的方法被调用时,代理对象首先检查指定的缓存中是否已有方法的返回值,如果缓存中有,则直接返回缓存中的值,否则调用原方法获取返回值,并将返回值存入缓存中,再返回给调用者。

在具体实现上,Spring Cache Abstraction 依赖于 CacheManager 和 Cache 两个接口来实现对缓存的管理和操作。CacheManager 接口提供了获取特定缓存的实例的能力,而 Cache 接口则提供了实际的缓存操作,如 get、put 和 evict 等。

同时,在 Spring Boot 中,我们可以通过配置来指定使用的缓存类型以及其他相关属性,比如缓存的过期时间、最大缓存数量等。

二、利用redis实现缓存

spring boot的整体的设计思路是约定大于配置,约定俗成,第一步,我们需要引入redis和cache的相关的依赖

java 复制代码
 <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
      <groupId>org.apache.commons</groupId>
      <artifactId>commons-pool2</artifactId>
</dependency>
<dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-cache</artifactId>
</dependency>

注意:commons-pool2必须引入,不然可能会报java.lang.NoClassDefFoundError: org/apache/commons/pool2/impl/GenericObjectPoolConfig错误

第二步,配置spring boot配置文件application.yml

java 复制代码
spring:
  redis:
    host: 127.0.0.1
    password:
    database: 0
    port: 6379
    lettuce:
      pool:
        max-idle: 8
        max-active: 8
        max-wait: 3000ms
        min-idle: 0
  cache:
    # 指定Redis作为缓存实现
    type: redis
    # 指定项目中的cacheNames
    cache-names:
      - USERS
    redis:
      # 缓存过期时间为10分钟,单位为毫秒
      time-to-live: 600000
      # 是否允许缓存空数据,当查询到的结果为空时缓存空数据到redis中
      cache-null-values: true
      # 为Redis的KEY拼接前缀
      key-prefix: "BOOT_CACHE:"
      # 是否拼接KEY前缀
      use-key-prefix: true
      # 是否开启缓存统计
      enable-statistics: false

第三步,配置序列化器

java 复制代码
@Configuration
public class RedisConfig extends CachingConfigurerSupport {
    @Bean
    public RedisCacheConfiguration redisCacheConfiguration(CacheProperties cacheProperties) {
        // 获取Properties中Redis的配置信息
        CacheProperties.Redis redisProperties = cacheProperties.getRedis();
        // 获取RedisCacheConfiguration的默认配置对象
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
        // 指定序列化器为GenericJackson2JsonRedisSerializer
        config = config.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));
        // 过期时间设置
        if (redisProperties.getTimeToLive() != null) {
            config = config.entryTtl(redisProperties.getTimeToLive());
        }
        // KEY前缀配置
        if (redisProperties.getKeyPrefix() != null) {
            config = config.prefixCacheNameWith(redisProperties.getKeyPrefix());
        }
        // 缓存空值配置
        if (!redisProperties.isCacheNullValues()) {
            config = config.disableCachingNullValues();
        }
        // 是否启用前缀
        if (!redisProperties.isUseKeyPrefix()) {
            config = config.disableKeyPrefix();
        }
        return config;
    }
}

第四步,开启缓存-@EnableCaching

java 复制代码
@SpringBootApplication
@EnableCaching
public class Application {

    public static void main(String[] args) throws Exception {
        SpringApplication springApplication=new SpringApplication(Application.class);
        springApplication.setBannerMode(Banner.Mode.OFF);
        springApplication.run(args);
    }
}

到此,我们利用redis作为spring boot的缓存已经搭建好了,下面我们来做个测试,这里就不使用数据库了,我们使用数据来自己模拟数据库数据查询,模拟数据访问层

java 复制代码
@Repository
@Slf4j
public class UserMapper {

    public final Map<String, SystemUser> map = new HashMap<>();

    @PostConstruct
    public void init(){
        SystemPermissions permissions1 = new SystemPermissions("1", "query");
        SystemPermissions permissions2 = new SystemPermissions("2", "add");
        Set<SystemPermissions> permissionsSet = new HashSet<>();
        permissionsSet.add(permissions1);
        permissionsSet.add(permissions2);
        SystemRole role = new SystemRole("1", "admin", permissionsSet);
        Set<SystemRole> roleSet = new HashSet<>();
        roleSet.add(role);
        SystemUser user = new SystemUser();
        user.setUserName("test");
        user.setUserId(UUID.randomUUID().toString());
        user.setUserPwd("123456");
        user.setSystemRoles(roleSet);

        map.put(user.getUserName(), user);

        Set<SystemPermissions> permissionsSet1 = new HashSet<>();
        permissionsSet1.add(permissions1);
        SystemRole role1 = new SystemRole("2", "user", permissionsSet1);
        Set<SystemRole> roleSet1 = new HashSet<>();
        roleSet1.add(role1);
        SystemUser user1 = new SystemUser();
        user1.setUserName("test1");
        user1.setUserId(UUID.randomUUID().toString());
        user1.setUserPwd("123456");
        user1.setSystemRoles(roleSet1);

        map.put(user1.getUserName(), user1);
    }

    public SystemUser queryUser(String userName){
        log.error("queryUser_没有走缓存:"+userName);
        return map.get(userName);
    }
}

以上类是自己的类,自己实现时可以换成自己的,编写service

java 复制代码
public interface UserService {

    SystemUser getUserByName(String userName);

}


@Service
public class UserServiceImpl implements UserService{

    private final UserMapper userMapper;

    public UserServiceImpl(UserMapper userMapper) {
        this.userMapper = userMapper;
    }

    @Cacheable(cacheNames = "USERS",key = "#userName")
    @Override
    public SystemUser getUserByName(String userName) {
        return userMapper.queryUser(userName);
    }
}

编写controller

java 复制代码
@RestController
@Slf4j
public class UserController {

  private final UserService userService;

    public UserController(UserService userService) {
        this.userService = userService;
    }

    @GetMapping("queryUser")
    public JsonResult getUser(String userName){
        SystemUser user=userService.getUserByName(userName);
        return new JsonResult<>("0", "查询成功", user);
    }
}

测试,可以看到,此时我们的redis中没有数据

第一次,请求没有走缓存,我们再看redis,已经有了数据,第二次请求直接拿了redis缓存中的数据

相关推荐
JH30734 小时前
SpringBoot 优雅处理金额格式化:拦截器+自定义注解方案
java·spring boot·spring
qq_12498707537 小时前
基于SSM的动物保护系统的设计与实现(源码+论文+部署+安装)
java·数据库·spring boot·毕业设计·ssm·计算机毕业设计
Coder_Boy_7 小时前
基于SpringAI的在线考试系统-考试系统开发流程案例
java·数据库·人工智能·spring boot·后端
2301_818732067 小时前
前端调用控制层接口,进不去,报错415,类型不匹配
java·spring boot·spring·tomcat·intellij-idea
此生只爱蛋7 小时前
【Redis】主从复制
数据库·redis
汤姆yu11 小时前
基于springboot的尿毒症健康管理系统
java·spring boot·后端
暮色妖娆丶11 小时前
Spring 源码分析 单例 Bean 的创建过程
spring boot·后端·spring
biyezuopinvip12 小时前
基于Spring Boot的企业网盘的设计与实现(任务书)
java·spring boot·后端·vue·ssm·任务书·企业网盘的设计与实现
惊讶的猫12 小时前
redis分片集群
数据库·redis·缓存·分片集群·海量数据存储·高并发写
JavaGuide12 小时前
一款悄然崛起的国产规则引擎,让业务编排效率提升 10 倍!
java·spring boot