1、概览 在 Spring Boot 应用中,一般使用 RestTemplate 来执行同步 HTTP 请求。数据通常以 JSON 的形式返回,而 RestTemplate 可以进行自动转换。
本文将带你了解,如何在 RestTemplate 中把响应的 JSON 数组转换为 Object 数组、POJO 数组和 POJO 集合。
2. JSON、POJO 和 Service 假设我们有一个端点 http://localhost:8080/users,它返回如下 JSON 格式的用户列表:
[{ "id": 1, "name": "user1", }, { "id": 2, "name": "user2" }] 对应的 User 类如下:
public class User { private int id; private String name; // get/set 方法省略 } 定义 Service 接口实现 UserConsumerServiceImpl,并注入 RestTemplate:
public class UserConsumerServiceImpl implements UserConsumerService { private final RestTemplate restTemplate; public UserConsumerServiceImpl(RestTemplate restTemplate) { this.
1、背景 有好几次线上发布老应用时,遭遇代码启动报错,具体错误如下:
Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'xxxManageFacadeImpl': Bean with name 'xxxManageFacadeImpl' has been injected into other beans [xxxProductMaintenceFacadeImpl] in its raw version as part of a circular reference, but has eventually been wrap means thff, for expped. This means that said other beans do not use the final version of the bean. This is often the result of over-eager type matching - consider using 'getBeanNamesallowEageOfType' with the 'allowEagerInit' flag turned off, for example 咋眼一看,这不就是 Spring Bean 循环依赖报错吗?脑海立马闪过那些年为了进阿里面试时被死亡 N 连问的场景,那时我们都知道 Spring 已经支持 Bean 循环依赖,为啥我们的 Spring Boot 应用启动时还报这个错误?于是,带着这个问题重新温习下 Spring 如何解决 Bean 循环依赖。
JdbcClient 是 Spring 6.1 引入的一个 Jdbc 客户端工具类,提供了 Fluent 链式调用风格的查询和更新方法,支持 JDBC 风格的位置参数和 Spring 风格的命名参数绑定。
本文将带你了解,如何在使用 JdbcClient 执行 insert 操作时返回自增 ID。
关于 JdbcClient 更多详细的用法可以参阅 “Spring 6 JdbcClient API 指南” 和 “Spring Boot 中的新 JDBC 客户端: JdbcClient”
创建数据表 在本地 MYSQL 数据库 demo 中创建一张简单的 t_user 表,如下:
CREATE TABLE `t_user` ( `id` int unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID', `create_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `enabled` tinyint unsigned NOT NULL COMMENT '是否启用。0:禁用,1:启用', `name` varchar(50) COLLATE utf8mb4_general_ci NOT NULL COMMENT '名字', PRIMARY KEY (`id`), UNIQUE KEY `name` (`name`) ) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='用户'; 其中, id 列是自增列。
1、概览 本文将带你了解给 Spring REST API 设置请求超时的几种方法。
当资源耗时过长时,请求超时机制可以避免糟糕的用户体验。当然也可以使用断路器模式(Circuit Breaker pattern)来实现,本文不细说。
2、@Transactional 超时 在数据库调用中实现请求超时的一种方法是利用 Spring 的 @Transactional 注解。它有一个 timeout 属性可以设置。该属性的默认值是 -1,相当于没有任何超时。
例如,假设将超时设置为 30 秒。如果注解方法的执行时间超过这个秒数,就会抛出异常。这对于回滚长时间运行的数据库查询可能很有用。
编写一个非常简单的 JPA Repository,它代表一个外部服务,该服务需要太长时间才能完成并导致超时。
这个 Repository 中有一个耗时的方法:
public interface BookRepository extends JpaRepository<Book, String> { default int wasteTime() { Stopwatch watch = Stopwatch.createStarted(); // 延迟 2 秒 while (watch.elapsed(SECONDS) < 2) { int i = Integer.MIN_VALUE; while (i < Integer.MAX_VALUE) { i++; } } } } 如果在超时时间为 1 秒的事务中调用 wasteTime() 方法,超时时间将在方法执行完毕之前结束:
1、简介 本文将带你了解如何使用 Spring AOP Aspect 获取 Advise 方法的签名、参数、注解以及其他的额外信息。
2、Maven 依赖 首先,在 pom.xml 中添加 spring-boot-starter-aop Starter 依赖:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> 3、创建 Pointcut 注解 创建一个 AccountOperation 注解,作为切面中的切点:
@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface AccountOperation { String operation(); } 注意,切点(Pointcut)不一定非要使用注解定义。也可以使用 Spring AOP 提供的 Pointcut 定义语言定义其他 Pointcut 类型,如类中的某些方法、以某些前缀开头的方法等。
4、创建示例 Service 4.1、Account 类 创建一个 Account POJO,带有 accountNumber 和 balance 属性。
在 service 方法中使用它作为方法参数:
public class Account { private String accountNumber; private double balance; // get/set toString方法省略 } 4.
1、概览 从 Spring 5 开始,可以使用 WebClient 以响应式、非阻塞的方式执行服务之间的 REST 通信。WebClient 是新的 WebFlux 框架的一部分,构建于 Project Reactor 之上。它使用 Fluent 风格的响应式 API,底层实现使用 HTTP 协议。
当发起 Web 请求时,数据通常会以 JSON 格式返回,本文将带你了解如何使用 WebClient 将响应的 JSON 数组转换为 Java Object 数组、POJO 数组和 POJO 集合。
2、依赖 在 pom.xml 中添加如下依赖:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> </dependency> <dependency> <groupId>org.projectreactor</groupId> <artifactId>reactor-spring</artifactId> <version>1.0.1.RELEASE</version> </dependency> 3、JSON、POJO 和 Service 从端点 http://localhost:8080/readers 开始,它以 JSON 数组的形式返回读者最喜欢的书籍列表:
[{ "id": 1, "name": "reader1", "favouriteBook": { "author": "Milan Kundera", "title": "The Unbearable Lightness of Being" } }, { "id": 2, "name": "reader2" "favouriteBook": { "author": "Douglas Adams", "title": "The Hitchhiker's Guide to the Galaxy" } }] 还需要相应的 Reader 和 Book 类来处理数据:
1、概览 本文将带你了解 Spring RestTemplate 抛出 IllegalArgumentException: Not enough variables available to expand 异常的原因以及解决办法。
2、原因 简而言之,当试图在 GET 请求参数中发送 JSON 数据时,通常会导致这个异常。
RestTemplate 提供了 getForObject 方法,通过在指定的 URL 上发出 GET 请求来获取表示对象。
出现异常的主要原因是 RestTemplate 将大括号中封装的 JSON 数据视为 URI 变量的占位符。
由于没有为预期的 URI 变量提供任何值,getForObject 方法就会抛出异常。
例如,尝试发送 {"name": "HP EliteBook"} 作为查询参数:
String url = "http://products.api.com/get?key=a123456789z&criterion={\"name\":\"HP EliteBook\"}"; Product product = restTemplate.getForObject(url, Product.class); 将导致 RestTemplate 抛出异常:
java.lang.IllegalArgumentException: Not enough variable values available to expand 'name' 3、示例应用 创建一个只有一个 GET 端点的基本 REST API 示例,来复现 RestTemplate 抛出 IllegalArgumentException 异常的情况。
1、概览 本文将带你全面了解 Spring @Component 注解及相关领域。
2、Spring ApplicationContext 在了解 @Component 之前,首先需要了解一下 Spring ApplicationContext。
Spring ApplicationContext 是 Spring 保存对象实例的地方,Spring 已确定这些实例将被自动管理和分发。这些实例被称为 Bean。
Spring 的一些主要功能包括 Bean 管理和依赖注入。
利用控制反转(Inversion of Control),Spring 可以从应用中收集 Bean 实例,并在适当的时候使用它们。可以在 Spring 中定义 Bean 依赖,而无需处理这些对象的设置和实例化。
使用 @Autowired 等注解将 Spring 管理的 Bean 注入应用的能力是在 Spring 中创建功能强大且可扩展代码的驱动力。
那么,如何让 Spring 来管理的 Bean 呢?可以利用 Spring 的自动 Bean 检测功能,通过在类中使用元注解(Stereotype Annotation)来实现。
3、@Component @Component 是一个注解,它允许 Spring 自动检测自定义 Bean。
换句话说,无需编写任何明确的代码,Spring 就能做到:
扫描应用,查找注解为 @Component 的类 将它们实例化,并注入任何指定的依赖 在需要的地方注入 不过,大多数时候应该使用更专业的元(Stereotype)注解来实现这一功能。
3.1、Spring 元注解 Spring 提供了一些专门的元注解:@Controller、@Service 和 @Repository。它们都提供了与 @Component 相同的功能。
1、概览 本文将带你了解 Spring 中出现 HttpMessageNotWritableException: "No converter found for return value of type" 异常的原因以及解决办法。
2、原因 通常,当 Spring 无法获取返回对象的属性时,就会出现这种异常。
导致这种异常的最典型原因通常是返回对象的属性没有任何 public getter 方法。
默认情况下,Spring Boot 依赖于 Jackson 库来完成序列化/反序列化请求和响应对象的所有工作。
因此,导致异常的另一个常见原因可能是 缺少或使用了错误的 Jackson 依赖。
简而言之,这种异常情况的一般准则是检查是否存在以下情况:
默认构造器 Getter 方法 Jackson 依赖 注意,异常类型 已从 java.lang.IllegalArgumentException 变为 org.springframework.http.converter.HttpMessageNotWritableException。
3、实例 现在,来看看一个会产生 org.springframework.http.converter.HttpMessageNotWritableException: "No converter found for return value of type" 异常的示例
使用 Spring Boot 构建一个基本的 REST API。
首先,创建 Student Model 类,并假装忘记生成 Getter 方法:
public class Student { private int id; private String firstName; private String lastName; private String grade; public Student() { } public Student(int id, String firstName, String lastName, String grade) { this.
1、概览 本文将带你了解 JAX-RS 和 Spring MVC 在 REST API 开发方面的区别。
2、Jakarta RESTful Web 服务 要成为 Jakarta EE 世界的一部分,一项功能必须具备规范、兼容的实现和 TCK(技术兼容套件)。JAX-RS 就是一套用于构建 REST 服务的规范。其最著名的参考实现是 RESTEasy 和 Jersey。
现在,通过实现一个简单的 Controller 来熟悉一下 Jersey:
@Path("/hello") public class HelloController { @GET @Path("/{name}") @Produces(MediaType.TEXT_PLAIN) public Response hello(@PathParam("name") String name) { return Response.ok("Hello, " + name).build(); } } 上面的代码中,端点返回一个简单的 “text/plain” 响应,这是由 @Produces 注解指定的。具体来说,暴露了一个名为 hello 的 HTTP 资源,它接受一个名为 name 的参数,使用了两个 @Path 注解进行路径的定义。还使用 @GET 注解指定它是一个 GET 请求。
3、使用 Spring MVC 实现 REST Spring MVC 是 Spring Framework 的一个模块,用于创建 Web 应用程序。它为 Spring Framework 添加了 REST 功能。