当前位置: 首页 > news >正文

重学SpringBoot3-集成Redis(二)之注解驱动

更多SpringBoot3内容请关注我的专栏:《SpringBoot3》
期待您的点赞👍收藏⭐评论✍

重学SpringBoot3-集成Redis(二)之注解驱动

  • 1. 为什么选择 Redis 作为缓存?
  • 2. 如何在 Spring Boot 中启用 Redis 缓存?
    • 2.1 添加 Redis 依赖
    • 2.2 配置 Redis 连接
    • 2.3 启用缓存支持
  • 3. 注解驱动的缓存机制
    • 3.1 @Cacheable示例
    • 3.2 @CachePut示例
    • 3.3 @CacheEvict示例
  • 4. 自定义缓存管理
    • 4.1 RedisCacheConfiguration 类
      • 4.1.1. 过期时间(TTL - Time To Live)
      • 4.1.2. 键序列化方式
      • 4.1.3. 值序列化方式
      • 4.1.4. 禁用缓存空值(Disable Caching Null Values)
      • 4.1.5. 使用前缀(Use Cache Key Prefixes)
      • 4.1.6. 设置空闲时间(Idle Time)
      • 4.1.7. 组合多种配置
      • 4.1.8. 设置自定义的过期策略
    • 4.2 自定义缓存配置
  • 5. Redis 缓存的常见问题和优化建议
  • 6. 总结

Spring Boot 提供了对缓存的简便支持,使得开发者能够通过简单的注解实现缓存操作,减少重复代码的编写。本文将详细介绍如何在 Spring Boot 3 中使用 Redis 作为缓存,并通过注解驱动的方式进行缓存操作。

1. 为什么选择 Redis 作为缓存?

Redis 是一个高效的键值对存储系统,特别适合于构建高性能、可扩展的缓存层。其优点包括:

  • 高吞吐量:Redis 使用内存作为存储介质,读取和写入性能极快,能够支撑高并发的访问需求。
  • 数据持久化:尽管 Redis 是内存数据库,它也支持将数据持久化到磁盘,防止数据丢失。
  • 丰富的数据结构:Redis 不仅支持简单的字符串存储,还支持哈希、列表、集合等丰富的数据结构,适用于多种应用场景。
  • 易于扩展:通过 Redis 的集群功能,可以很容易地扩展 Redis 实例,处理更大规模的数据和请求。

2. 如何在 Spring Boot 中启用 Redis 缓存?

Spring Boot 提供了对缓存的开箱即用支持,开发者只需简单配置即可使用。具体参考上一章 重学SpringBoot3-集成Redis(一)。

2.1 添加 Redis 依赖

pom.xml 中引入 Redis 和 Spring Cache 相关依赖:

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

2.2 配置 Redis 连接

application.yml 中,配置 Redis 服务器地址及相关连接池配置:

spring:cache:type: redis     	 	# 使用 Redis 作为缓存类型data:redis:host: localhostport: 6379            # Redis 端口password: 			# 如果有密码可以在这里配置lettuce:pool:max-active: 100    # 最大并发连接数max-idle: 50       # 最大空闲连接数min-idle: 10       # 最小空闲连接数

2.3 启用缓存支持

在 Spring Boot 项目中,使用 @Cacheable 注解前,需要通过 @EnableCaching 注解启用缓存功能。可以在主应用类或者任何配置类中加上这个注解:

import org.springframework.cache.annotation.EnableCaching;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
@EnableCaching
public class MyApplication {public static void main(String[] args) {SpringApplication.run(MyApplication.class, args);}
}

3. 注解驱动的缓存机制

Spring 提供了一组注解用于操作缓存,这些注解可以直接应用于方法上,使得代码更简洁。常用注解包括:

  • @Cacheable:用于标记一个方法的返回值是可缓存的。下一次调用该方法时,Spring 会直接从缓存中返回结果,而不是再次执行方法。
  • @CachePut:在方法执行后将返回值放入缓存。它与 @Cacheable 的区别在于,@CachePut 不会跳过方法执行,而是始终执行方法并更新缓存。
  • @CacheEvict:用于清除缓存中的某些条目,可以指定缓存的 key 或清空整个缓存空间。

3.1 @Cacheable示例

import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;@Service
public class UserService {// 当方法第一次调用时,结果将被缓存起来,之后相同参数的调用将直接从缓存中获取数据@Cacheable(value = "user", key = "#p0")public User getUserById(Long id) {// 模拟数据库查询操作System.out.println("Fetching user with id: " + id);return new User(id, "User" + id);}
}

解释:

  • @Cacheable 用于缓存方法的返回值。
  • value = "user" 指定了缓存的名称,即 “user”。
  • key = "#p0" 指定了缓存的键值。这里的 #p0 是一个 SpEL 表达式,表示方法的第一个参数。

在这个例子中,方法 getUserById 第一次被调用时,结果会缓存到 Redis 中,并与 user::id 作为 key 存储。后续相同 id 的请求将直接从缓存返回,而无需执行方法。

@Cacheable添加缓存

3.2 @CachePut示例

有时候,我们希望方法执行后,不仅返回结果,还更新缓存,这时可以使用 @CachePut 注解。

import org.springframework.cache.annotation.CachePut;
import org.springframework.stereotype.Service;@Service
public class UserService {// 无论缓存中是否存在数据,该方法都会被执行,并且返回值会更新缓存@CachePut(value = "user", key = "#p0.id")public User updateUser(User user) {System.out.println("Updating user with id: " + user.getId());// 模拟数据库更新操作user.setName("Updated " + user.getName());return user;}
}

解释:

  • @CachePut 用于更新缓存中的值。
  • value = "user" 指定了缓存的名称,即 “user”。
  • key = "#p0.id" 指定了缓存的键值。这里的 #p0 是一个 SpEL 表达式,表示方法的第一个参数,即 User 对象。.id 表示取 User 对象的 id 属性作为缓存键。

连续两次调用 curl "http://localhost:8080/api/redis/updAndSave?id=2" ,可以从日志中看到,每次方法都执行了,并且 user 对象加入到了缓存中。

@CachePut更新缓存

3.3 @CacheEvict示例

为了保持缓存数据的准确性,某些情况下需要手动清除缓存中的数据。@CacheEvict 注解允许我们在数据修改或删除时,移除缓存中的旧数据。

import org.springframework.cache.annotation.CacheEvict;
import org.springframework.stereotype.Service;@Service
public class UserService {// 清除缓存中的指定用户数据@CacheEvict(value = "user", key = "#p0")public void deleteUser(Long id) {System.out.println("Deleting user with id: " + id);// 模拟数据库删除操作}// 清空整个缓存空间@CacheEvict(value = "user", allEntries = true)public void clearCache() {System.out.println("Clearing all user cache");}
}

调用 curl "http://localhost:8080/api/redis/delUser?id=1" ,删除 key 为 user::1 的缓存。

@CacheEvict删除缓存

调用 curl "http://localhost:8080/api/redis/delAllUser" ,删除所有前缀为 user:: 的缓存。

@CacheEvict删除所有缓存

4. 自定义缓存管理

以上缓存名称、过期时间和序列化方式都是默认设置,Spring 允许我们自定义缓存管理器。在大多数情况下,默认配置足够使用,但如果需要定制化的缓存行为,我们可以自定义缓存配置。通过实现 RedisCacheConfiguration,我们可以设置缓存的过期时间、序列化方式等。

4.1 RedisCacheConfiguration 类

Spring Boot 3 中,RedisCacheConfiguration 类是用于配置 Redis 缓存行为的核心组件之一。它提供了多种方法,用于自定义 Redis 缓存的各类设置,比如缓存过期时间、序列化策略等。以下是一些常用的配置选项:

4.1.1. 过期时间(TTL - Time To Live)

设置缓存条目的默认生存时间(TTL)。这决定了缓存数据在 Redis 中保留的时间。

RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofMinutes(10)); // 设置缓存10分钟后过期

4.1.2. 键序列化方式

默认情况下,Redis 使用二进制存储键和值。RedisCacheConfiguration 提供了设置键(key)序列化方式的方法。常见的序列化方式包括 StringRedisSerializer,可以使用它来确保键以字符串格式存储:

import org.springframework.data.redis.serializer.StringRedisSerializer;RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig().serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()));

4.1.3. 值序列化方式

同样,值(value)的序列化方式也可以自定义。常用的序列化方式有 GenericJackson2JsonRedisSerializer,它将对象序列化为 JSON 格式:

import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig().serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));

4.1.4. 禁用缓存空值(Disable Caching Null Values)

你可以配置不缓存空值,避免 Redis 存储 null,减少缓存的无效占用。

RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig().disableCachingNullValues();

4.1.5. 使用前缀(Use Cache Key Prefixes)

Redis 中默认会为缓存键值加上一个命名空间的前缀,以防止不同缓存键冲突。可以自定义这个前缀,也可以关闭它:

RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig().prefixCacheNameWith("myApp::")  // 自定义缓存键前缀.computePrefixWith(cacheName -> "customPrefix::" + cacheName + "::");  // 使用自定义逻辑

要禁用前缀:

RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig().disableKeyPrefix();

4.1.6. 设置空闲时间(Idle Time)

你可以设置一个键的空闲时间,Redis 将会在指定的时间内删除不再被访问的键。

RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofMinutes(10)).enableTimeToIdle();

4.1.7. 组合多种配置

可以将多个配置组合到一起:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;import java.time.Duration;@Configuration
public class CacheConfig {@Beanpublic RedisCacheConfiguration redisCacheConfiguration() {return RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofMinutes(10))  // 缓存的过期时间.disableCachingNullValues()        // 不缓存 null 值.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))  // 自定义 key 序列化.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer())); // 自定义 value 序列化}
}

4.1.8. 设置自定义的过期策略

可以为不同的缓存区域设置不同的过期策略。例如:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheManager;@Configuration
public class CacheConfig {@Beanpublic RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) {RedisCacheConfiguration defaultConfig = RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofMinutes(5));RedisCacheConfiguration longLivedConfig = RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofHours(1));Map<String, RedisCacheConfiguration> cacheConfigurations = new HashMap<>();cacheConfigurations.put("shortLivedCache", defaultConfig);cacheConfigurations.put("longLivedCache", longLivedConfig);return RedisCacheManager.builder(connectionFactory).withInitialCacheConfigurations(cacheConfigurations).build();}
}

4.2 自定义缓存配置

import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;import java.time.Duration;@Configuration
public class CacheConfig {@Beanpublic RedisCacheConfiguration cacheConfiguration() {return RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofMinutes(10))  // 设置缓存过期时间为 10 分钟.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer())) // 自定义 Key 序列化器.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer())); // 自定义 Value 序列化器}
}

通过这种方式,我们可以对缓存的过期时间、序列化方式进行更细粒度的控制。

自定义配置

5. Redis 缓存的常见问题和优化建议

尽管 Redis 是一个高效的缓存解决方案,但在实际应用中,仍然有一些需要注意的问题:

  • 缓存穿透:大量请求查询缓存中不存在的 key,导致所有请求都直接打到数据库上,降低系统性能。解决方案是使用布隆过滤器来拦截非法请求。
  • 缓存雪崩:当大量缓存同时过期时,可能会导致瞬间的大量请求直接涌入数据库,造成系统崩溃。可以通过设置不同的过期时间(TTL)来缓解这一问题。
  • 缓存击穿:某个热点 key 在缓存过期后,大量并发请求直接打到数据库上。解决方案是使用互斥锁,避免大量请求同时加载缓存。

6. 总结

通过本文,我们学习了如何在 Spring Boot 3Java 17 中使用 Redis 作为缓存。Spring 提供了注解驱动的缓存操作方式,使得缓存操作变得非常简单易用。通过合理配置和使用缓存,我们能够极大地提升系统的性能和响应速度。在生产环境中,合理的缓存策略、过期时间和缓存层优化将会进一步提高系统的稳定性和扩展能力。

相关文章:

重学SpringBoot3-集成Redis(二)之注解驱动

更多SpringBoot3内容请关注我的专栏&#xff1a;《SpringBoot3》 期待您的点赞&#x1f44d;收藏⭐评论✍ 重学SpringBoot3-集成Redis&#xff08;二&#xff09;之注解驱动 1. 为什么选择 Redis 作为缓存&#xff1f;2. 如何在 Spring Boot 中启用 Redis 缓存&#xff1f;2.1 …...

【React】入门Day04 —— 项目搭建及登录与表单校验、token 管理、路由鉴权实现

项目搭建 创建项目 # 使用npx创建项目 npx create-react-app my-react-app # 进入项目目录 cd my-react-app # 创建项目目录结构 mkdir -p src/{apis,assets,components,pages,store,utils} touch src/{App.js,index.css,index.js} 使用npx create-react-app创建项目&#xff0…...

CMake 属性之目录属性

【写在前面】 CMake 的目录属性是指在特定目录&#xff08;及其子目录&#xff09;范围内有效的设置。 这些属性不同于全局变量或目标&#xff08;Target&#xff09;属性&#xff0c;它们提供了一种机制&#xff0c;允许开发者为项目中的不同部分定义不同的构建行为。 通过目录…...

ChatGPT:引领人工智能新潮流!

一、ChatGPT 是什么&#xff1f; 1. ChatGPT 的强大功能和广泛应用。 ChatGPT 作为一款先进的 AI 语言模型&#xff0c;拥有众多强大功能。它可以进行文本生成、文本分类、情感分析、机器翻译等多种自然语言处理任务。同时&#xff0c;ChatGPT 还能进行对话式交互&#xff0c;…...

【银河麒麟高级服务器操作系统】安全配置基线相关分析全过程及解决方案

了解更多银河麒麟操作系统全新产品&#xff0c;请点击访问 麒麟软件产品专区&#xff1a;https://product.kylinos.cn 开发者专区&#xff1a;https://developer.kylinos.cn 文档中心&#xff1a;https://documentkylinos.cn 服务器环境以及配置 【机型】物理机或虚机 【…...

用Python实现图片转ASCII艺术:图像处理与字符艺术的完美结合

解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 ASCII艺术是一种通过字符来表现图像的艺术形式,最早用于早期计算机显示器,它仅支持字符显示。如今,尽管图像分辨率和显示技术得到了极大的提升,ASCII艺术作为一种复古而别具一格的图像表现形式,仍然受到许多…...

大数据-162 Apache Kylin 全量增量Cube的构建 Segment 超详细记录 多图

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; 目前已经更新到了&#xff1a; Hadoop&#xff08;已更完&#xff09;HDFS&#xff08;已更完&#xff09;MapReduce&#xff08;已更完&am…...

Redis-缓存过期淘汰策略

缓存淘汰策略 生产上redis内存设置为多少 设置为最大内存的 3/4 redis 会占用物理机多少内存 默认大小是 0&#xff0c;64 位系统下表示不限制内存大小&#xff0c;32位系统表示 3G 如何设置修改redis内存大小 config get maxmemory 查看修改方式 配置文件 单位是字节 2.…...

如何设置LED电子显示屏的屏幕参数?

LED电子显示屏因其高亮度、低能耗和长寿命等优点&#xff0c;在广告、信息显示等领域得到了广泛应用。正确设置屏幕参数对于确保显示屏的最佳性能至关重要。以下是LED电子显示屏设置屏幕参数的步骤&#xff1a; 1. 确定屏幕参数 在开始设置之前&#xff0c;需要了解显示屏的基本…...

Spring Boot Starter Parent介绍

引言 spring-boot-starter-parent 是一个特殊的项目&#xff0c;为基于 Spring Boot 的应用程序提供默认配置和默认依赖。 在本 Spring Boot 教程中&#xff0c;我们将深入了解所有 Spring Boot 项目内部使用的 spring-boot-starter-parent 依赖项。我们将探讨此依赖项所提供…...

【含开题报告+文档+PPT+源码】基于SpringBoot乡村助农益农平台的设计与实现

开题报告 近年来&#xff0c;随着社会经济的快速发展和人民生活水平的提高&#xff0c;人们对优质农产品的需求越来越高。然而&#xff0c;传统的农产品销售管理模式存在一些问题。首先&#xff0c;农产品供应链信息不透明&#xff0c;导致生产者难以了解市场需求和价格变动趋…...

数据中心运维挑战:性能监控的困境与智能化解决方案的探寻

随着数字化进程的加速&#xff0c;数据中心已成为企业信息架构的核心支撑&#xff0c;其运维管理的复杂度和重要性也随之提升。运维团队需应对设备老化、资源分配失衡、性能波动等多重难题&#xff0c;以确保数据中心持续高效运行。 其中&#xff0c;性能监控作为运维管理的关键…...

基于SSM的民宿管理系统【附源码】

基于SSM的民宿管理系统&#xff08;源码L文说明文档&#xff09; 目录 4 系统设计 4.1 系统概要设计 4.2 系统功能结构设计 4.3 数据库设计 4.3.1 数据库E-R图设计 4.3.2 数据库表结构设计 5 系统实现 5.1用户信息管理 5.2 房东信息管理…...

显卡 3090 vs v100

1.3090 Date: 2020 AmperePielines/ Cuda cores: 10496 2.V100 Date: 2018 VoltaPielines/ Cuda cores: 5129 3.结构 & Core比较: v100优点: v100功耗小v100较快的双精度(fp64)和混合精度(fp16fp32)pcie版的NVLink与2080ti完全一致 v100缺点: 不支持整数格式计算&…...

怎么在单片机裸机程序中移植EasyLogger?

1、介绍 EasyLogger 是一款超轻量级、高性能的C日志库&#xff0c;非常适合对资源敏感的软件项目。例如&#xff1a;IoT产品、可穿戴设备、智能家居等等。相比log4c、zlog这些知名的C日志库&#xff0c;EasyLogger的功能更加简单&#xff0c;提供给用户的接口更少&#xff0c;但…...

C/C++解析文件名和目录路径

文章目录 主要函数使用注意事项示例程序总结 #include <libgen.h> 是一个 C/C 语言的头文件&#xff0c;主要用于字符串处理&#xff0c;特别是在处理文件路径时。它提供了一些函数来帮助你解析文件名和目录路径。 主要函数 以下是 libgen.h 中一些常见的函数&#xff…...

Git 基本命令行操作

Git是一个开源的分布式版本控制系统&#xff0c;用于管理源代码和文档的版本。以下是Git的基本命令行操作&#xff1a; 一、配置 安装完成后&#xff0c;需要配置Git的用户名和邮箱&#xff0c;以便在提交记录时记录操作者的信息。 配置全局用户名&#xff1a;git config --g…...

【Rust练习】17.泛型

练习题来自&#xff1a;https://practice-zh.course.rs/generics-traits/generics.html 函数 1 // 填空 struct A; // 具体的类型 A. struct S(A); // 具体的类型 S. struct SGen<T>(T); // 泛型 SGen.fn reg_fn(_s: S) {}fn gen_spec_t(_s: SGen<A&…...

java脚手架系列4--测试用例、拦截器

异常处理、拦截器、数据库连接 1 测试用例 单元测试是一个老生常谈的问题&#xff0c;无论是后端对自己的代码质量把的第一道关也好&#xff0c;也是对测试减缓压力。这里就不过多讲述测试用例的重要性&#xff0c;但是有2个框架我们必须了解一下。 1.1 JUnit和mockito 我们…...

论文推荐 |【Agent】自动化Agent设计系统

论文标题&#xff1a; Automated Design of Agentic Systems 论文地址&#xff1a; https://arxiv.org/abs/2408.08435 GitHub地址&#xff1a; https://github.com/ShengranHu/ADAS 自动化代理设计在性能和通用性方面显著超越了手动方法。 • 引入了自动化代理系统设计&am…...

Linux操作系统提供了五种主要的IO(输入/输出)模型

Linux操作系统提供了五种主要的IO&#xff08;输入/输出&#xff09;模型&#xff0c;这些模型旨在优化应用程序对输入输出操作的管理和处理。以下是关于这五种IO模型的详细介绍。 一、阻塞IO&#xff08;Blocking IO&#xff09; 阻塞IO是最常见、最传统的IO模型。在这种模型…...

基于深度学习的花卉识别系统

简介&#xff1a; 基于Python的花卉识别分类系统利用深度学习和计算机视觉技术&#xff0c;能够准确识别和分类各种花卉&#xff0c;如玫瑰、郁金香和向日葵等。这种系统不仅有助于植物学研究和园艺管理&#xff0c;还在生态保护、智能农业和市场销售等领域展现广泛应用前景。随…...

【斯坦福CS144】Lab0

一、实验目的 1.初步了解计算机网络&#xff0c;准备实验所需的材料和环境&#xff1b; 2.掌握基础实验方法&#xff1b; 3.动手实现网络功能。 二、实验内容 1.下载实验所需的资料&#xff0c;安装虚拟机&#xff0c;配置环境&#xff1b; 2.获取一个网页&#xff1b; …...

关于Mybatis中,IPage<PO>转换成IPage<VO>的问题

以下是一个比较常见通用的一个查询并且为单表查询&#xff0c;在开发初期&#xff0c;或者项目不是很复杂的时候&#xff0c;或者一开始项目框架就规划好的情况下&#xff0c;通常我们都会封装。 在我们的项目中&#xff0c;这部分代码其实是自动生成的&#xff0c;足以满足大…...

使用idea和vecode创建vue项目并启动(超详细)

一、idea创建vue项目 创建项目之前先下载好插件 新建项目找到vue生成器 写好名称&#xff0c;找到自己需要存放的地址&#xff0c;node解释器安装方式可以看我上一个博客&#xff0c;vueCLI是选择vue的版本&#xff0c;我们可以使用idea自带的vue版本默认是vue3&#xff0c;创…...

C#|.net core 基础 - 删除字符串最后一个字符的七大类N种实现方式

今天想通过和大家分享如何删除字符串最后一个字符的N种实现方法&#xff0c;来回顾一些基础知识点。 01第一类、字符串方式 这类方法是通过string类型自身方法直接实现。 1、Substring方法 相信大多数人第一个想到的可能就是这个方法。Substring方法是字符串内置方法&#…...

成都睿明智科技有限公司怎么样靠谱吗?

随着短视频与直播的深度融合&#xff0c;抖音电商凭借其强大的流量入口、精准的算法推荐以及便捷的购物体验&#xff0c;迅速崛起。对于传统企业和新兴品牌而言&#xff0c;这无疑是一个不可多得的机遇。然而&#xff0c;如何在这片红海中脱颖而出&#xff0c;就需要借助专业的…...

docker简述

1.安装dockers&#xff0c;配置docker软件仓库 安装&#xff0c;可能需要开代理&#xff0c;这里我提前使用了下好的包安装 启动docker systemctl enable --now docker查看是否安装成功 2.简单命令 拉取镜像&#xff0c;也可以提前下载使用以下命令上传 docker load -i imag…...

第27周:Transformer实战:文本分类

目录 前言 一、前期准备 1.1 环境安装 1.2 加载数据 二、数据预处理 2.1 构建词典 2.2 生成数据批次和迭代器 2.3 构建数据集 三、模型构建 3.1 定义位置编码器 3.2 定义Transformer模型 3.3 初始化模型 3.4 定义训练函数 3.5 定义评估函数 四、训练模型 4.1 模…...

在QT中将Widget提升为自定义的Widget后,无法设置Widget的背景颜色问题解决方法

一、问题 在Qt中将QWidget组件提升为自定义的QWidget后&#xff0c;Widget设置的样式失效&#xff0c;例如设置背景颜色为白色失效。 二、解决方法 将已经提升的QWidget实例对象&#xff0c;脱离父窗体的样式&#xff0c;然后再重新设置自己的样式。...