休息前

通过参考资料开始使用Spring 5和Spring Boot 2学习春天课程:

>>查看课程

1.概述

很多框架和项目正在介绍响应式编程和异步请求处理。因此,春天5介绍了活性WebClient.实施作为其中的一部分webflux框架。

在本教程中,我们将看到如何反应地消耗休息API端点WebClient.

2. REST API端点

首先,让我们定义一个样本休息API.下面是获取端点的方法:

  • /产品- 获取所有产品
  • /产品/ {id}-通过ID获取产品
  • /产品/ {id} /属性/ {attributeId}—通过id获取产品属性
  • /产品/?名称= {name}&traveringdate = {transportdate}&color = {color}找到产品
  • / /产品?标签[]={标签1}标记[]={标签2}- 通过标记获取产品
  • / /产品?类别= {category1}类别= {category2}-按类别获取产品

所以,我们刚刚定义了一些不同的URI。在短短的一刻,我们将弄清楚如何构建和发送每种类型的URIWebClient.

请注意,按标签和按类别获取产品的uri包含数组作为查询参数。然而,语法是不同的。自对于在uri中如何表示数组没有严格的定义。主要是,这取决于服务器端实现。因此,我们将介绍这两种情况。

3.WebClient.设置

首先,我们需要创建一个实例WebClient.。对于本文,我们将使用嘲笑的对象据我们所需要只是为了验证是否要求有效的URI。

让我们定义客户端和相关模拟对象:

this.exchangeFunction = Mock(ExpectFunction.class);clientresponse mockresponse = mock(clientresponse.class);什么时候(这个.exchangefunction.exchange(this.argumentcaptor.capture()))。然后return(mono.just(mockresponse));这个.webclient = webclient .builder().baseull(“https://example.com/api”).exchangefunction(ExpectionFunction).build();

此外,我们还传递了一个基URL,该URL将被添加到客户机发出的所有请求中。

最后,验证特定的URI已经传递到底层Expection.实例,让我们使用下面的helper方法:

私有void验证cledull(String ContctoryURL){ClientRequest请求= this.argumentCaptor.getValue();assert.assertequals(string.format(“%s%s”,base_url,contgureurl),请求。url()。toString());mockito.verify(this.exchangefunction).exchange(请求);verifynomore interactions(this.exchangefunction);}

WebClientBuilder.类的Uri()方法提供uribuilder.实例作为参数。通常,通常以下列方式进行API调用:

this.webclient.get()。uri(uribuilder  - > ulibuilder // ...构建URI .Build()).Retrieve();

我们会使用uribuilder.本指南将详细介绍如何构造uri。值得注意的是,我们可以使用任何其他方式构建URI,然后将生成的URI作为字符串传递。

4.URI路径组件

路径组件由一系列用斜杠(/)分隔的路径段组成。。首先,当URI没有任何可变段时,让我们从一个简单的情况开始/产品:

this.webClient.get () .uri(“/产品”).retrieve ();verifyCalledUrl(“/产品”);

在这种情况下,我们可以传递a字符串作为一个论点。

接下来,让我们带/产品/ {id}端点,并构建相应的URI:

this.webclient.get()。uri(uribuilder  - > ulibuilder .path(“/ products / {id}”).build(2)).retrieve();验证程序(“/ products / 2”);

从上面的代码中,我们可以看到实际的段值传递给build ()方法。
现在,我们可以用类似的方式为/产品/ {id} /属性/ {attributeId}端点:

urbuilder .path("/products/{id}/attributes/{attributeId}") .build(2, 13)) .retrieve();verifyCalledUrl(“/产品/ 2 /属性/ 13”);

URI可以根据需要具有多种路径段。当然,如果最终的URI长度不超过限制。最后,请记住保持转移到的实际段值的正确顺序build ()方法。

5. URI查询参数

通常,查询参数是一个简单的键值对title 金宝搏188体育= Baeldung。让我们看看如何构建这样的uri。

5.1。单值参数

让我们从单值参数开始并拍摄/产品/?名称= {name}&traveringdate = {transportdate}&color = {color}端点。要设置查询参数,我们调用queryParam ()方法的方法uribuilder.接口:

这个。webclient .get() .uri(urilbuilder - > urilbuilder .path("/products/") .queryParam("name", "AndroidPhone") .queryParam("color", "black") .queryParam("deliveryDate", "13/04/2019") .build()) .retrieve();verifyCalledUrl(“/产品/ ?名字= AndroidPhone&color = black&deliveryDate = 13/04/2019”);

在这里,我们已添加三个查询参数并立即分配实际值。此外,还可以留下占位符而不是确切的值:

this.webclient.get()。uri(uribuilder  - > ulibuilder .path(“/ products /”).queryparam(“名称”,“{title}”).queryparam(“color”,“{authorid}”)。queryparam(“transportdate”,“{date}”).build(“androidphone”,“黑色”,“13/04/2019”)).Retrieve();VerifyCalledURL(“/产品/?名称= AndroidPhone&Color = Black&DeliveryDate = 13%2F04%2F2019”);

特别是,当在链中进一步传递生成器对象时,这可能会有帮助。请注意一个重要的上面的两个代码片段之间的差异

注意所期望的uri,我们可以看到它们是以不同的方式编码。特别是斜杠字符(/)在上一个示例中被转义。一般来说,RFC3986在查询中不需要对斜杠进行编码。

然而,一些服务器端应用程序可能需要这样的转换。因此,我们将在本指南的后面部分看到如何改变这种行为。

5.2。数组参数

同样,我们可能需要传递一个值数组。不过,在查询字符串中传递数组没有严格的规则。因此,查询字符串中的数组表示形式因项目而异,通常取决于底层框架。我们将涵盖最广泛使用的格式。

让我们从/ /产品?标签[]={标签1}标记[]={标签2}端点:

this.webclient.get().uri(uribuilder  - > ulibuilder .path(“/ products /”).queryparam(“tag []”,“snapdragon”,“nfc”).build()).retrieve();VerifyCalledURL(“/产品/?标签%5B%5d = Snapdragon&Tag%5b%5d = nfc”);

正如我们所看到的,最终的URI包含多个标记参数,后跟经过编码的方括号。的queryParam ()方法接受变量参数作为值,因此不需要多次调用该方法。

或者,我们可以省略方括号并刚用相同的键传递多个查询参数,但不同的价值观 -/ /产品?类别= {category1}类别= {category2}:

this.webclient.get().uri(uribuilder  - > ulibuilder .path(“/ products /”).queryparam(“类别”,“手机”,“平板电脑”).build()).Retrieve();VerifyCalledURL(“/产品/?类别=手机和类别=平板电脑);

最后,还有一种更常用的方法来编码数组,那就是传递以逗号分隔的值。让我们把前面的例子转换成逗号分隔的值:

urilbuilder .path("/products/") . queryparam ("category",字符串。加入(“,”、“手机”、“平板电脑”)).build ()) .retrieve ();verifyCalledUrl(“类别/产品/ ? =手机、平板电脑”);

因此,我们只是使用加入()方法的方法字符串类创建以逗号分隔的字符串。当然,我们可以使用应用程序所期望的任何其他分隔符。

6.编码模式

还记得我们前面提到的URL编码吗?

如果默认行为不适合我们的要求,我们可以更改它。我们需要提供一个UriBuilderFactory在构建WebClient.实例。在本例中,我们将使用defaulturibuilderfactory.班级。设置编码呼叫setEncodingMode ()方法。以下模式可用:

  • template_and_values.:对URI模板进行预编码,并在展开时对URI变量进行严格编码
  • VALUES_ONLY:不要对URI模板进行编码,而是在将URI变量展开到模板后对其进行严格编码
  • URI_COMPONENTS:过期URI变量后,对URI组件值进行编码
  • 没有任何:未应用编码

默认值是template_and_values.。让我们将模式设置为URI_COMPONENTS:

DefaultUriBuilderFactory factory = new DefaultUriBuilderFactory(BASE_URL);factory.setEncodingMode (DefaultUriBuilderFactory.EncodingMode.URI_COMPONENT);这一点。webClient = webClient .builder() .uriBuilderFactory(factory) .baseUrl(BASE_URL) .exchangeFunction(exchangeFunction) .build();

因此,下面的断言将成功:

这个。webclient .get() .uri(urilbuilder - > urilbuilder .path("/products/") .queryParam("name", "AndroidPhone") .queryParam("color", "black") .queryParam("deliveryDate", "13/04/2019") .build()) .retrieve();verifyCalledUrl(“/产品/ ?名字= AndroidPhone&color = black&deliveryDate = 13/04/2019”);

当然,我们也可以提供完全定制的UriBuilderFactory实现手动处理URI创建。

7.结论

在本教程中,我们已经看到了如何使用不同类型的URI使用WebClient.DefaultUribuilder。

沿途,我们涵盖了各种类型和格式的查询参数。我们用更改URL Builder的默认编码模式来包裹。

与往常一样,本文中的所有代码片段都是可用的在GitHub存储库

休息下

通过。开始使用Spring 5和Spring Boot 2学习春天课程 :

>>查看课程
本文评论关闭!