教程

在 Springdoc 文档中配置身份认证,以访问需要认证的的端点

1、概览 Springdoc-OpenAPI 是一个为 Spring Boot 应用程序自动生成 API 文档的框架。它实现了 OpenAPI 3 规范,使用它,通过 UI 界面就可以与 API 进行交互,非常方便。 在本教程中,我们将学习如何使用 Spring Security 通过表单登录和 Basic Authentication 来认证 springdoc 中的端点访问。 2、项目设置 创建一个 Spring Boot Web 应用程序,该应用程序将通过 Spring Security 保护 API,并使用 Springdoc 生成文档。 2.1、依赖 首先添加 springdoc-openapi-ui,它整合了 Swagger-UI,用于提供 UI 界面: http://localhost:8080/swagger-ui.html 其次,添加 springdoc-openapi-security,用于为 Spring Security 提供支持: <dependency> <groupId>org.springdoc</groupId> <artifactId>springdoc-openapi-ui</artifactId> <version>1.6.13</version> </dependency> <dependency> <groupId>org.springdoc</groupId> <artifactId>springdoc-openapi-security</artifactId> <version>1.6.13</version> </dependency> 2.2、示例 API 创建一个示例 REST Controller,Springdoc 会为其生成文档。 此外,我们将通过 Swagger-UI 来演示与 FooController 中受保护(需要认证)的端点进行交互。 @RestController @RequestMapping(value = "foos", produces = MediaType.

使用 Webclient 以流式下载大文件

1、简介 在本教程中,我们将学习如何使用 WebClient 从服务器以流式下载一个大文件。我们通过创建一个简单的 Controller 和两个客户端进行演示。最后,我们将了解如何以及何时使用 Spring 的 DataBuffer 和 DataBufferUtils 工具类。 2、服务器 创建一个可以下载文件的简单 Controller。 首先,构建一个 FileSystemResource,传递一个文件路径,然后将其封装为 ResponseEntity 的 body: @RestController @RequestMapping("/large-file") public class LargeFileController { @GetMapping ResponseEntity<Resource> get() { return ResponseEntity.ok() .body(new FileSystemResource(Paths.get("/tmp/large.dat"))); } } 其次,我们需要生成下载所用的示例文件,文件内容并不重要,所以我们使用 fallocate 在磁盘上生成一个指定大小的“空”内容文件。如下: fallocate -l 128M /tmp/large.dat 然后就可以开始编写客户端了。 3、WebClient 使用 ExchangeStrategies 处理大文件 先用一个简单而有限的 WebClient 下载文件。使用 ExchangeStrategies 来提高 exchange() 操作的可用内存限制。这样,就能操作更多字节,但仍受限于 JVM 可用的最大内存。 使用 bodyToMono() 从服务器获取 Mono<byte[]>: public class LimitedFileDownloadWebClient { public static long fetch(WebClient client, String destination) { Mono<byte[]> mono = client.

Spring Boot 启动时 “jar中没有主清单属性” 异常

1、概览 当我们在执行 Spring Boot JAR 文件时候,可能会遇到 “jar中没有主清单属性”(no main manifest attribute)错误。这是因为我们在 MANIFEST.MF 文件中缺少了 Main-Class 元数据属性的声明,该文件位于 META-INF 文件夹下。 在本教程中,我们将重点介绍造成这一问题的原因以及如何解决。 TL;DR 出现这个问题的原因,八成是你忘记在 pom.xml 中添加 spring-boot-maven-plugin 插件了,添加即可。如下: <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> 2、问题的出现 一般来说,从 Spring Initializr 获取 pom.xml 不会有任何问题。不过,如果我们是手动创建项目,自己在 pom.xml 中添加 spring-boot-starter-parent 依赖,可能会遇到这个问题。 我们可以尝试以 mvn clean package 的方式来构建应用,以重现这个问题: $ mvn clean package 运行 jar 时,我们会遇到错误: $ java -jar target\spring-boot-artifacts-2.jar no main manifest attribute, in target\spring-boot-artifacts-2.jar 在此示例中,MANIFEST.MF 文件的内容为: Manifest-Version: 1.0 Archiver-Version: Plexus Archiver Created-By: Apache Maven 3.

对 RestTemplate 上的 URI 变量进行编码

1、概览 我们经常遇到的一个编码问题是,URI 变量中包含一个加号(+)。例如,如果我们的 URI 变量值为 http://localhost:8080/api/v1/plus+sign,那么加号将被编码为空格,这可能会导致意外的服务器响应。 在本教程中,我们将学习如何在 Spring 的 RestTemplate 上对 URI 变量进行编码。 让我们来看看解决这个问题的几种方法。 2、项目设置 创建一个使用 RestTemplate 进行 API 调用的小项目。 2.1、Spring Web 依赖 在 pom.xml 中添加 Spring Web Starter 依赖: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> 或者,可以使用 Spring Initializr 生成项目并添加依赖。 2.2、RestTemplate Bean 创建一个 RestTemplate Bean: @Configuration public class RestTemplateConfig { @Bean public RestTemplate restTemplate() { return new RestTemplate(); } } 3、 调用 API 创建一个 service 类,调用公共 API http://httpbin.org/get。 API 会返回一个包含请求参数的 JSON 响应。例如,如果我们在浏览器上访问 URL https://httpbin.

在 Spring Boot 中使用 Undertow 作为嵌入式服务器

Spring Boot 默认使用 Tomcat 作为嵌入式 Servlet 服务器,它是由 Apache 软件基金会下 Jakarta 项目开发的 Servlet 容器,被广泛用于部署和运行 Java Web 应用程序。特点是轻量级、易于安装和配置,并且具有良好的可扩展性和性能 本文将会介绍另一款优秀的 Servlet 容器,Undertow。以及如何在 Spring Boot 中用它来替换 Tomcat 作为嵌入式服务器。 Undertow Undertow 是一个轻量级的、高性能的 Java Web 服务器,由 JBoss 开发并开源。它是基于非阻塞(non-blocking)的I/O模型,具有低资源消耗和高并发处理能力。 Undertown 的优势如下: 支持 HTTP/2:Undertow 开箱即支持 HTTP/2,无需重写启动类路径。 支持 HTTP Upgrade:允许通过 HTTP 端口复用多种协议。 支持 Web Socket:Undertow 提供对 Web Sockets 的全面支持,包括 JSR-356 支持。 Servlet 4.0:Undertow 支持 Servlet 4.0,包括对嵌入式 Servlet 的支持。还可以在同一部署中混合使用 Servlet 和原生 undertow 非阻塞 handler。 可嵌入式:只需几行代码,即可将 Undertow 嵌入应用程序或独立运行。 灵活性:Undertow 通过链式 handler 进行配置,可以根据需求灵活地添加功能。 在很多场景的测试下, Undertow 的性能都高于 Tomcat。天生适合作为 Spring Boot 应用的嵌入式服务器!

在 Spring 应用中实现 Kafka Consumer 重试消费

1、概览 本文将会带你学习在 Spring 应用中实现 Kafka Consumer 重试消费的 2 种方式,及其优缺点。 关于如何在 Spring 中整合 Kafka 的细节,请参阅 这里。 2、项目设置 创建一个新的 Spring Boot 项目,并添加 spring-kafka 依赖: <dependency> <groupId>org.springframework.kafka</groupId> <artifactId>spring-kafka</artifactId> <version>3.0.1</version> </dependency> 创建一个对象: public class Greeting { private String msg; private String name; // 构造函数、get、set 方法省略 } 3、Kafka Consumer Kafka Consumer(消费者)是从 Kafka 集群中读取数据的客户端应用程序。它订阅一个或多个 topic,并消费已发布的消息。Producer (生产者)向 topic 发送消息,topic 是存储和发布记录的类别名称。topic 被分为多个分区,以便横向扩展。每个分区都是一个不可更改的消息序列。 Consumer 可以通过指定偏移量(即消息在分区中的位置)来读取特定分区中的消息。Ack(确认)是消费者发送给 Kafka broker 的消息,表示它已成功处理了一条记录。一旦 ACK 被发送,消费者偏移量(consumer offset)将会被更新。 这将确保消息已被消费,并且不会再次传递给当前 Listener。 3.1、Ack 模式 Ack 模式决定了 broker 何时更新消费者偏移量(consumer offset)。

将 byte[] 转换为 MultipartFile

1、概览 MutlipartFile 是 Spring 提供的一个接口,用于接收 multipart 请求中的文件参数。Spring 没有为其提供任何默认实现,但提供了一个用于测试的实现。 在本教程中,我们将学习如何将字节数组转换为 MultipartFile。 2、实现 MultipartFile 接口 让我们创建自己的 MultipartFile 接口实现,并封装传入的字节数组: public class CustomMultipartFile implements MultipartFile { private byte[] input; @Override public String getName() { return null; } @Override public String getOriginalFilename() { return null; } @Override public String getContentType() { return null; } // 下一个代码段中定义了接口的其他方法 } 我们在类中定义了一个 byte[] 属性,存储传入的字节数组。接口中定义的其他几个描述性方法,可以根据需求来实现。这里默认返回 null。 剩余的几个接口方法是必须要实现的,如下: public class CustomMultipartFile implements MultipartFile { // 前一段儿代码省略... @Override public boolean isEmpty() { return input == null || input.

Spring 6 中的 AOT(Ahead of Time)优化

1、概览 Spring 6 提供了一项新功能,有望优化应用程序的性能: Ahead-of-Time(AOT) 编译支持。 在本文中,我们将了解 Spring 6 中 AOT 优化功能的工作原理、优点以及使用方法。 2、AOT 编译 2.1、JIT 编译器 对于最常用的 Java 虚拟机(JVM),如 Oracle 的 HotSpot JVM 和 OpenJDK,当我们编译源代码(.java 文件)时,生成的字节码存储在 .class 文件中。这样,JVM 就会使用 JIT(Just-In-Time,即时编译) 编译器将字节码转换为机器码。 此外,JIT 编译涉及 JVM 对字节码的解释,以及在运行时将频繁执行的代码动态编译为本地机器码。 2.2、AOT 编译器 Ahead-of-Time(AOT,提前编译或预编译)是一种在应用程序运行前将字节码预编译为本地机器码的技术。 Java 虚拟机(JVM)通常不支持这一功能。不过,甲骨文已在 OpenJDK 项目中发布了一项针对 HotSpot JVM 的实验性 AOT 功能,名为 “GraalVM Native Image”,允许进行 AOT 编译。 预编译代码后,计算机处理器可直接执行代码,无需 JVM 解释字节码,从而缩短了启动时间。 关于 AOT 编译器的更多细节可以参考 官方文档。 3、Spring 6 中的 AOT 支持 3.1、AOT 编译优化 在构建 Spring 6 应用程序时,我们需要考虑三种不同的运行时选项:

Spring Boot 中 Logback 和 Log4j2 的扩展

1、概览 日志是系统中的一个重要组件。Spring Boot 支持 Logback 和 Log4j2 日志框架,并且提供了一些扩展,可用于高级配置。 在本教程中,我将带你学习如何在 Spring Boot 中使用 Logback 和 Log4j2 的扩展进行高级的日志配置。 2、Logback 扩展 Spring Boot 默认使用 Logback 进行日志记录。在本节中,我们将了解 Logback 的一些扩展,以进行高级配置。 注意:Spring Boot 建议使用 logback-spring.xml 作为 Logback 的配置文件名称,而不是默认的 logback.xml。因为 logback.xml 配置文件会被 Logback 默认加载,它会比 Spring 更早地加载进系统,所以我们不能在标准的 logback.xml 中使用扩展, 2.1、Maven 依赖 要使用 Logback,我们需要在 pom.xml 中添加 logback-classic 依赖项。 spring-boot-starter-web 依赖已经包含了它,所以不需要额外导入 logback-classic: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> 2.2、基本日志 首先,在 Spring Boot main 类中输出一些示例日志: @SpringBootApplication public class SpringBootLogbackExtensionsApplication { private static final Logger logger = LoggerFactory.

在 Spring Boot 应用中设置 Cookie 的 SameSite 属性

SameSite 是一个用于增强 Web 应用程序安全性的 Cookie 机制。它定义了浏览器在发送跨站请求时是否应该附加 Cookie。旨在防止跨站请求伪造(CSRF)攻击和某些类型的跨站信息泄露攻击。 SameSite 属性是可选的,它有三个可选值: Strict(严格模式):在严格模式下,浏览器只会在用户访问与 Cookie 关联的站点时发送 Cookie。如果请求来自其他站点(包括跨站请求),浏览器将不会发送 Cookie。这样可以有效地防止跨站请求伪造攻击。 Lax(宽松模式):在宽松模式下,大多数情况下,浏览器只会在用户访问与 Cookie 关联的站点时发送 Cookie。但是,如果用户从外部站点通过 GET 方法访问当前站点的 URL,浏览器会发送 Cookie。这样可以在某些常见的使用情况下保持用户体验,同时仍然提供一定程度的安全性。总结如下: 请求类型 示例 正常情况 Lax 链接 <a href=...></a> 发送 Cookie 发送 Cookie 预加载 <link rel=prerender href=.../> 发送 Cookie 发送 Cookie GET 表单 <form method=GET action=...> 发送 Cookie 发送 Cookie POST 表单 <form method=POST action=...> 发送 Cookie 不发送 iframe <iframe src=...></iframe> 发送 Cookie 不发送 AJAX $.get(...) 发送 Cookie 不发送 Image <img src=.