springboot高级特性-缓存(代码片段)

暴躁的程序猿啊 暴躁的程序猿啊     2022-12-30     499

关键词:

缓存:将相应数据存储起来以避免数据的重复创建、处理和传输,可有效提高性能

springboot中使用缓存 可以缓存方法的返回值 等等 避免多次查询数据库

springboot的缓存有以下层级关系
CachingProvider 缓存提供者 —>管理和控制多个CacheManager---->管理和控制多个唯一命名的cache----->存储在cache中的key-value对-------->Expiry 每一个存储在cache中的条目有一个有效期

Spring缓存抽象

cache 定义各种操作

CacheManager 缓存管理器,管理各种缓存组件

Cache缓存接口 定义缓存操作 如:RedisCache。EhCacheCaceh等

缓存注解

@Cacheable 主要针对方法配置,能够根据方法的请求参数对其结果进行缓存

@CacheEvict 清空缓存

@CachePut 保证方法被调用,又希望结果被缓存

@EnableCaching 开启基于注解的缓存

keyGenerator 缓存数据时key生成策略

serialize 缓存数据时value序列化策略

我们要想使用缓存 导入缓存依赖

         <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-cache</artifactId>
        </dependency>

创建一个可以访问数据库的工程
pojo类

/**
 * @create: 2021/9/4
 * @author: Tony Stark
 */
@Data
public class Employee 
    private Integer id;
    private String lastName;
    private String email;
    private Integer gender;  //性别  1男  0女

定义mapper

@Mapper
public interface EmployeeMapper 

    @Select("select * from employee where id =#id")
    public Employee getEmpById(Integer id);


service

@Service
public class EmployeeService 

    @Autowired
    EmployeeMapper employeeMapper;

    public Employee getEmp(Integer id)
        System.out.println("查询"+id+"号员工");
        Employee empById = employeeMapper.getEmpById(id);
        return empById;
    


controller

@RestController
public class EmployeeController 

    @Autowired
    EmployeeService employeeService;

    @GetMapping("/emp/id")
    public Employee getEmployee(@PathVariable("id")Integer id)
        Employee emp = employeeService.getEmp(id);
        return emp;
    

如果我们要使用缓存需要在启动类上加EnableCaching注解开启缓存

@SpringBootApplication
@EnableCaching
public class Springboot01CacheApplication 

    public static void main(String[] args) 
        SpringApplication.run(Springboot01CacheApplication.class, args);
    


将方法的运行结果进行缓存;以后再有相同的数据,直接从缓存中取,不用去调方法;
在方法上加上cacheable注解缓存结果
@Cacheable(cacheNames = “emp”)

 @Cacheable(cacheNames = "emp")
    public Employee getEmp(Integer id)
        System.out.println("查询"+id+"号员工");
        Employee empById = employeeMapper.getEmpById(id);
        return empById;
    

访问测试

http://localhost:8080/emp/1

第一次访问

我们清空控制台进行 第二次访问

可以看到并没有查询数据库 而是使用了缓存 大家可以多试几次

方法的属性 :
**cacheNames/value 😗*指定缓存的名字;将方法的返回结果放在哪个缓存中,是数组的方式可以指定多个缓存
cacheManager管理多个cache组件的,对缓存的真正CRUD操作在cache组件中,每一个缓存有自己唯一一个名字
key: 缓存数据时的key;可以用它来指定 默认使用方法参数的值 值就是方法的返回值
#id 代表取出取出参数id的值作为key
例如 参数传入进来 1 存储为 1-返回值
编写SpEL:#id 参数id的值 #a0 #p0 #root.args[0]

KeyGenerator: key的生成器 : 可以指定key的生成器的组件id
key/KeyGenerator二选一使用
cacheManager:指定缓存管理器 或者cacheResolver指定缓存解析器

condition: 指定符合条件的情况下才缓存
condition = “#id>0” 指定id大于0的时候才进行缓存

 @Cacheable(cacheNames = "emp",condition = "#id>2")
    public Employee getEmp(Integer id)
        System.out.println("查询"+id+"号员工");
        Employee empById = employeeMapper.getEmpById(id);
        return empById;
    

我现在指定的id>2时才进行缓存
测试一下
第一次访问

第二次访问 可以看出并没有进行缓存

unless: 否定缓存; 当unless指定的条件为true方法的返回值就不回被缓存;可以获取到结果进行判断
unless = “#result == null” 当结果为空时就不进行缓存

sync: 是否使用异步模式 注意开启异步 unless就会失效

@CachePut 注解

加入mapper方法

  @Update("update employee  set lastName=#lastName,email=#email,gender=#gender,d_id=#dIdwhere id=#id")
    public void updateEmp(Employee employee);

@CachePut : 即调用方法又更新缓存数据
修改了数据库的某个数据,同时更新缓存
运行时机:先调用目标方法把方法的返回值缓存起来

   @CachePut(cacheNames = "emp")
    public Employee updateEmployee(Employee employee)
        employeeMapper.updateEmp(employee);
        return employee;
    

测试步骤

先查询一个员工 查到的结果会放到缓存中

http://localhost:8080/emp/1


以后查询的结果还是之前缓存的结果

这时候我们更新这个员工

http://localhost:8080/get?id=1&lastName=&email=王五2858458@qq.com&dId=1&gender=1

更新方法将方法的返回值也放在了缓存中

当我们再次查询这个员工的时候 数据是更新之后的 还是更新之前的值

http://localhost:8080/emp/1

这是为什么呢 难道我们的@CachePut注解没生效??

其实不是的

我们缓存的时候key默认为方法的参数 我们查询的参数为 id 所以缓存key为id id-value
我们更新的方法参数为employee 所以缓存key为employee employee-value
跟我们查询的时候不是一个缓存 所以导致结果没更新 我们需要指定key为同一个可以即可

    @CachePut(cacheNames = "emp",key = "#employee.id")
    public Employee updateEmployee(Employee employee)
        employeeMapper.updateEmp(employee);
        return employee;
    

或者
因为我们的 @CachePut注解 是方法返回结果后缓存所以我们可以从方法的返回值中获取

 @CachePut(cacheNames = "emp",key = "#result.id")
    public Employee updateEmployee(Employee employee)
        employeeMapper.updateEmp(employee);
        return employee;
    

当然我们的@Cacheable注解是不能用result的 因为我们的@Cacheable注解要在目标方法执行之前按照key去查询缓存 所以没有方法返回的result的结果

这时候我们重新测试

http://localhost:8080/emp/1


我们更新

http://localhost:8080/get?id=1&lastName=wangwu&email=2858458@qq.com&dId=1&gender=1


这时候我们再查询看看会不会更新

答案是已经更新了 且还是缓存中的值没有查询数据库

@CacheEvict注解

@CacheEvict : 缓存清除
通过可以指定要清除的数据 不写默认是参数为key
key = "#id"取出id为key的缓存
参数:allEntries = true 是指定是否删除缓存中的所有数据默认为false true时就是删除缓存中所有数据
beforeInvocation = true 缓存的清除是否在方法之前执行
默认值为true代表在方法执行之后执行 这里需要注意的是 如果是在方法执行之后执行 如果方法抛出了异常 缓存就不会清空。
添加删除的方法

  @GetMapping("/deleteEmp/id")
    public String deleteEmp(@PathVariable("id") Integer id)
        employeeService.deleteEmp(id);
        return "删除成功";
    
     public void deleteEmp(Integer id)
         System.out.println("删除员工"+id);
         employeeMapper.deleteEmpById(id);
     

添加注解

 @CacheEvict(value = "emp",key = "#id" )
     public void deleteEmp(Integer id)
         System.out.println("删除员工"+id);
         employeeMapper.deleteEmpById(id);
     

测试

我们先拿缓存

这是调用删除缓存方法

http://localhost:8080/deleteEmp/1


我们再次查询数据 发现我们的数据是从数据库中拿的不是缓存

@CacheConfig注解

@CacheConfig(cacheNames = “emp”)
可以指定全局的配置 标注在类上该类的所有公共注解只需在类上配置一次即可

@CacheConfig(cacheNames = "emp")
@Service
public class EmployeeService 

    @Autowired
    EmployeeMapper employeeMapper;
    @Cacheable(condition = "#id>0")
    public Employee getEmp(Integer id)
        System.out.println("查询"+id+"号员工");
        Employee empById = employeeMapper.getEmpById(id);
        return empById;
    
    /**
     * @CachePut  :  即调用方法又更新缓存数据
     * 修改了数据库的某个数据,同时更新缓存
     * 运行时机:先调用目标方法把方法的返回值缓存起来
     * key = "#result.id"
     */
    @CachePut(key = "#employee.id")
    public Employee updateEmployee(Employee employee)
        employeeMapper.updateEmp(employee);
        return employee;
    
  
    @CacheEvict(key = "#id",beforeInvocation = true)
     public void deleteEmp(Integer id)
        employeeMapper.deleteEmpById(id);
     
 

springboot高级-缓存消息(代码片段)

springboot与缓存、消息1.缓存1.1JSR-1071.2Spring缓存抽象1.2.1搭建基本环境&缓存入门体验1.2.2缓存缓存工作原理&运行流程1.2.3几个重要概念&缓存注解1.2.4@Cacheable的几个属性1.3整合Redis2.消息2.1概述2.2异步处理、应用解耦、流... 查看详情

springboot高级特性之邮件发送(代码片段)

...件发送的场景如发送验证码,向客户发送邮件等等。springboot中整合了mail帮助我们更方便的发送邮件平时我们发送邮件是通过邮件的服务器发送出去的比如qq邮件调用qq的邮件服务器网易的邮件通过网易的服务器我们使用邮件... 查看详情

springboot整合rabbitmq高级特性&真实业务应用(代码片段)

♨️本篇文章记录的为RabbitMQ知识中高级特性和企业级项目相关内容,适合在学Java的小白,帮助新手快速上手,也适合复习中,面试中的大佬🙉🙉🙉。♨️如果文章有什么需要改进的地方还请大佬不吝赐教❤️... 查看详情

rabbitmq高级特性之消费端限流通俗易懂超详细内含案例(代码片段)

RabbitMq高级特性之消费端限流一丶首先部署SpringBoot框架完成SpringBoot整合RabbitMq中的Topic通配符模式二丶在resource资源文件夹里application.yml文件中添加配置spring:rabbitmq:listener:simple:acknowledge-mode:manual#开启手动签收prefetch:3#一次就收三... 查看详情

dubbo--dubbo高级特性(序列化地址缓存超时与重试机制多版本:灰度发布负载均衡集群容错策略服务降级)(代码片段)

文章目录1.dubbo高级特性1.1序列化1.2地址缓存1.3超时与重试机制1.4多版本1.4.1灰度发布图示1.4.2version属性示例1.5负载均衡1.6集群容错策略1.7服务降级1.Dubbo–分布式系统的相关概念(大型互联网项目架构目标集群和分布式架构演... 查看详情

springboot参数校验,高级特性,非常实用!(代码片段)

之前也写过一篇关于SpringValidation使用的文章,不过自我感觉还是浮于表面,本次打算彻底搞懂SpringValidation。本文会详细介绍SpringValidation各种场景下的最佳实践及其实现原理,死磕到底!简单使用JavaAPI规范(JSR303)... 查看详情

springboot学习总结二(代码片段)

...的一些特性,因此有着丰富的应用场景。本文介绍Redis在SpringBoot中两个典型的应用场景,cache的配置类:@Conf 查看详情

golang常用库包:缓存redis操作库go-redis使用(03)-高级数据结构和其它特性(代码片段)

Redis高级数据结构操作和其它特性第一篇:go-redis使用,介绍Redis基本数据结构和其他特性,以及go-redis连接到Redishttps://www.cnblogs.com/jiujuan/p/17207166.html第二篇:go-redis使用,Redis5种基本数据类型操作https://www.cnblogs.com/jiujuan/p/17215125.... 查看详情

springboot-缓存管理(代码片段)

...作数据的执行次数,同时不会对程序本身造成任何干扰。SpringBoot继承了Spring框架的缓存管理功能,通过使用@EnableCaching注解开启基于注解的缓存支持,SpringBoot就可以启动缓存管理的自动化配置。接下来针对SpringBoot支持的默认缓... 查看详情

springboot整合mybatisplus(代码片段)

1.开发前准备1.1前置知识java基础SpringBoot简单基础知识1.2环境参数开发工具:IDEA基础环境:Maven+JDK8所用技术:SpringBoot、lombok、MybatisPlusSpringBoot版本:2.1.41.3涉及知识点MybatisPlus简介、特性、架构MybatisPlus快速入门MybatisPlus的基本CRU... 查看详情

2-高级特性(代码片段)

...dubbo-admin是一个前后端分离项目,前端采用Vue,后端采用springboot。安装首先需要安装node,然后在github中搜索dubbo-admin,此项目来自apache。在./dubbo-admin-server/src/main/resources/application.properties中修改zk的地址:admin.registry.address=zookeeper... 查看详情

springboot缓存管理(代码片段)

SpringBoot缓存管理缓存是分布式系统中的重要组件,主要解决数据库数据的高并发访问问题。在实际开发中,尤其是用户访问较大的网站,为了提高服务器访问性能、减少数据库的压力、提高用户体验,使用缓存显... 查看详情

23.flink-高级特性-新特性-streamingfliesink介绍代码演示flink-高级特性-新特性-flinksql整合hive添加依赖和jar包和配置(代码片段)

23.Flink-高级特性-新特性-StreamingFlieSink23.1.介绍23.2.代码演示24.Flink-高级特性-新特性-FlinkSQL整合Hive24.1.介绍24.2.版本24.3.添加依赖和jar包和配置24.4.FlinkSQL整合Hive-CLI命令行整合24.5.FlinkSQL整合Hive-代码整合23.Flink-高级特性-新特性-Stream... 查看详情

web前端面试高频考点——vue的高级特性(动态组件异步加载keep-alivemixinvuexvue-router)(代码片段)

系列文章目录文章目录系列文章目录一、Vue高级特性1、动态组件2、vue异步加载组件3、vue缓存组件(keep-alive)4、mixin二、Vuex1、Vuex基本概念2、用于Vue组件三、Vue-router1、动态路由2、懒加载一、Vue高级特性1、动态组件按... 查看详情

玩转mybatis高级特性:让你的数据操作更上一层楼(代码片段)

目录动态SQL缓存机制插件机制自定义类型转换总结Mybatis高级特性能够帮助我们更加灵活地操作数据库,包括动态SQL、缓存机制、插件机制、自定义类型转换等。学习这些特性可以让我们更好地利用Mybatis,提高数据操作的效率和... 查看详情

springboot第一特性:自动装配(代码片段)

文章目录一、前言二、Springboot四个特性三、Springboot自动装配3.1Springboot牛刀小试:整合redis,引入自动装配3.2自动装配的思考3.3实践:模拟自动装配3.3.1两个bean和两个配置类3.3.2MyImportSelector类3.3.3@MyEnableConfiguration注... 查看详情

springboot开启redis缓存(代码片段)

...之前不是说过Redis可以当作缓存用嘛现在我们就配置一下SpringBoot使用Redis的缓存Redis缓存为什么用Redis作缓存用redis做缓存,是因为re 查看详情

springboot缓存注解介绍(代码片段)

SpringBoot缓存注解介绍1.@EnableCaching注解2.@Cacheable注解@Cacheable注解相关属性3.@CachePut注解4.@CacheEvict注解5.@Caching注解6.@CacheConfig注解。本文介绍在使用Spring缓存时,所应用到的一些注解和相对应的属性,... 查看详情