1、概览 在本文中,我们将学习如何在使用 Spring Cache 时获取 Caffeine 缓存中的所有缓存 KEY。
2、Spring Cache 缓存(Cache)是 Spring Framework 不可分割的一部分。从 3.1 版本开始,它就是 Spring 生态系统的一部分。因此,它拥有一套定义明确、久经考验的接口。
让我们来看看其中两个主要接口: CacheManager 和 Cache:
interface CacheManager { Cache getCache(String name); Collection<String> getCacheNames(); } public interface Cache { String getName(); Object getNativeCache(); ValueWrapper get(Object key); <T> T get(Object key, @Nullable Class<T> type); <T> T get(Object key, Callable<T> valueLoader); void put(Object key, @Nullable Object value); ValueWrapper putIfAbsent(Object key, @Nullable Object value); void evict(Object key); void clear(); } 我们可以看到,CacheManager 是应用程序中可用缓存的注册中心。而 Cache 对象则是缓存内的一组键值对。
1、概览 我们经常需要为开发和部署过程中的不同阶段创建不同的配置。在 Spring Boot 应用中,我们可以为每个不同的阶段定义一个 Spring Profile 并为其创建专门的测试。
在本教程中,我们将介绍如何使用 JUnit 5 基于激活的 Spring Profile 来进行测试。
2、项目设置 首先,在我们的项目中添加 spring-boot-starter-web 依赖:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> 现在,让我们创建一个简单的 Spring Boot 应用:
@SpringBootApplication public class ActiveProfileApplication { public static void main (String [] args){ SpringApplication.run(Application.class); } } 最后,创建 application.yaml 配置文件。
3、Spring Profile Spring Profile 提供了一种方法,通过对每个环境的特定配置进行分组,来定义和管理不同的环境。
通过激活特定的 Profile,我们可以在不同的配置之间轻松切换。
3.1、在 Properties 中激活 Profile 我们可以在 application.yaml 文件中指定要激活的 profile:
spring: profiles: active: dev 现在 Spring 将检索激活的 profile 的所有属性,并将所有专用 Bean 加载到 application context 中。
一般我们会使用 multipart/form-data 请求来上传文件。multipart/form-data 请求可以有多个子请求体,每个子请求体都可以有自己的 header 和 body。
本文将带你了解如何在 Spring Boot 应用中使用 multipart/form-data 请求同时上传文件、JSON、表单数据。
服务端 Controller 定义文件上传 controller。
package cn.springdoc.demo.controller; import java.io.IOException; import java.io.InputStream; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.MediaType; import org.springframework.util.StreamUtils; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestPart; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import cn.springdoc.demo.model.Meta; @RestController @RequestMapping("/upload") public class UploadController { private static final Logger log = LoggerFactory.getLogger(UploadController.class); /** * 文件上传 * @param file * @param response * @return * @throws IOException */ @PostMapping(consumes = MediaType.
1、概览 Thymeleaf 是一种流行的 Java 模板引擎,它允许我们创建动态网页。它提供了多种属性,用于将数据从模型绑定到视图。
在本教程中,我们将了解 Thymeleaf 中 th:text 和 th:value 属性之间的主要区别。
2、th:text 属性 Thymeleaf 中的 th:text 属性用于设置元素的文本内容。
它还取代了标准的 HTML text 属性。因此,我们可以把它放在任何支持文本内容的 HTML 元素中,如标题、段落、标签等。
我们还可以使用该属性来显示动态文本内容,例如网页上的标题。
假设我们想在 HTML 页面上显示 controller 提供的 title 属性。
首先,让我们创建一个 controller 类和一个指定模型属性的方法:
@GetMapping public String show(Model model) { model.addAttribute("title", "Baeldung"); return "attributes/index"; } 接下来,我们将在标题元素中显示值:
<h1 th:text="${title}"/> 在这里,Thymeleaf 会计算表达式 ${title},并将该值插入标题元素。
我们将得到的 HTML 如下:
<h1>Baeldung</h1> 此外,与标准 HTML text 属性不同,th:text 属性支持表达式。除了变量,这些表达式还可能包括运算符和函数。
例如,让我们在没有提供 title 属性的情况下指定默认值:
<h1 th:text="${title} ?: 'Default title'"/> 3、th:value 属性 另一方面,th:value 属性用于设置通常需要用户输入的元素的值。输入框、复选框、单选按钮和下拉按钮等元素都属于此类。
1、概览 在本教程中,我们将学习如何在 Spring Boot 中调用 OpenAI ChatGPT API。我们将创建一个 Spring Boot 应用程序,通过调用 OpenAI ChatGPT API 来生成对提示的回复。
2、OpenAI ChatGPT API 在开始本教程之前,让我们先了解一下本教程中将使用的 OpenAI ChatGPT API。我们将调用 create chat completion API 来生成对提示的回复。
2.1、API 参数和认证 让我们来看看 API 强制的请求参数:
model - 是我们将向其发送请求的模型版本。该模型有几个版本。我们将使用 gpt-3.5-turbo 模型,它是 该模型的最新公开版本。
messages - 发送给模型的提示。每条 message 都需要两个字段:role 和 content。role 字段指定信息的发送者。在请求中是 user,在回复中是 assistant。content 字段是实际的消息。
API 调用需要认证,我们需要生成一个 OpenAI API key。在调用 API 时在 Authorization 头中设置该 key。
cURL 格式的请求示例如下:
$ curl https://api.openai.com/v1/chat/completions \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $OPENAI_API_KEY" \ -d '{ "model": "gpt-3.
1、简介 在这个简短的教程中,我们将了解如何在 Spring Boot 中使用虚拟线程(Virtual Threads)。
虚拟线程是 Java 19 的 预览特性,这意味着它们将在未来 12 个月内被纳入 JDK 的正式版本中。虚拟线程最初是由 Loom 项目引入的,在 Spring 6 中,开发人员可以一睹为快了。
首先,我们将了解 “平台线程” 与 “虚拟线程” 的主要区别。接下来,我们将使用虚拟线程从头开始构建一个 Spring-Boot 应用。最后,我们会进行一个测试,测试 web 应用的吞吐量提升了多少。
2、虚拟线程和平台线程 主要区别在于,虚拟线程在运行周期内不依赖操作系统线程:它们与硬件脱钩,因此被称为 “虚拟”。这种解耦是由 JVM 提供的抽象层赋予的。
虚拟线程的运行成本远低于平台线程。它们消耗的内存要少得多。这就是为什么我们可以创建数百万个虚拟线程而不会出现内存不足的问题,而标准平台(或内核)线程只能创建数百个。
从理论上讲,这赋予了开发人员一种超级能力:无需依赖异步代码即可管理高度可扩展的应用程序。
3、在 Spring 6 中使用虚拟线程 从 Spring Framework 6(和 Spring Boot 3)开始,虚拟线程功能正式全面可用,但虚拟线程是 Java 19 的预览特性。这意味着我们需要告诉 JVM 我们想在应用程序中启用虚拟线程。由于我们使用 Maven 构建应用程序,因此要确保在 pom.xml 中包含以下代码:
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>19</source> <target>19</target> <compilerArgs> --enable-preview </compilerArgs> </configuration> </plugin> </plugins> </build> 从 Java 的角度来看,要使用 Apache Tomcat 和虚拟线程,我们需要一个简单的配置类和几个 Bean:
在 Spring 应用中,无论使用 JdbcTemplate 还是 JPA/Hibernate 或 Spring Data JPA,都需要处理数据库事务。
数据库事务是一个事务单元,它要么全部完成,要么都不完成,并使数据库处于一致状态。在实现数据库事务时,需要考虑到 ACID(原子性、一致性、隔离性、持久性)属性。
让我们了解一下如何在 Spring Boot 应用中处理数据库事务。
使用 JDBC 进行事务处理 首先,让我们快速了解一下我们通常是如何在普通 JDBC 中处理数据库事务的。
class UserService { void register(User user) { String sql = "..."; Connection conn = dataSource.getConnection(); // <1> try(conn) { // <6> conn.setAutoCommit(false); // <2> PreparedStatement pstmt = conn.prepareStatement(sql); pstmt.setString(1, user.getEmail()); pstmt.setString(2, user.getPassword()); pstmt.executeUpdate(); // <3> conn.commit(); // <4> } catch(SQLException e) { conn.rollback(); // <5> } } } 在上述代码片段中:
在调用第三方Api服务的时候,如果涉及到文件上传,就需要自己通过 Http 客户端发起 Multipart 请求来上传文件。
在 Spring 应用中比较流行的 Http 客户端就是 RestTemplate。本文将会指导你如何用 RestTemplate 发起 Multipart 请求来上传文件。
服务端 在服务端创建一个用于测试的 FileUploadController, 它接受来自客户端的 Multipart 文件请求,并且响应文件的相关信息。
package cn.springdoc.demo.controller; import java.io.IOException; import java.io.InputStream; import java.util.HashMap; import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.MediaType; import org.springframework.util.StreamUtils; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestPart; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import jakarta.servlet.http.HttpServletResponse; @RestController @RequestMapping("/upload") public class FileUploadController { private static final Logger log = LoggerFactory.getLogger(FileUploadController.class); /** * 文件上传 * @param file * @param response * @return * @throws IOException */ @PostMapping(consumes = MediaType.
1、简介 模块化单体(Modular Monolith)是一种架构风格,在这种风格中,我们的源代码按照模块的概念进行结构化。对于许多组织来说,模块化单体是一个很好的选择。它有助于保持一定程度的独立性,这有助于我们在需要时过渡到微服务架构。
Spring Modulith 是 Spring 的一个实验项目,可用于模块化单体应用程序。此外,它还支持开发人员构建结构合理、领域一致的 Spring Boot 应用程序。
在本教程中,我们将讨论 Spring Modulith 项目的基础知识,并举例说明如何实际使用它。
2、模块化单体架构 我们有不同的选择来构建应用程序的代码。传统上,我们围绕基础设施设计软件解决方案。但是,当我们围绕业务设计应用程序时,就能更好地理解和维护系统。模块化单体架构就是这样一种设计。
模块化单体架构因其简单性和可维护性而越来越受到架构师和开发人员的青睐。如果我们将领域驱动设计(DDD)应用于现有的单体应用程序,就可以将其重构为模块化单体架构:
我们可以通过确定应用程序的领域和定义有界上下文,将单体的核心拆分成模块。
让我们来看看如何在 Spring Boot 框架内实现模块化单体应用程序。Spring Modulith 包含一系列库,可帮助开发人员构建模块化 Spring Boot 应用程序。
3、Spring Modulith 基础 Spring Modulith 可帮助开发人员使用由领域(domain)驱动的模块,并支持对这种模块化进行验证和文档化。
3.1、Maven 依赖 首先,让我们在 pom.xml 的 <dependencyManagement> 部分导入 spring-modulith-bom 依赖:
<dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.experimental</groupId> <artifactId>spring-modulith-bom</artifactId> <version>0.5.1</version> <scope>import</scope> <type>pom</type> </dependency> </dependencies> </dependencyManagement> 此外,我们还需要一些 Spring Modulith 核心依赖:
<dependency> <groupId>org.springframework.experimental</groupId> <artifactId>spring-modulith-api</artifactId> </dependency> <dependency> <groupId>org.springframework.experimental</groupId> <artifactId>spring-modulith-starter-test</artifactId> <scope>test</scope> </dependency> 3.2、模块 Spring Modulith 的主要概念是模块。模块是将 API 暴露给其他模块的功能单元。此外,它还有一些不允许其他模块访问的内部实现。当我们设计应用程序时,我们会为每个域(domain)考虑一个模块。
1、概览 Spring Boot CLI 是一个 Spring Boot 工具,用于从命令运行和测试 Spring Boot 应用。该工具提供了一个非常有用的密码编码功能,主要目的是避免暴露明文形式的密码。
在本教程中,我们将深入 Spring Security 的世界,学习如何使用 Spring Boot CLI 对密码进行编码。
2、密码编码 密码编码是一种将密码以二进制格式表示并保存在存储介质上的简单方法。我们可以使用 Spring Security 对密码进行编码,也可以通过 Spring Boot CLI 进行编码。
2.1、Spring Security PasswordEncoder Spring Security 提供了 PasswordEncoder 接口,并且预置了很多实现,如 StandardPasswordEncoder 和 BCryptPasswordEncoder。
此外,Spring Security 建议使用基于强大算法和随机生成盐值的 BCryptPasswordEncoder。在框架的早期版本中,可以使用 MD5PasswordEncoder 或 SHAPasswordEncoder 类,但由于其算法的弱点,它们现在已被弃用,这两个类强制开发者将盐作为构造函数参数传递。而 BCryptPasswordEncoder 将在内部生成随机盐,BCryptPasswordEncoder 生成的字符串大小为 60 个字符。
而 StandardPasswordEncoder 类则基于 SHA-256 算法。
显然,在第三方系统中创建的用户密码必须按照 Spring Security 中选择的编码类型进行编码,这样才能成功进行身份认证。
2.2、Spring Boot CLI Password Encoder Spring Boot CLI 提供了许多命令,其中之一就是 encodepassword。该命令允许对密码进行编码,以便与 Spring Security 配合使用。简单地说,Spring Boot Cli 可以使用这种简单的 encodepassword 命令直接将原始密码转换为加密密码: