1.概述

在本教程中,我们将研究WebClient,这是Spring 5中引入的一个响应式web客户端。

我们也要看看WebTestClient,一个WebClient设计用于测试。

进一步阅读:

春天WebClient过滤器

在Sprin金宝搏官网188beg WebFlux中了解WebClient过滤器

使用参数的Spring WebClient请求

学习如何用WebClient从Spring Webflux响应式消费REST API端点。

2.什么是WebClient吗?

简单地说,WebClient是表示执行Web请求的主要入口点的接口。

它是作为Spring Web Reactive模块的一部分创建的,并将取代经典的创建RestTemplate在这些场景中。此外,新客户端是一个响应式的、非阻塞的解决方案,工作在HTTP/1.1协议上。

重要的是要注意,即使它实际上是非阻塞客户端,它属于spring-webflux库,该解决方案提供了对同步和异步操作的支持,使其也适用于运行在Servlet堆栈上的应用程序。

这可以通过阻止操作来获得结果来实现。当然,如果我们正在使用反应堆,则不建议这种做法。

最后,该接口只有一个实现,即defaultWebClient.班级,我们将与之合作。

3.依赖关系

由于我们正在使用Spring启动应用程序,我们需要的只是Spring-Boot-Starter-WebFlux依赖性获取Spring Framework的无功网络支持。

3.1。与Maven构建

让我们将以下依赖添加到pom.xml文件:

<依赖> < groupId > org.springframework。启动< / groupId > < artifactId > spring-boot-starter-webflux < / artifactId > < / >的依赖

3.2。建筑与它

使用Gradle,我们需要将以下条目添加到build.gradle.文件:

编译org.springframework。引导:spring-boot-starter-webflux}

4.与之合作WebClient

要与客户合理地工作,我们需要知道如何:

  • 创建一个实例
  • 发出请求
  • 处理响应

4.1。创建一个WebClient实例

有三种选择可供选择。第一个是创造一个WebClient具有默认设置的对象:

WebClient Client = webclient.create();

第二种选择是发起WebClient使用给定的基URI的实例:

WebClient client = WebClient.create(“http://localhost:8080”);

第三个选项(以及最先进的一个)正在使用该选项来构建客户DefaultWebClientBuilder课程,允许完整自定义:

webclient client = webclient.builder().baseurl(“http:// localhost:8080”).defaultcookie(“cookiekey”,“cookievalue”).defaultheader(httpheaders.content_type,mediatype.application_json_value).defaulturivariables(collections.singletonmap(“URL”,“http:// localhost:8080”)).build();

4.2。创建一个WebClient实例与超时

通常,对于我们的需求来定制此行为,30秒的默认HTTP超时为30秒太慢,我们可以创建一个HttpClient实例化并配置我们的WebClient使用它。

我们可以:

  • 方法设置连接超时ChannelopTion.connect_timeout_millis.选项
  • 属性设置读和写超时readtimeouthandler.和一个WriteTimeoutHandler分别
  • 属性配置响应超时响应次数指示

正如我们所说,所有这些都必须在HttpClient我们将配置实例:

httpclient httpclient = httpclient.create().option(channeloption.connect_timeout_millis,5000).responseTimeout(duration.ofmillis(5000)).doonconnected(conn  - > conn.addhandlerlast(new readtimeouthandler(5000,timeUnit.milliseconds)).addhandlerlast(新的writeTemethandler(5000,TimeUnit)))));webclient client = webclient.builder().clientConnector(新restorclienthttpConnector(httpclient)).build();

注意我们可以打电话超时对于我们的客户端请求,这是一个信号超时,而不是一个HTTP连接,一个读/写,或响应超时;这是Mono/Flux出版商的暂停时间。

4.3。准备请求-定义方法

首先,我们需要通过调用来指定请求的HTTP方法方法(HttpMethod方法):

URISPEC  Urispec = client.method(httpmethod.post);

或调用它的快捷方法,例如得到,帖子,删除:

URISPEC  Urispec = client.post();

注意:虽然看起来我们重用了请求规范变量(webclient.urispec.,webclient.requestbodyspec.,WebClient。RequestHeadersSpec,WebClient。ResponseSpec),这只是为了简单地给出不同的方法。这些指令不应该用于不同的请求,它们检索引用,因此后一种操作将修改我们在前面步骤中所做的定义。

4.4。准备一个请求-定义URL

下一步是提供一个URL。再说一次,我们有不同的方法。

我们可以把它传给Uri.API作为A.细绳:

RequestBodySpec bodySpec = uriSpec.uri(“/资源”);

用一个uribuilder函数:

bodySpec = uriSpec。Uri.( uriBuilder -> uriBuilder.pathSegment("/resource").build());

或作为一个java.net.URL实例:

RequestBodySpec bodySpec = urispecc .uri(URI.create("/resource"));

请记住,如果我们为此定义了默认的基本URLWebClient,最后一个方法将覆盖这个值。

4.5。准备请求-定义请求主体

然后,如果需要,我们可以设置请求正文、内容类型、长度、cookie或头。

例如,如果我们想设置请求正文,则有一些可用方式。可能是最常见和最简单的选择是使用的体积方法:

RequestHeadersSpec < ?> headersSpec = bodySpec.bodyValue(“数据”);

或者通过展示出版商(以及要发布的元素的类型)身体方法:

RequestHeadersSpec < ?> headersSpec = bodySpec。身体(Mono。(新Foo(“名字”)),Foo.class);

或者,我们可以利用BodyInserters实用程序类。例如,让我们看看如何使用简单对象填充请求体,就像使用体积方法:

RequestHeadersSpec < ?> headersSpec = bodySpec。身体( BodyInserters.fromValue("data"));

同样,我们可以使用BodyInserters # fromPublisher方法如果我们使用反应堆实例:

RequestHeadersSpec headersSpec = bodySpec。身体( BodyInserters.fromPublisher(Mono.just("data")), String.class);

此类还提供其他直观的功能来涵盖更高级的方案。例如,如果我们必须发送多部分请求:

LinkedMultiValueMap map = new LinkedMultiValueMap();地图。一个dd("key1", "value1"); map.add("key2", "value2"); RequestHeadersSpec headersSpec = bodySpec.body( BodyInserters.fromMultipartData(map));

所有这些方法都会创建一个Burdenserter.实例,我们可以作为的身体的请求。

Burdenserter.一个接口负责填充ReactiveHttpOutputMessage体,其中包含给定的输出消息和插入期间使用的上下文。

一个出版商是负责提供潜在未绑定数量的测序元件的反应性组分。它也是一个接口,最流行的实现是单核细胞增多症助焊剂。

4.6。准备一个请求-定义头

在我们设置了主体之后,我们可以设置标题、cookie和可接受的媒体类型。在实例化客户端时,值将被添加到已经设置的值中。

此外,对于最常用的头文件,如“if-none-match”,“if-comified - 以来”,“接受”,“接受字符集”。

以下是如何使用这些值的示例:

ResponseSpec ResponseSpec = headersSpec。头(HttpHeaders。CONTENT_TYPE MediaType.APPLICATION_JSON_VALUE) .accept (MediaType。一个PPLICATION_JSON, MediaType.APPLICATION_XML) .acceptCharset(StandardCharsets.UTF_8) .ifNoneMatch("*") .ifModifiedSince(ZonedDateTime.now()) .retrieve();

4.7。得到一个回应

最后一个阶段是发送请求和接收响应。我们可以通过使用Exchangetomono / Exchangetoflux.或者是检索方法。

exchangeToMonoexchangetoflux.方法允许访问ClientResponse以及其状态和标题:

Mono response = headersSpec。exchangeToMono(response -> { if (response.statusCode() .equals(HttpStatus.OK)) { return response.bodyToMono(String.class); } else if (response.statusCode() .is4xxClientError()) { return Mono.just("Error response"); } else { return response.createException() .flatMap(Mono::error); } });

检索方法是直接获取主体的最短路径:

Mono response = headersSpec.retrieve() .bodyToMono(String.class);

重要的是要注意责任。bodyToMono方法,它会扔一个WebClientException状态码为4 xx(客户端错误)5 xx(服务器错误)。

5.与之合作WebTestClient

WebTestClient是测试WebFlux服务器端点的主要入口点。它有一个非常相似的APIWebClient,并将大部分工作委托给内部WebClient实例主要用于提供测试上下文。的defaultwebtestclient.类是单个接口实现。

测试客户端可以绑定到真实服务器或使用特定的控制器或功能。

5.1。绑定到服务器

要完成对运行中的服务器的实际请求的端到端集成测试,我们可以使用bindToServer方法:

WebTestClient testClient = WebTestClient .bindToServer() .baseUrl(“http://localhost:8080”).build();

5.2。绑定到路由器

我们可以测试一个特定的RouterFunction.通过将它传递给BindtorouterFunction.方法:

RouterFunction function = RouterFunctions。route(requestpredicate . get ("/resource"), request -> ServerResponse.ok().build());WebTestClient .bindToRouterFunction(function) .build().get().uri("/resource") .exchange() .expectStatus().isOk() .expectBody().isEmpty();

5.3。绑定到Web处理程序

可以实现相同的行为bindToWebHandler方法,需要一个WebHandler实例:

WebHandler = exchange -> Mono.empty();WebTestClient.bindToWebHandler(处理器).build ();

5.4。绑定到应用程序上下文

更有趣的情况发生在我们使用the的时候BindToApplicationContext.方法。它需要一个ApplicationContext并分析控制器bean和@bablewebflux配置。

对象的实例ApplicationContext,一个简单的代码片段可能如下所示:

@Autowired私有ApplicationContext上下文;WebTestClient testClient = WebTestClient. bindtoapplicationcontext (context) .build();

5.5。绑定到控制器

更短的方法是提供一系列控制器,我们想要测试bindtocontroller.方法。假设我们有控制器类,并将其注入到所需的类中,可以编写:

@Autowired专用控制器控制器;WebTestClient testClient = WebTestClient. bindtocontroller (controller).build();

5.6。发出请求

建立A之后WebTestClient对象,链中的所有后续操作都将类似于WebClient直到交换方法(获得响应的一种方法),它提供了WebTestClient。ResponseSpec类等有用的方法expectStatus,expectBody,expectHeader:

WebTestClient . bindtoserver (). baseurl(“http://localhost:8080”). build() .post() .uri(“/resource”). exchange() . expectstatus (). iscreated (). expectheader()。valueEquals(“内容类型”、“application / json”).expectBody () .jsonPath .isEqualTo(“场”)(“价值”);

六,结论

在本文中,我们探索了WebClient,一种新的增强型弹簧机制,用于在客户端对要求进行要求。

通过配置客户机、准备请求和处理响应,我们还了解了它提供的好处。

本文中提到的所有代码片段都可以在我们的GitHub库

通用底部

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

>>看看这个课程
评论在本文上关闭!