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

 <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

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

第三步,配置序列化器

@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

@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的缓存已经搭建好了,下面我们来做个测试,这里就不使用数据库了,我们使用数据来自己模拟数据库数据查询,模拟数据访问层

@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

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

@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缓存中的数据

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/107672.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C++入门精讲——入门看完这一篇就够了

文章目录 前言1. C发展历史2. 关键字3. 命名空间3.1 命名空间的概念3.2 命名空间的定义3.3 命名空间的使用 4. C输入、输出5. 缺省参数5.1 全缺省5.2 半缺省 6. 函数重载6.1 几种不同类型的函数重载6.2 函数重载的原理——名字修饰(name Mangling)6.2.1 C程序为什么不支持函数重…

Nokogiri库和OpenURI库使用HTTP做一个爬虫

Nokogiri和OpenURI是两个常用的Ruby库&#xff0c;用于编写爬虫程序。它们的主要功能如下&#xff1a; 1、Nokogiri&#xff1a;Nokogiri是一个强大的HTML和XML解析库&#xff0c;可以用于解析网页内容。它提供了一组简单易用的API&#xff0c;可以方便地遍历和操作HTML或XML文…

模型对象CSS2DObject始终在画布的左上角(问题解决)

写了个简单案例模拟一下这个问题&#xff0c;看下图片 下面看下c2渲染器相关代码部分 this.css2DRenderer new CSS2DRenderer(); this.css2DRenderer.render(this.scene, this.camera); this.css2DRenderer.setSize(width, height); this.css2DRenderer.domElement.style.pos…

【每日一题】合并两个有序数组

链接奉上&#xff1a;合并两个有序数组 目录 直接合并后排序&#xff1a;思路&#xff1a;代码实现&#xff1a; 双指针思路&#xff1a;代码实现&#xff1a; 直接合并后排序&#xff1a; 思路&#xff1a; 将nums2直接合并到nums1后边&#xff0c;并进行排序 代码实现&…

Proteus仿真--基于51单片机的LED模拟交通灯仿真(仿真文件+程序)

本文主要介绍基于51单片机的LED模拟交通灯仿真&#xff08;完整仿真源文件及代码见文末链接&#xff09; 仿真运行视频 Proteus仿真--基于51单片机的LED模拟交通灯仿真&#xff08;仿真文件程序&#xff09; 附完整Proteus仿真资料代码资料 百度网盘链接: https://pan.baidu.c…

STM32F4X SDIO(二) SDIO协议

上一节简单介绍了SD卡的分类&#xff0c;本节将会介绍SD卡的通信协议&#xff0c;也就是SDIO协议。 STM32F4X SDIO&#xff08;二&#xff09;SDIO协议 SD 卡管脚和寄存器SD卡管脚分布SD卡通信协议SD卡寄存器SD卡内部结构 SDIO总线SDIO总线拓扑SDIO总线协议SDIO协议的基本结构…

Oracle (7)Online Redo Log Files

目录 一、Oracle Online Redo Log Files及其相关内容介绍 1、Online Redo Log Files简介 2、Online Redo Log Files特点 3、Online Redo Log Files文件组 4、多路复用文件 5、联机重做日志文件工作方式 6、LGWR什么时候写重做 7、LS和LSN 8、删除Redo文件成员 9、删除…

CTF-php特性绕过

注意&#xff1a;null0 正确 nullflase 错误 Extract变量覆盖 <?php$flagxxx; extract($_GET);if(isset($shiyan)){ $contenttrim(file_get_contents($flag));//trim移除引号if($shiyan$content){ echoctf{xxx}; }else{ echoOh.no;} }?> extract() 函数从数组中将…

C语言每日一题(21)删除排序数组中的重复项

力扣 26.删除排序数组中的重复项 题目描述 给你一个 非严格递增排列 的数组 nums &#xff0c;请你 原地 删除重复出现的元素&#xff0c;使每个元素 只出现一次 &#xff0c;返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums 中唯一元素的个数。 考…

Redis(02)| 数据结构-SDS

一、键值对数据库是怎么实现的&#xff1f; 在开始讲数据结构之前&#xff0c;先给介绍下 Redis 是怎样实现键值对&#xff08;key-value&#xff09;数据库的。 Redis 的键值对中的 key 就是字符串对象&#xff0c;而 value 可以是字符串对象&#xff0c;也可以是集合数据类型…

哪一个更好?Spring boot还是Node.js

前言 本篇文章有些与众不同&#xff0c;由于我自己手头有些关于这个主题的个人经验&#xff0c;受其启发写出此文。虽然SpringBoot和Node.js服务于很不一样的场景&#xff0c;但是这两个框架共性惊人。其实每种语言都有不计其数的框架&#xff0c;但仅仅一部分是真正卓越的。如…

【优选算法系列】第二节.双指针(202. 快乐数和11. 盛最多水的容器)

作者简介&#xff1a;大家好&#xff0c;我是未央&#xff1b; 博客首页&#xff1a;未央.303 系列专栏&#xff1a;优选算法系列 每日一句&#xff1a;人的一生&#xff0c;可以有所作为的时机只有一次&#xff0c;那就是现在&#xff01;&#xff01;&#xff01;&#xff01…

【数据结构】搜索树 与 Java集合框架中的Set,Map

作者主页&#xff1a;paper jie_博客 本文作者&#xff1a;大家好&#xff0c;我是paper jie&#xff0c;感谢你阅读本文&#xff0c;欢迎一建三连哦。 本文录入于《JAVA数据结构》专栏&#xff0c;本专栏是针对于大学生&#xff0c;编程小白精心打造的。笔者用重金(时间和精力…

TSINGSEE青犀睡岗离岗检测算法——确保加油站安全运营

众所周知&#xff0c;加油站是一个需要24小时营业的场所&#xff0c;由于夜间加油人员较少&#xff0c;员工极易处于疲劳或者睡眠状态&#xff0c;为保障安全和效率&#xff0c;通过TSINGSEE青犀睡岗离岗检测算法在加油站场景中&#xff0c;可以及时发现工作人员的疲劳状况&…

JAVA面试题简单整理

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、重载和重写的区别一、&和&&的区别一、get和post请求的区别 delete、put一、cookie和session的区别一、Autowired和Resource区别一、”和equals…

笔记:电子设备接地,接的到底是什么地?

电路中有“地”&#xff0c;设备中有“地”&#xff1b;都是“地”&#xff0c;此地非彼地。 混淆的原因 有些混淆&#xff0c;是以为中文翻译造成的&#xff0c;英文所有Ground都统一翻译为“地”&#xff1b; 例1&#xff1a;英文Circuit Ground&#xff0c;应该翻译为电路…

mac安装并使用wireshark

mac安装并使用wireshark 1 介绍 我们在日常开发过程中&#xff0c;遇到了棘手的问题时&#xff0c;免不了查看具体网络请求情况&#xff0c;这个时候就需要用到抓包工具。比较著名的抓包工具就属&#xff1a;wireshark、fildder。我这里主要介绍wireshark。 2 安装 以mac安装为…

Android-宝宝相册(第四次作业)

第四次作业-宝宝相册 题目 用Listview建立宝宝相册&#xff0c;相册内容及图片可自行设定&#xff0c;也可在资料文件中获取。给出模拟器仿真界面及代码截图。 &#xff08;参考例4-8&#xff09; 创建工程项目 创建名为baby的项目工程&#xff0c;最后的工程目录结构如下图所…

自学爬虫—作业1—requests模块

视频&#xff1a; 要求&#xff1a; 肯德基地址查询&#xff0c;爬某个关键字&#xff0c;获取下面的所有page的信息&#xff0c;存到一个json或者txt。 代码&#xff1a; 关键点&#xff0c;&#xff08;1&#xff09;每一个ajax的请求第一个键值对就是所有获得的地址的总数…

【算法|动态规划No.31 | 01背包问题】01背包模板题

个人主页&#xff1a;兜里有颗棉花糖 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 兜里有颗棉花糖 原创 收录于专栏【手撕算法系列专栏】【LeetCode】 &#x1f354;本专栏旨在提高自己算法能力的同时&#xff0c;记录一下自己的学习过程&#xff0c;希望…
最新文章