1、概览 本文将带你全面了解如何使用 Spring Data JPA 在 PostgreSQL JSONB 列中存储、检索 JSON 数据。
2、VARCHAR 映射 本节将介绍如何使用 AttributeConverter 将 VARCHAR 类型的 JSON 值转换为自定义 Java POJO。
其目的是方便 Java 数据类型中的实体属性值与数据库列中的相应值之间的转换。
2.1、Maven 依赖 要创建 AttributeConverter,必须在 pom.xml 中加入 Spring Data JPA 依赖:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> <version>2.7.18</version> </dependency> 2.2、数据表定义 数据库表定义如下:
CREATE TABLE student ( student_id VARCHAR(8) PRIMARY KEY, admit_year VARCHAR(4), address VARCHAR(500) ); student 表有三个字段,其中我们希望 address 列能存储具有以下结构的 JSON 值:
{ "postCode": "TW9 2SF", "city": "London" } 2.3、Entity 类 创建一个相应的 POJO 类,用 Java 表示 address 数据:
1、概览 本文将带你了解如何在 Spring WebClient 中自定义 JSON 的反序列化(Deserialization)。
2、为什么需要自定义反序列化? Spring WebFlux 模块中的 Spring WebClient 通过 Encoder 和 Decoder 组件处理序列化和反序列化。编码器(Encoder)和解码器(Decoder)是表示读取和写入内容的接口。默认情况下,spring-core 模块提供 byte[]、ByteBuffer、DataBuffer、Resource 和 String 编码器和解码器实现。
Jackson 是一个 JSON 库,它通过 ObjectMapper 将 Java 对象序列化为 JSON,并将 JSON 字符串反序列化为 Java 对象。ObjectMapper 包含内置的配置选项,可以使用 Deserialization Feature 进行开启或关闭。
当 Jackson 库提供的默认行为无法满足我们的特定需求时,就有必要定制反序列化过程。为了在序列化和反序列化过程中修改行为,ObjectMapper 提供了一系列配置选项供我们设置。因此,我们需要将这个自定义的 ObjectMapper 注册到 Spring WebClient 中,以便在序列化和反序列化中使用。
3、如何自定义 ObjectMapper? 自定义 ObjectMapper 可以在全局应用程序级别与 WebClient 关联,也可以与特定请求关联。
以一个获取客户订单详细信息的 GET 端点为例。
OrderResponse Model 如下:
{ "orderId": "a1b2c3d4-e5f6-4a5b-8c9d-0123456789ab", "address": [ "123 Main St", "Apt 456", "Cityville" ], "orderNotes": [ "Special request: Handle with care", "Gift wrapping required" ], "orderDateTime": "2024-01-20T12:34:56" } 对于上述响应的一些反序列化规则如下:
1、简介 gRPC 是一个高性能的开源 RPC 框架,最初由谷歌开发。它有助于消除样板代码,并在数据中心内外连接多语言服务。该 API 基于 Protocol Buffer,它提供了一个 protoc 编译器,用于生成不同支持的语言的代码。
我们可以将 gRPC 视为 REST、SOAP 或 GraphQL 的替代品,它建立在 HTTP/2 的基础上,可以使用多路复用或流式连接等功能。
本文将带你了解如何使用 Spring Boot 实现 gRPC 服务提供者和消费者。
2、面临的问题 首先,Spring Boot 并不直接支持 gRPC。它只支持 Protocol Buffer,允许我们实现基于 protobuf 的 REST 服务。因此,需要通过使用第三方库来加入 gRPC:
平台相关的编译器:protoc 编译器是平台相关的。因此,如果在构建过程中需要生成存根(Stub),构建过程会变得更加复杂且容易出错。 依赖: 需要在 Spring Boot 应用中添加兼容的依赖。不幸的是,Java 的 protoc 添加了 javax.annotation.Generated 注解(Issues),这迫使我们需要添加一个依赖项来编译旧的 Java EE 注解库。 服务器运行时:gRPC 服务提供者需要在服务器中运行。gRPC for Java 项目提供了一个 shaded Netty,我们需要将其包含在 Spring Boot 应用中,或者用 Spring Boot 已经提供的服务器来代替。 消息传输: Spring Boot 提供了不同的客户端,如 RestClient(阻塞)或 WebClient(非阻塞),但遗憾的是,这些客户端无法配置和用于 gRPC,因为 gRPC 在阻塞和非阻塞调用中都使用了 自定义 transport 技术。 配置: 由于 gRPC 使用了自己的技术,我们需要配置属性以按照 Spring Boot 的方式对其进行配置。 3、示例项目 幸运的是,可以使用第三方 Spring Boot Starter 来应对这些挑战,例如 LogNet 或 grpc ecosystem project。这两个 Starter 都很容易整合,但后者同时支持提供者和消费者以及许多其他集成功能,因此本文选择了后者。
1、概览 本文将带你了解如何使用 Spring Modulith 来监听 Spring Application Event 并自动将其发布到 Kafka Topic。
2、事务操作和 Message Broker 假设,正在开发一个保存文章的功能:
@Service class Baeldung { private final ArticleRepository articleRepository; // 构造函数 @Transactional public void createArticle(Article article) { validateArticle(article); article = addArticleTags(article); // ...其他业务逻辑 articleRepository.save(article); } } 此外,还需要向系统的其他部分通知这一新文章。其他模块或服务会根据此做出反应,例如创建报告或向网站读者发送新闻邮件。
最简单的方法是使用 KafkaOperations 向 baeldung.articles.published Kafka Topic 发送消息,并使用文章的 slug() 作为关 Key:
@Service class Baeldung { private final ArticleRepository articleRepository; private final KafkaOperations<String, ArticlePublishedEvent> messageProducer; // 构造函数 @Transactional public void createArticle(Article article) { // .
1、概览 后端 HTTP API 开发最重要的功能之一是解析前端传递的请求查询参数。
本文将带你了解几种直接从 HttpServletRequest 获取查询参数的方法,以及 Spring MVC 提供的一些简洁方法。
2、HttpServletRequest 中的方法 首先,来看看 HttpServletRequest 提供的与参数相关的方法。
2.1、HttpServletRequest#getQueryString() HttpServletRequest#getQueryString() 可以直接从 URL 获取查询字符串信息:
@GetMapping("/api/byGetQueryString") public String byGetQueryString(HttpServletRequest request) { return request.getQueryString(); } 使用 curl 向该 API 发送一个包含多个参数的 GET 请求时,getQueryString() 方法会返回 ? 后面的所有字符:
$ curl 'http://127.0.0.1:8080/spring-mvc-basics/api/byGetQueryString?username=bob&roles=admin&roles=stuff' username=bob&roles=admin&roles=stuff 如果将 @GetMapping 更改为 @RequestMapping,当使用 POST/PUT/PATCH/DELETE HTTP 方法发送请求时,返回的响应相同。也就是说 HttpServletRequest#getQueryString 始终获取到的是 URL 中的查询参数,无论 HTTP 方法是什么。因此,本教程只关注GET请求。
2.2、HttpServletRequest#getParameter(String) 为了简化参数的解析,HttpServletRequest 提供了一个 getParameter 方法,可以通过参数名获取参数值:
@GetMapping("/api/byGetParameter") public String byGetParameter(HttpServletRequest request) { String username = request.
在应用中把 Redis 当成消息队列来使用已经屡见不鲜了。我想主要原因是当代应用十有八九都会用到 Redis,因此不用再引入其他消息队列系统。而且 Redis 提供了好几种实现消息队列的方法,用起来也简单。
使用 Redis 实现消息队列的几种方式 Redis 提供了多种方式来实现消息队列。
Pub/Sub 订阅发布模式,发布者把消息发布到某个 Channel,该 Channel 的所有订阅者都会收到消息。但是这种方式最大的问题是 发布出去的消息,如果没有被监听消费,或者消费过程中宕机,那么消息就会永远丢失。适合用于临时通知之类的场景,对于需要保证数据不丢失的场景不能使用这种方式。
List List 是 Redis 提供的一种数据类型,底层是链表,可以用来实现队列、栈。
Stream Stream 是一个由 Redis 5 引入的,功能完善的消息队列。想必也是 Redis 官方团队看到太多人拿 Redis 当消息队列使,于是干脆就在 Redis 上设计出一个类似于 Kafka 的消息队列。
Steam 支持消费组消费,一条消息只能被消费组中的其中一个消费者消费。支持 消息确认、支持 回溯消费 还支持把未 ACK(确认)的消息转移给其他消费者进行重新消费,在进行转移的时候还会累计消息的转移次数,当次数达到一定阈值还没消费成功,就可以放入死信队列。
这也是 Redis 种最复杂的一种数据类型。如果你真的到了需要使用 Redis Steam 作为消息队列的地步,那不如直接使用 RabbitMQ 等更加成熟且稳定的消息队列系统。
使用 List 实现可靠的消息队列 目前来说,这是用得最多的一种方式,适用于大多数简单的消息队列应用场景。List 类型有很多指令,但是作为消息队列来说用到的只有几个个:
LPUSH key element [element ...]
把元素插入到 List 的首部,如果 List 不存在,会自动创建。
BRPOPLPUSH source destination timeout
移除并且返回 List (source)尾部的最后一个元素,并且同时会把这个元素插入到另一个 List (destination)的首部。
Spring Boot 3.2.2 版本的详细更新内容如下:
🐞 Bug 修复 SSLBundle 实现未提供有用的 toString() 结果 #39167 JarEntry.getComment() 从 NestedJarFile 实例返回不正确的结果 #39166 在 server.ssl 属性中混合 PEM 和 JKS 类型的证书不起作用 #39158 仅仅在 classpath 上引入 AspectJ 和 Micrometer 并不足以启用对 Micrometer observation 注解的支持 #39128 当映射到 / 时,无法访问未使用选择器(Selector)操作的 Actuator 端点。#39122 由于缺少 Authentication Manager,使用 WebFlux、Security 和 Actuator 的 Spring Boot 3.2 应用可能无法启动 #39096 management.observations.http.server.requests.name 不再生效 #39083 spring.rabbitmq.listener.stream.auto-startup 属性不起作用 #39078 PatternParseException 的日志信息中的错误标记位置不对 #39075 server.jetty.max-connections 配置无效 #39052 依赖于初始的 CharSequence 到 String 转换的 @ConfigurationPropertiesBinding 转换器不再起作用 #39051 在新的加载器实现中无法解析 Manifest attributes #38996 来自日志系统初始化的 Throwable 可能导致应用在启动时默默地失败 #38963 使用 Jetty 时,IO 操作和延迟调度的空闲超时不能设置为小于 30000ms #38960 当 jar 放在 WSL 网络驱动器上时,spring-boot-maven-plugin repackage uber jar 执行失败 #38956 Oracle OJDBC BOM 版本被标记为不适合生产使用 #38943 使用 jOOQ 且未设置 spring.
1、概览 本文将带你了解如何在 Spring Cloud Gateway 中实现全局异常处理。
在现代软件开发中,尤其是在微服务中,API 的高效管理至关重要。这正是 Spring Cloud Gateway 作为 Spring 生态系统的关键组件发挥重要作用的地方。它就像一个门卫,将流量和请求引导到适当的微服务,并提供跨切面的关注点,如安全性、监控/指标和弹性。
然而,在如此复杂的环境中,由于网络故障、服务宕机或应用错误而产生的异常是必然的,这就需要一个强大的异常处理机制。Spring Cloud Gateway 的全局异常处理可确保在所有服务中采用一致的错误处理方法,并增强整个系统的弹性和可靠性。
2、全局异常处理的必要性 Spring Cloud Gateway 是 Spring 生态系统中的一个项目,旨在作为微服务架构中的 API 网关,其主要作用是根据预先制定的规则将请求路由到相应的微服务。网关提供安全(认证和授权)、监控和熔断(Circuit Breakers)等功能。通过处理请求并将其导向适当的后端服务,它有效地管理了诸如安全性和流量管理等横切关注点。
在微服务等分布式系统中,异常可能来自多个方面,如网络问题、服务不可用、下游服务错误和应用级错误,这些都是常见的罪魁祸首。在这种环境下,以本地化方式(即在每个服务内)处理异常可能会导致零散和不一致的错误处理。这种不一致性会使调试工作变得繁琐,并降低用户体验:
全局异常处理通过提供集中的异常管理机制,确保所有异常(无论其来源如何)都能得到一致的处理,并提供标准化的错误响应,从而应对这一挑战。
这种一致性对于系统恢复能力、简化错误跟踪和分析至关重要。它还能提供精确一致的错误格式,帮助用户了解出错的原因,从而提升用户体验。
3、在 Spring Cloud Gateway 中实现全局异常处理 在 Spring Cloud Gateway 中实现全局异常处理涉及几个关键步骤,每个步骤都能确保建立一个强大而高效的异常管理系统。
3.1、创建自定义全局异常处理器 全局异常处理器对于捕获和处理网关中发生的异常至关重要。为此,需要继承 AbstractErrorWebExceptionHandler 并将其添加到 Spring Context 中。这样,就创建了一个能拦截所有异常的集中式处理器。
@Component public class CustomGlobalExceptionHandler extends AbstractErrorWebExceptionHandler { // 构造函数和其他方法 } 该类应能处理各种类型的异常,从 NullPointerException 等一般异常到 HttpClientErrorException 等更具体的异常。目标是涵盖各种可能的错误。该类的核心方法如下所示。
@Override protected RouterFunction<ServerResponse> getRoutingFunction(ErrorAttributes errorAttributes) { return RouterFunctions.
1、概览 Spring WebFlux 是一个响应式 Web 框架,它提供了一个非阻塞 Event Loop,可异步处理 I/O 操作。此外,它还使用 Mono 和 Flux Reactive Stream Publisher 在订阅时发布数据。
这种响应式方式可帮助应用处理大量请求和数据,而无需分配大量资源。
本文将带你了解如何在 Spring WebFlux 中处理 Multipart 文件上传。
2、项目设置 创建一个简单的响应式 Spring Boot 项目,将 Multipart 文件上传到一个目录。
为简单起见,使用项目的根目录来存储文件。在生产中,可以使用 云厂商 OSS、Minio 存储等文件系统。
2.1、Maven 依赖 首先,在 pom.xml 中添加 spring-boot-starter-webflux 依赖,以启动 Spring WebFlux 应用:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> <version>3.2.0</version> </dependency> 它提供核心 Spring WebFlux API 和嵌入式 Netty 服务器,用于构建响应式 Web 应用。
另外,还要在 pom.xml 文件中添加 spring-boot-starter-data-r2dbc 和 H2 数据库依赖:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-r2dbc</artifactId> <version>3.2.0</version> </dependency> <dependency> <groupId>com.
1、概览 在许多情况下,可以在 JWT Access Token 添加自定义 Claim,从而在 Token Payload 中包含更多信息。
本文将带你了解如何在 Spring Authorization Server 中为 JWT Access Token 添加资源所有者授权。
2、Spring Authorization Server Spring Authorization Server 是 Spring 生态系统中的一个新项目,旨在为 Spring 应用提供授权服务器支持。它通过 Spring 编程模型简化 OAuth 2.0 和 OpenID Connect(OIDC) 授权服务器的实现。
2.1、Maven 依赖 首先,在 pom.xml 中导入 spring-boot-starter-web、spring-boot-starter-security、spring-boot-starter-test 和 spring-security-oauth2-authorization-server 依赖:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <version>2.5.4</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> <version>2.5.4</version> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-oauth2-authorization-server</artifactId> <version>0.2.0</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <version>2.5.4</version> </dependency> 或者,可以在 pom.xml 文件中添加 spring-boot-starter-oauth2-authorization-server 依赖: