Spring Cache(边路缓存)

news2024/11/19 15:39:21

一、Spring Cache介绍

Spring Cache 是Spring - context-xxx.jar中提供的功能,可以结合EHCache,Redis等缓存工具使用。给用户提供非常方便的缓存处理,缓存基本判断等操作,可以直接使用注解实现。 ​ 在包含了Spring - context-xxx.jar的Spring Boot项目中,在启动类中添加@EnableCaching注解,即可开启缓存功能。默认Spring Cache是不开启。

二、Spring Cache加载缓存工具顺序

只要检测到项目中配置了下面缓存工具(导入了依赖,在Spring容器中发现对应工具的内容),无论导入多少个缓存工具依赖,只用优先级最高的一个。 ​ 默认寻找缓存工具的顺序:(为什么Redis配置上就可以用的原因)

  1. Generic

  2. JCache (JSR-107) (EhCache 3, Hazelcast, Infinispan, and others)

  3. EhCache 2.x

  4. Hazelcast

  5. Infinispan

  6. Couchbase

  7. Redis

  8. Caffeine

  9. Simple

三、基于Spring Cache完成缓存管理

(1)导入依赖

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.3.12.RELEASE</version>
</parent>
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
</dependencies>

(2)编写配置文件

spring:
  redis:
    host: 192.168.8.128
    port: 6379 # 默认值,可省略

(3)编写启动类

@SpringBootApplication
@EnableCaching
public class SpringCacheApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class,args);
    }
}

四、使用

(1)Cacheable:查询缓存的注解

@Service
public class SpringCacheServiceImpl implements SpringCacheService {
    
    /**
     * 查询数据
     * Cacheable - 查询缓存的注解。
     *  固定流程:
     *   1. 根据key访问缓存服务器,查询缓存数据。
     *   2. 判断缓存查询结果
     *     2.1 缓存查询有结果,直接返回。当前方法不执行
     *     2.2 缓存查询无结果,进入后续流程。
     *   3. 执行当前方法代码逻辑。
     *   4. 代码返回值作为value,保存到缓存服务器中。
     *   5. 返回方法的返回结果。
     *  属性:
     *   完整的缓存key是: cacheNames + "::" + key
     *   cacheNames - 缓存key的前缀,字符串类型。只能使用字符串字面值赋值。
     *   key - 缓存key的后缀。字符串类型。可以使用字符串字面值和SpringEL表达式赋值。
     *    赋值的时候,如果是字符串的字面值,必须使用 '' 标记。
     * @return
     */
    @Override
    @Cacheable(cacheNames = "test", key = "'getAll'")
    public List<String> getAll() {
        // 模拟数据库访问
        System.out.println("开始访问数据库。。。。");
        List<String> result = new ArrayList<>();
        for(int i = 0; i < 5; i++){
            result.add("user-" + i);
        }
        System.out.println("数据库查询结束,查询结果是:" + result);
        return result;
    }
}
/**
 * 主键查询
 *  缓存的key必须和方法参数的值相关。
 *
 *  使用SpringEL,访问方法的参数表。
 *  访问方式有:
 *   #root.method.args[下标]
 *   #方法参数变量名
 *
 *  常见的key属性赋值方式是: 方法名称(参数值)
 */
@Override
@Cacheable(cacheNames = "test", key = "#root.methodName + '(' +  #id + ')'")
public String getById(Long id) {
	System.out.println("开始访问数据库....");
	String result = "getById - " + id;
	System.out.println("访问数据库结束,查询结果是:" + result);

	return result;
}

(2)CachePut: 保存数据到缓存服务器。

/**
 * 新增
 * 希望保存数据成功后,同时缓存到Redis中。
 * 后续主键查询的时候,可以减少数据库查询次数。
 *
 * CachePut - 保存数据到缓存服务器。是针对新增和更新使用的缓存注解。
 *  固定流程:
 *   1. 执行当前方法。
 *   2. 根据注解拼接key,把方法的返回值作为value,保存的缓存服务器。
 *   3. 方法返回
 * @return
 */
@Override
@CachePut(cacheNames = "test", key = "'getById(' + #id + ')'")
public String add(Long id, String name) {
    // 完整的数据
    String data = name + " - " + id;
    // 保存到数据库
    System.out.println("保存数据 【" + data + "】 到数据库");
​
    return data;
}

(3)CacheEvict:缓存淘汰。

/**
 * 根据主键删除数据
 * 当删除数据库数据成功后,也要删除缓存中的数据。避免查询的时候,基于缓存,
 * 查询到脏数据。
 *
 * CacheEvict - 缓存淘汰。
 *  固定流程:
 *   1. 执行方法
 *   2. 根据注解中的key,访问缓存服务器,删除键值对
 *   3. 方法返回。
 *
 *  属性:
 *   allEntries - 布尔类型。是否删除cacheNames作为前缀的所有键值对。默认false。
 *     谨慎使用。
 */
@Override
@CacheEvict(cacheNames = "test", key = "'getById(' + #id + ')'")
public String removeById(Long id) {
	System.out.println("删除数据,主键是:" + id);

	return "删除主键是" + id + "数据";
}

(4)CachConfig:公共前缀,使用在类上

@CachConfig(cacheNames = "test")

五、condition和unless属性

(1) condition

condition是普通条件。如果条件成立则进行缓存。此判断为进入到方法体之前的判断,所以#result不允许用在这里。如果在condition中出现#result会导致条件恒不成立,不进行缓存。

@Override
@Cacheable(/*cacheNames = "test", */key = "#root.methodName + '(' +  #id + ')'",
		condition = "#id >= 10"
)
public String getById(Long id) {
	System.out.println("开始访问数据库....");
	String result = "getById - " + id;
	System.out.println("访问数据库结束,查询结果是:" + result);

	return result;
}

(2)unless

unless是方法执行完成后的条件,当符合条件不被缓存。注意:#result只能写在这个属性中。多用在返回结果为null时不缓存效果。

@Override
@Cacheable(/*cacheNames = "test", */key = "#root.methodName + '(' +  #id + ')'",
		unless = "#id >= 10"
)
public String getById(Long id) {
	System.out.println("开始访问数据库....");
	String result = "getById - " + id;
	System.out.println("访问数据库结束,查询结果是:" + result);

	return result;
}

(3)SpringEL中的常见变量

 六、Spring Cache缓存管理器配置

@Configuration
public class MySpringCacheConfiguration {
    /**
     * 创建一个CacheManager,缓存管理器。
     * 实现缓存的访问配置管理。
     * 如:缓存有效期。键值对的序列化方式等。
     * 在SpringCache技术中,要求,一个Spring容器上下文只有唯一的CacheManager对象。
     *
     * RedisCacheManager - Redis缓存服务器的管理工具。
     */
    @Bean
    public CacheManager cacheManager(RedisConnectionFactory factory){
        // 创建默认的缓存配置管理。
        RedisCacheConfiguration configuration =
                RedisCacheConfiguration.defaultCacheConfig();

        // 配置,可以提供缓存有效期和键值对序列化器等。
        // RedisCacheConfiguration设计比较特殊。每个配置的修改,都会创建一个新的RedisCacheConfiguration对象并返回。
        configuration =
                configuration
                .serializeKeysWith(
                        RedisSerializationContext.SerializationPair.fromSerializer(
                                new StringRedisSerializer()
                        )
                ) // 设置key的序列化工具
                .serializeValuesWith(
                        RedisSerializationContext.SerializationPair.fromSerializer(
                                new GenericJackson2JsonRedisSerializer()
                        )
                ) // 设置value的序列化工具
                .entryTtl(Duration.ofMinutes(30L)) // 设置所有键值对的有效期
                .disableCachingNullValues() ; // 是否忽略value为null的数据缓存保存过程。

        // 使用构建器,默认构建的管理器,是默认配置逻辑。
        // 永久保存数据,key是字符串序列化工具。value是JDKSerializable序列化工具
        // 可以提供自定义的配置逻辑。 RedisCacheConfiguration
        RedisCacheManager redisCacheManager =
                RedisCacheManager
                        .builder() // 构建器。用于构建RedisCacheManager的工具。必须提供连接工厂
                        .cacheWriter(  // 提供连接工厂
                                RedisCacheWriter.lockingRedisCacheWriter(factory)
                        )
                        .cacheDefaults(configuration) // 基于提供的配置,创建管理器。
                        .build();
        return redisCacheManager;
    }

}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

07---vue前端实现增删改查

前端VUE通过请求后端实现增删改查&#xff0c;文末会有前端完整代码 1、实现查询功能 一、实现三个条件一起查询 后台需要实现这三个条件的模糊查询 UserController.java //分页查询GetMapping("/page")public IPage<User> findPage(RequestParam Integer p…

【Jenkins】学习笔记

学习笔记一、Jenkins1.1、Jenkins的作用二、下载安装2.1、安装环境2.2、安装GitLab2.3、安装Jenkins三、Jenkins Git Maven 部署配置3.1、安装maven插件3.2、新建项目3.3、自动发布到测试服务器四、publish over ssh 配置4.1、超时机制4.2、shell的日志输出4.3、运行前清理五…

网络地址转换NAT

目录 IP 地址空间即将面临耗尽的危险 NAT 缓解 IP 地址空间耗尽的问题 NAT 的基本方法 VPN 的要点 IP 地址空间即将面临耗尽的危险 互联网采用了无分类编址方式、动态分配IP地址等措施来减缓IP地址空间耗尽的速度 但由于互联网用户数目的激增&#xff0c;特别是大量小型办公…

Linux搭建DHCP服务

DHCP(Dynamic Host Confifuration Protocol,动态主机配置协议)它可以为客户自动分配IP地址、以及缺省网关、DNS服务器的IP地址等TCP/IP参数。 简单说,就是在DHCP服务器上有一个存放着IP地址、网关、DNS等参数。当客户端请求使用时,服务器则负责将相应的参数分配给客户端,…

win10环境下基于face_recognition搭建自己的人脸识别软件

在win10环境下安装face_recognition&#xff0c;了解face_recognition中api的使用&#xff0c;如人脸截取、人脸矫正、人脸特征提取、人脸关键点提取、人脸mask获取、人脸特征比对等功能。最后构建自己的人脸数据库&#xff0c;使用knn实现人脸识别软件。 1、安装face_recogni…

【圣诞特辑】码一个漂漂亮亮的圣诞树(Single Dog版)

目录 前言 一、C语言版圣诞树 1.代码实现 2.效果图 二、python版圣诞树 1.代码实现 2.效果图​ 三、html5版圣诞树 1.代码实现 2.效果图 总结 前言 圣诞节即将来临&#xff0c;圣诞树也是必不可少的装饰之一。圣诞树是一棵绿叶繁茂的树&#xff0c;上面挂满了彩色的灯…

Nginx学习笔记2【尚硅谷】

host文件修改时&#xff0c;可以更改用户组权限或者复制到某个有权限的位置修改完再复制替换之前的文件。 在server{}中&#xff0c;listenserver_name两个加一起是唯一的。 代理服务器就是一个网关。 配置Nginx反向代理&#xff1a; 注意&#xff1a;在写proxy_pass时&#xf…

java+selenium环境搭建

目录 1.写在前面的话: 2.下载谷歌驱动 3.添加Selenium依赖(我这里添加的是4.0.0版本的) 4.在操作过程中可能出现的问题&解决办法 目录 1.写在前面的话: 2.下载谷歌驱动 3.添加Selenium依赖(我这里添加的是4.0.0版本的) 1.写在前面的话: (1)java版本最低要求为8,Chro…

SpringBoot整合Activemq

目录 一、Pom.xml 二、Spring配置文件 三、队列 四、主题 一、Pom.xml <dependencies><!-- activemq核心依赖包 --><dependency><groupId>org.apache.activemq</groupId><artifactId>activemq-all</artifactId><version>…

终生学习——读书有什么坏处

一般爱读书者往往受到赞扬&#xff0c;但仍然需要谨记一些读书的原则 目录 一、读书的整体观点 二、为什么需要知道读书的坏处 三、何时会出现读书的坏处 四、读书有什么坏处 1、100%全部相信书中的观点&#xff0c;进而实践了错误观点 2、不实践 五、如何杜绝读书的害处…

程序员为了少加班想了这几招

&#x1f4e3;&#x1f4e3;&#x1f4e3;&#x1f4e3;&#x1f4e3;&#x1f4e3;&#x1f4e3; &#x1f38d;大家好&#xff0c;我是慕枫 &#x1f38d;前阿里巴巴高级工程师&#xff0c;InfoQ签约作者、阿里云专家博主&#xff0c;一直致力于用大白话讲解技术知识 &#x…

一个简单的Linux内核字符驱动程序编写

一、背景 为了了解设备驱动程序的框架&#xff0c;在此编写一个简单的字符驱动程序&#xff0c;以此来对驱动程序的框架进行一个简单的了解。 二、设备驱动程序 所谓设备驱动程序&#xff0c;其实就是计算机硬件与外部设备进行通信的接口。由于硬件设备各式各样&#xff0c;…

【Ctfer训练计划】——(四)

作者名&#xff1a;Demo不是emo 主页面链接&#xff1a;主页传送门创作初心&#xff1a;舞台再大&#xff0c;你不上台&#xff0c;永远是观众&#xff0c;没人会关心你努不努力&#xff0c;摔的痛不痛&#xff0c;他们只会看你最后站在什么位置&#xff0c;然后羡慕或鄙夷座右…

【kafka】学习笔记(三)

学习笔记七、Kafka-Eagle 监控7.1 环境准备7.2 Eagle 安装7.3、修改配置文件7.4、添加环境变量7.5、启动Eagle八、Kafka-Kraft 模式8.1、Kafka-Kraft 集群部署8.2、初始化集群数据目录8.3、启动 kafka 集群8.4、测试8.5、集群启动脚本九、SpringBoot集成Kafka七、Kafka-Eagle 监…

RabbitMQ 第一天 基础 4 RabbitMQ 的工作模式 4.3 Routing 路由模式

RabbitMQ 【黑马程序员RabbitMQ全套教程&#xff0c;rabbitmq消息中间件到实战】 文章目录RabbitMQ第一天 基础4 RabbitMQ 的工作模式4.3 Routing 路由模式4.3.1 模式说明4.3.2 代码编写4.3.3 小结第一天 基础 4 RabbitMQ 的工作模式 4.3 Routing 路由模式 4.3.1 模式说明 …

React 学习笔记总结(四)

文章目录1. 创建组件流程(以及脚手架环境流程)2. 样式 的模块化3. 常用快捷生成4. 通用性 组件编码流程5. React脚手架 配置代理5.1 React 引入 ajax库5.2 第一种配置代理方式(package.json)5.3 第二种代理方式(setupProxy.js)6. React List列表效果实现7. React 消息订阅与发布…

“内卷之王”vivo:成败即将见分晓

文丨熔财经 作者|XL 12月22日&#xff0c;随着年底收官之作S16系列正式发布&#xff0c;vivo完成了自己的年度答卷。2022年&#xff0c;vivo总体风头正盛&#xff0c;尤其在第三季度一马当先稳居国内出货量榜首&#xff0c;市占比提升到20.0%&#xff0c;领先第二名3%。这是一…

elementUI中el-table每行异常高度原因排查,累死

理论上不单独设置高度的话&#xff0c;表格每一个应该是默认的高度才对&#xff0c;我说的没错吧&#xff0c; 但是请看实际情况&#xff1a; 这是默认情况下的高度为48 还有两外一个表格&#xff0c;我也没有设置高度&#xff0c;但是但是&#xff1a;这个高度竟然达到了71&…

深入理解蓝牙BLE之“无线通信的调制解调”

FSK&#xff1a; Frequency Shift Keying&#xff0c;频移键控&#xff0c;即一种允许根据数字调制信号改变载波频率而进行数据传输的数字调制技术&#xff0c;比如在BFSK中&#xff0c;二进制1和二进制0期间传输不同频率的载波信号。由于这种调制解调方式容易实现&#xff0c…

我国水产养殖行业现状及趋势分析:不断推进产业机械化高质量发展

水产养殖业主要是人类利用适宜水域养殖水产经济动植物的生产事业&#xff0c;是渔业的重要组成部分。按养殖水域&#xff0c;水产养殖可分为淡水养殖、海水养殖、浅海滩涂养殖&#xff1b;按养殖对象&#xff0c;可分为鱼类养殖、贝类养殖、虾类养殖、蟹类养殖、藻类栽培&#…