• 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的相关的依赖

    1. org.springframework.boot
    2. spring-boot-starter-data-redis
    3. org.apache.commons
    4. commons-pool2
    5. org.springframework.boot
    6. spring-boot-starter-cache

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

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

    1. spring:
    2. redis:
    3. host: 127.0.0.1
    4. password:
    5. database: 0
    6. port: 6379
    7. lettuce:
    8. pool:
    9. max-idle: 8
    10. max-active: 8
    11. max-wait: 3000ms
    12. min-idle: 0
    13. cache:
    14. # 指定Redis作为缓存实现
    15. type: redis
    16. # 指定项目中的cacheNames
    17. cache-names:
    18. - USERS
    19. redis:
    20. # 缓存过期时间为10分钟,单位为毫秒
    21. time-to-live: 600000
    22. # 是否允许缓存空数据,当查询到的结果为空时缓存空数据到redis中
    23. cache-null-values: true
    24. # 为Redis的KEY拼接前缀
    25. key-prefix: "BOOT_CACHE:"
    26. # 是否拼接KEY前缀
    27. use-key-prefix: true
    28. # 是否开启缓存统计
    29. enable-statistics: false

    第三步,配置序列化器

    1. @Configuration
    2. public class RedisConfig extends CachingConfigurerSupport {
    3. @Bean
    4. public RedisCacheConfiguration redisCacheConfiguration(CacheProperties cacheProperties) {
    5. // 获取Properties中Redis的配置信息
    6. CacheProperties.Redis redisProperties = cacheProperties.getRedis();
    7. // 获取RedisCacheConfiguration的默认配置对象
    8. RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
    9. // 指定序列化器为GenericJackson2JsonRedisSerializer
    10. config = config.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));
    11. // 过期时间设置
    12. if (redisProperties.getTimeToLive() != null) {
    13. config = config.entryTtl(redisProperties.getTimeToLive());
    14. }
    15. // KEY前缀配置
    16. if (redisProperties.getKeyPrefix() != null) {
    17. config = config.prefixCacheNameWith(redisProperties.getKeyPrefix());
    18. }
    19. // 缓存空值配置
    20. if (!redisProperties.isCacheNullValues()) {
    21. config = config.disableCachingNullValues();
    22. }
    23. // 是否启用前缀
    24. if (!redisProperties.isUseKeyPrefix()) {
    25. config = config.disableKeyPrefix();
    26. }
    27. return config;
    28. }
    29. }

    第四步,开启缓存-@EnableCaching

    1. @SpringBootApplication
    2. @EnableCaching
    3. public class Application {
    4. public static void main(String[] args) throws Exception {
    5. SpringApplication springApplication=new SpringApplication(Application.class);
    6. springApplication.setBannerMode(Banner.Mode.OFF);
    7. springApplication.run(args);
    8. }
    9. }

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

    1. @Repository
    2. @Slf4j
    3. public class UserMapper {
    4. public final Map map = new HashMap<>();
    5. @PostConstruct
    6. public void init(){
    7. SystemPermissions permissions1 = new SystemPermissions("1", "query");
    8. SystemPermissions permissions2 = new SystemPermissions("2", "add");
    9. Set permissionsSet = new HashSet<>();
    10. permissionsSet.add(permissions1);
    11. permissionsSet.add(permissions2);
    12. SystemRole role = new SystemRole("1", "admin", permissionsSet);
    13. Set roleSet = new HashSet<>();
    14. roleSet.add(role);
    15. SystemUser user = new SystemUser();
    16. user.setUserName("test");
    17. user.setUserId(UUID.randomUUID().toString());
    18. user.setUserPwd("123456");
    19. user.setSystemRoles(roleSet);
    20. map.put(user.getUserName(), user);
    21. Set permissionsSet1 = new HashSet<>();
    22. permissionsSet1.add(permissions1);
    23. SystemRole role1 = new SystemRole("2", "user", permissionsSet1);
    24. Set roleSet1 = new HashSet<>();
    25. roleSet1.add(role1);
    26. SystemUser user1 = new SystemUser();
    27. user1.setUserName("test1");
    28. user1.setUserId(UUID.randomUUID().toString());
    29. user1.setUserPwd("123456");
    30. user1.setSystemRoles(roleSet1);
    31. map.put(user1.getUserName(), user1);
    32. }
    33. public SystemUser queryUser(String userName){
    34. log.error("queryUser_没有走缓存:"+userName);
    35. return map.get(userName);
    36. }
    37. }

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

    1. public interface UserService {
    2. SystemUser getUserByName(String userName);
    3. }
    4. @Service
    5. public class UserServiceImpl implements UserService{
    6. private final UserMapper userMapper;
    7. public UserServiceImpl(UserMapper userMapper) {
    8. this.userMapper = userMapper;
    9. }
    10. @Cacheable(cacheNames = "USERS",key = "#userName")
    11. @Override
    12. public SystemUser getUserByName(String userName) {
    13. return userMapper.queryUser(userName);
    14. }
    15. }

    编写controller

    1. @RestController
    2. @Slf4j
    3. public class UserController {
    4. private final UserService userService;
    5. public UserController(UserService userService) {
    6. this.userService = userService;
    7. }
    8. @GetMapping("queryUser")
    9. public JsonResult getUser(String userName){
    10. SystemUser user=userService.getUserByName(userName);
    11. return new JsonResult<>("0", "查询成功", user);
    12. }
    13. }

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

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

  • 相关阅读:
    高性价比的大带宽机器选哪里?泉州移动大带宽了解下
    spring实战笔记
    基于C++和C#窗体实现各种无损压缩算法并进行比较分析
    static关键字和final关键字
    SpringMVC入门
    科技云报道:不卷自研大模型,金山办公如何创新生成式AI?
    文件系统和日志分析
    uniapp开发小程序项目
    windows 调用 static lib
    小程序分包和基础页面创建
  • 原文地址:https://blog.csdn.net/weixin_42172472/article/details/134055958