Spring-Boot

在 HttpServletRequest 中添加自定义请求头

HTTP 请求头一般都是由客户端设置,服务端获取,用以处理业务。但是偶尔也有一些需求,需要服务端对一些请求,添加自定义的请求头。例如:统一为所有请求添加一个名为 X-Requested-Id 的请求头,用于跟踪不同请求。 Servlet 中的请求对象 jakarta.servlet.http.HttpServletRequest 并未提供设置 Header 的方法。 但是,但是通过一些方法,可以实现。本教程将会教你如何在 Spring Boot 应用中添加自定义请求头到 HttpServletRequest。 思路 既然可以从 HttpServletRequest 获取到 Header,那它一定是把 Header 存储在了某个地方。我们只要找到 HttpServletRequest 存储 Header 的容器,就可以对其进行添加、编辑、删除操作。 不同 HttpServletRequest 的实现中,对 Header 的存储方式不一定一样。目前,在 Spring Boot 中最流行的 Servlet 实现就是 Tomcat 和 Undertow,所以下文将会针对这两个服务器进行讲解。 示例应用 创建一个 Spring Boot 应用。我们要在 Filter 中为所有请求添加一个 X-Requested-Id 请求头,并在 Controller 中获取并返回。 Controller 如下: import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import jakarta.servlet.http.HttpServletRequest; @RestController @RequestMapping("/demo") public class DemoController { @GetMapping public String getHeaders (HttpServletRequest request) { // 获取 X-Requested-Id Header 值 String requestedId = request.

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.

在 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 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=.

在 Spring Boot 中配置 OpenTelemetry

1、概览 在本教程中,我们将学习如何在 Spring Boot 应用中整合 OpenTelemetry 。以及如何配置 OpenTelemetry 来追踪请求链路,并将其发送到中央系统以监控请求。 2、OpenTelemetry 简介 OpenTelemetry(Otel)是一组标准化的工具(与供应商无关)、API 和 SDK。它是一个 CNCF 孵化项目,是 OpenTracing 和 OpenCensus 项目的合并产物。 OpenTracing 用于向可观测性后端发送 telemetry(遥测)数据。OpenCensus 项目提供了一套特定于语言的库,开发人员可以用它来检测自己的代码,并将其发送到任何受支持的后端。Otel 使用与其前身项目相同的 trace 和 span 概念来表示微服务间的请求链路。 OpenTelemetry 允许我们检测、生成和收集 telemetry 数据,这有助于分析应用程序的行为或性能。telemetry 数据包括日志、指标和链路跟踪。 使用 Otel SDK,我们可以轻松地覆盖或添加更多属性到链路跟踪中。 让我们通过一个例子来深入了解一下。 3、示例应用 假设我们需要构建两个微服务,其中一个服务与另一个服务交互。 3.1、Maven 依赖 首先,我们将创建 Spring Boot Web 项目,并在两个应用中包含以下 Spring 和 OpenTelemetry 依赖项: spring-cloud-starter-sleuth、spring-cloud-sleuth-otel-autoconfigure 和 opentelemetry-exporter-otlp 将自动捕获链路跟踪并导出到任何支持的 collector。 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-sleuth</artifactId> <exclusions> <exclusion> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-sleuth-brave</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.

Spring Boot 3 整合 Spring Cloud 开发微服务应用

Spring Boot 3.0 已于 2022 年 11 月底全面 发布。本文将教你如何使用 Spring Boot 3 和 Spring Cloud 组件构建微服务。 总的来说,本文将涉及以下主题: 在云原生开发中使用 Spring Boot 3。 使用 Spring Cloud Netflix Eureka 为所有微服务提供服务发现功能。你可能想说 “在还用 Eureka?” - 是的,Eureka 还在。它是 Spring Cloud 中最后一个可用的 Netflix 微服务组件。 使用 Spring Cloud OpenFeign 进行服务间通信。 使用 Spring Cloud Config 作为分布式配置中心。 使用 Spring Cloud Gateway 作为网关,其中包括使用 Springdoc 项目创建全局 OpenAPI 文档。 使用 Micrometer OpenTelemetry 和 Zipkin 采集链路追踪。 从 Spring Boot 2 迁移到 Spring Boot 3 并不是太麻烦,具体变更的细节和迁移方法可以参考 这篇文章。

在 Spring Boot 中整合、使用 WebSocket

WebSocket 是一种基于 TCP 协议的全双工通信协议,它允许客户端和服务器之间建立持久的、双向的通信连接。相比传统的 HTTP 请求 - 响应模式,WebSocket 提供了实时、低延迟的数据传输能力。通过 WebSocket,客户端和服务器可以在任意时间点互相发送消息,实现实时更新和即时通信的功能。WebSocket 协议经过了多个浏览器和服务器的支持,成为了现代 Web 应用中常用的通信协议之一。它广泛应用于聊天应用、实时数据更新、多人游戏等场景,为 Web 应用提供了更好的用户体验和更高效的数据传输方式。 本文将会指导你如何在 Spring Boot 中整合、使用 WebSocket,以及如何在 @ServerEndpoint 类中注入其他 Bean 依赖 。 在 Spring Boot 中使用 WebSocket 有 2 种方式。第 1 种是使用由 Jakarta EE 规范提供的 Api,也就是 jakarta.websocket 包下的接口。第 2 种是使用 spring 提供的支持,也就是 spring-websocket 模块。前者是一种独立于框架的技术规范,而后者是 Spring 生态系统的一部分,可以与其他 Spring 模块(如 Spring MVC、Spring Security)无缝集成,共享其配置和功能。 2 种方式各有优劣,你可以按需选择。本文将使用第 1 种方式,也就是使用 jakarta.websocket 来开发 WebSocket 应用。 软件版本: Spring Boot:3.1.3 在 Spring Boot 中整合 WebSocket 添加依赖 在 pom.

Spring Boot REST API 最佳实践 - 第四章

在 “Spring Boot REST API 最佳实践” 系列教程的前几章中,我们已经学习了如何实现 CRUD 操作。在本章节教程中,我们将了解如何为 API 实现异常处理。 Spring Boot REST API 最佳实践 - 第一章:实现 Get Collection API Spring Boot REST API 最佳实践 - 第二章:实现 Create 和 Update API Spring Boot REST API 最佳实践 - 第三章:实现 FindById 和 DeleteById API Spring Boot REST API 最佳实践 - 第四章:REST API 的异常处理(本文) 你可以在此 GitHub 仓库中找到本教程的示例代码。 如 第三章节 所述,如果 Controller 中的请求处理方法抛出异常,Spring Boot 将使用默认的异常处理机制进行处理并返回响应。 如果你只关心在抛出异常时返回正确的 HTTP 状态码,你可以异常类上使用 @ResponseStatus 注解来指定使用哪个 HTTP 状态码,而不是默认的 INTERNAL_SERVER_ERROR - 500。

Spring Boot REST API 最佳实践 - 第三章

在本章节教程中,我们将了解如何实现 FindById 和 DeleteById API 端点。 Spring Boot REST API 最佳实践 - 第一章:实现 Get Collection API Spring Boot REST API 最佳实践 - 第二章:实现 Create 和 Update API Spring Boot REST API 最佳实践 - 第三章:实现 FindById 和 DeleteById API(本文) Spring Boot REST API 最佳实践 - 第四章:REST API 的异常处理 你可以在此 GitHub 仓库中找到本教程的示例代码。 实现 GET /api/bookmarks/{id} API 端点 我们希望实现一个根据指定 id 获取单个资源的 API 端点,如果找到,以 HTTP 状态码 200 返回。如果未找到,则返回 HTTP 状态码 404,可选择返回包含异常信息的响应体。 实现 GET /api/bookmarks/{id} API 端点,如下: