优秀的编程知识分享平台

网站首页 > 技术文章 正文

Spring Boot 3 指南 三、Spring MVC(10)使用Spring MVC消费REST资源

nanyue 2024-12-25 14:42:51 技术文章 6 ℃

问题

你需要为你的应用程序连接到一个REST资源,并希望使用RestTemplate或RestClient来完成这个任务。

解决方案

Spring Boot提供了配置和构建器来帮助构建所需的类。这个食谱将会构建一个可以用来消费API的应用程序,如食谱3-2所示。

您可以使用RestTemplateBuilder来创建一个RestTemplate并在您的应用程序中使用它,或者使用暴露的RestClient.Builder来创建一个RestClient。最后一个选择是使用带有@HttpExchange注解的声明式客户端。

RestClient是一种比RestTemplate更流畅的方式来构建、执行和处理REST调用。它被构建为Webflux的WebClient的阻塞变体(参见第4章)。

它是如何工作的

尽管每种方法使用的类不同,我们仍然需要对Spring MVC的web类有依赖。为此,我们可以添加spring-boot-starter-web依赖。参见列表3-50。

如果你正在编写一个不需要servlet容器的独立客户端,你可能想要添加一个排除项,排除spring-boot-starter-tomcat。

我们将使用配方3-2作为我们的服务器API,并将编写一个应用程序,该程序在该API上查找一本书,调用另一个API(在https://openlibrary.org)以检索有关该书的额外信息,并返回一个丰富的响应。

EnrichedBook看起来像列表3-51。

这是在食谱3-2中创建的Book类的一个稍微扩展的版本(见列表3-6)。对于Open Library API,我们将使用一个HashMap来存放响应并检索我们需要的元素。

使用RestTemplate

要创建一个RestTemplate,我们可以使用RestTemplateBuilder,理想情况下作为@Bean方法的一个参数。这样我们就可以创建一个新的RestTemplate作为bean。RestTemplateBuilder负责配置我们需要的RestTemplate。参见列表3-52。

这将为我们的应用程序构建一个新的RestTemplate。

也可以通过辅助方法为RestTemplateBuilder指定额外的配置。

每个方法都将构建一个新的RestTemplateBuilder,因为RestTemplateBuilder本身是不可变的。

因此,设置的更改不会反映在使用RestTemplateBuilder的其他地方。

参见表3-14。

让我们编写一个控制器,它将从我们自己的服务器(参见食谱3-2)获取一本书,

并且还将调用开放图书馆API来获取书籍的出版日期。参见列表3-53。

控制器首先使用RestTemplate上的getForObject方法检索一本书(还有其他各种方法)。接下来,我们使用相同的方法从Open Library API检索额外的信息,然后使用这两个响应编写结果。

当你使用curl或HTTPie从命令行调用http://localhost:8090/books/9780618260300时,你将得到类似于图3-20的输出。


使用 RestClient

除了使用 RestTemplate,也可以使用更流畅的 RestClient。Spring Boot 自动暴露了 RestClient.Builder。参见代码清单 3-54。

RestClient.Builder 提供了一些方法来增强配置。

每个方法都会产生一个新的RestClient.Builder实例。参见表3-15和列表3-55。


控制器使用RestClient来调用URL。首先,我们确定我们想要的请求类型,以便在我们的案例中使用get()。接下来,我们使用uri()方法指定我们想要调用的带有参数的URL。这完成了我们的请求,现在我们可以通过receive()方法执行它。最后,我们使用body()方法映射响应体。

由于RestClient重用了RestTemplate使用的相同基础设施的一部分,我们可以重用我们之前相同的异常处理。当你使用curl或HTTPie从命令行调用http://localhost:8090/books/9780618260300时,你将得到类似于图3-20的输出。

使用声明式客户端

Spring Framework 6 引入了声明式 HTTP 客户端。通过这个功能,可以编写一个带有注解的接口。在运行时,会创建一个代理来处理请求/响应,包括映射和异常处理。

起点是一个带有 @HttpExchange 注解的接口(或者像 @GetExchange 或 @PostExchange 这样的派生注解),这些注解可以放在类上或方法上。它的功能与服务器 API 中的 @RequestMapping 非常相似。

使用 @HttpExchange,可以设置一些属性(见表 3-16)。

除了@HttpExchange注解之外,还有@DeleteExchange、@GetExchange、@PatchExchange、@PostExchange和@PutExchange。这些可以用来代替带有特定方法值的@HttpExchange。使用这些注解可以使其更加明确。

就像带有@RequestMapping的请求处理方法一样,声明式客户端支持多个参数、注解和返回类型。它重用了Web基础设施的通用部分。参见表3-17。

除了方法参数外,还支持几种方法返回类型。参见表 3-18。

根据这些信息,我们可以提供两个接口来访问我们需要调用的API。让我们从书籍的API开始。参见列表3-56。

BookServiceClient有一个方法,该方法使用了@GetExchange注解。

提供了一个值http://localhost:8080/books/{isbn},这是一个URI模板。

该方法接受一个参数isbn,该参数被@PathVariable注解。

当我们调用这个方法时,我们传入的值将会被放置在URI的{isbn}部分,然后执行请求。

当请求发送后,会收到一个响应,该响应会被转换成一个Book对象,

接下来我们也需要一个用于Open Library API的界面。参见列表3-57。

OpenLibraryClient 有一个带有 url 属性设置的 @HttpExchange 方法。这将为这个接口中的所有其他方法设置一个基础 URI。这允许我们只为所有其他方法指定相对 URL。现在只有一个带有 @GetExchange 的方法。这个方法还接受一个参数 isbn,在执行之前也会将其放置在 URI 模板中。响应再次被转换成一个 Map,就像之前一样。

现在接口已经准备好了,我们需要在我们的配置中公开它们,但我们不能从接口创建实例。这就是 HttpServiceProxyFactory 发挥作用的地方;它在运行时为这些接口创建一个代理。为此,我们需要向我们的应用程序添加一些配置。参见列表 3-58。

RestClient.Builder 用于构建一个用于 HttpServiceProxyFactory 的 RestClient。由于无法直接使用 RestClient,我们需要将其包装在 RestClientAdapter 中,后者将 RestClient 适配到 HttpExchangeAdapter 接口。

HttpExchangeAdapter 有三种实现:RestClientAdapter、RestTemplateAdapter 和 WebClientAdapter。后者在第 4 章中使用,并且是非阻塞的。然而,也可以使用 RestTemplate 来执行请求,而不是使用 RestClient。

HttpServiceProxyFactory 反过来用于为 BookServiceClient 和 OpenLibraryClient 创建代理。这只需在 HttpServiceProxyFactory 上调用带有给定接口的 createClient 方法即可轻松完成。参见列表 3-59。

请注意,我们现在可以直接在接口上调用方法,而无需担心构建适当的请求。所有这些都被隐藏在接口外观和代理内部。这使得编写可重用的API客户端以供应用程序使用变得更加容易。

最后,请注意,异常处理并未改变,因为声明式客户端仍然使用相同的基础设施,RestClient的异常处理无需更改。

当重新运行应用程序并请求书籍信息时,输出应该仍然与图3-20所示相同。

使用RestTemplate或RestClient-Based Code进行测试

为了使用RestTemplate或RestClient测试客户端代码,Spring Test框架提供了MockRestServiceServer。MockRestServiceServer可用于返回特定请求的响应(基于URL、头部、内容等)。

Spring Boot通过提供@RestClientTest注解,使得使用它变得更加容易。这将设置MockRestServiceServer,使其可以自动装配,并将测试类配置好。参见列表3-60。

测试使用@RestClientTest来设置服务器并为测试准备EnrichedBookController。MockRestServiceServer和EnrichedBookController都被注入,以便它们可用于测试。

在实际的测试方法中,我们首先通过我们想要的行为来设置MockRestServiceServer。这里我们只匹配URL并设置它们返回特定的JSON响应和HTTP 200 OK(更多可能性请参见表3-19)。测试运行后,我们在MockRestServiceServer上调用verify()来验证我们记录的请求是否也被发出,表明我们的客户端按预期工作。

响应是通过使用MockRestResponseCreators创建的,目前我们只使用了withSuccess,但也可以设置错误场景(表3-20)。

在调用设置方法后,返回了一个DefaultResponseCreator,可以用来进一步定义响应,通过添加头部、cookies,甚至是正文。

我们可以使用@RestClientTest,也可以使用@WebMvcTest,因为EnrichedBookController是一个控制器。自动设置MockRestServiceServer需要一个额外的注解@AutoConfigureMockRestServiceServer;否则,它将不会被配置。

最近发表
标签列表