响应式编程理论篇:源码浅析WebClient

1 缘起

WebFlux系统中,如何请求第三方或其他内部兄弟系统提供的接口?
当然,可以直接使用OKhttp/Apache HttpClient/SpringMVC RestTemplate,
在WebFlux中同样提供了请求接口的工具:WebClient,
本篇文章主要讲解WebClient的功能,理论篇。
实践篇中讲解如何实战。

2 Webclient

Spring WebClient官方地址:
https://docs.spring.io/spring-framework/reference/web/webflux-webclient.html
响应式编程理论篇:源码浅析WebClient_第1张图片

源码位置:org.springframework.web.reactive.function.client.WebClient
先看一下WebClient的注释:
非阻塞响应式发送HTTP请求。
通过底层HTTP客户端库(如Reactor Netty)暴露响应式API。
核心点:

  • 如何构建实例:通过create()、create(String)、builder()方法
  • 如何获取响应结果:通过retrieve()、exchangeToMono()、exchangeToFlux()方法
  • 如何在请求中添加请求体:通过bodyValue(Object)、body(Publisher, Class)方法

接下来以应用的角度讲解WebClient,即:
创建实例->请求方法->请求URI->请求体->结果解析。

响应式编程理论篇:源码浅析WebClient_第2张图片

2.1 构建实例

构建WebClinet实例的方法有三个:create()、create(String)、builder()
这三个静态工厂方法都是使用WebClient接口的默认实现类:DefaultWebClientBuilder,
不同的是参数不同:

  • create():默认构建,不带参数;
  • create(String):构建基础URL前缀,如公用的IP和PORT;
  • builder():默认构建,不带参数,构建一个构造器;

响应式编程理论篇:源码浅析WebClient_第3张图片
构建WebClient实例后,即可发起HTTP/HTTPS请求,
WebClient接口,通过工厂方法实例化,结合SpringBoot的自动装配机制,
这里使用@PostConstruct启动SpringBoot服务时实例化WebClient,
初始化调用接口的IP和PORT,如:http://192.168.0.123:8888
为后续使用准备。

  • 样例
    private WebClient pyRpcWebClient;

    @PostConstruct
    public void init() {
        pyRpcWebClient = WebClient.builder().baseUrl(rpcPyUrl).build();
    }

2.2 请求方法

接下来,看下请求方法,熟悉的味道:
GET、HEAD、POST、PUT、PATCH、DELETE和OPTIONS方法。
方法列表:
响应式编程理论篇:源码浅析WebClient_第4张图片
接口方法:org.springframework.web.reactive.function.client.WebClient
响应式编程理论篇:源码浅析WebClient_第5张图片
具体的实现在实现类:
org.springframework.web.reactive.function.client.DefaultWebClient
到这,细节可各位读者深究。
响应式编程理论篇:源码浅析WebClient_第6张图片

2.3 配置URI

实例化WebClient,确定请求方法后,接下来需要配置实际请求接口的URI。
方法列表:
响应式编程理论篇:源码浅析WebClient_第7张图片
接口类:org.springframework.web.reactive.function.client.WebClient.UriSpec
响应式编程理论篇:源码浅析WebClient_第8张图片

默认实现类:
org.springframework.web.reactive.function.client.DefaultWebClient.DefaultRequestBodyUriSpec
具体源码如下:
响应式编程理论篇:源码浅析WebClient_第9张图片

2.4 发送请求参数

接下来构建请求参数,如Form-Data、Body类型
WebClient中提供的接口:RequestBodySpec用于配置请求头和请求体。
方法列表:分为两类

  • 请求头:contentType,contentLength
  • 请求体:body、bodyValue

其中,body既可以填充请求体,又可以填充表单数据,或为文件数据。
响应式编程理论篇:源码浅析WebClient_第10张图片
RequestBodySpec接口:
org.springframework.web.reactive.function.client.WebClient.RequestBodySpec
响应式编程理论篇:源码浅析WebClient_第11张图片

默认实现:
org.springframework.web.reactive.function.client.DefaultWebClient.DefaultRequestBodyUriSpec
响应式编程理论篇:源码浅析WebClient_第12张图片

2.5 提取响应结果:retrieve()

WebClient请求接口后,通过retrieve()方法提取接口响应的结果。
ResponseSpec提供的方法如下:
响应式编程理论篇:源码浅析WebClient_第13张图片
retrieve类型为:ResponseSpec,
该接口提供了众多结果处理的方式,如将结果转化为Mono、Flux、Entity类型,
并且可以根据onStatus()方法,获取对应响应状态码,进行处理。
Http状态码:
https://developer.mozilla.org/en-US/docs/Web/HTTP/Status

序号 状态码 描述
1 1xx 响应信息
2 2xx 成功响应
3 3xx 重定向
4 4xx 客户端响应异常
5 5xx 服务端响应异常

响应式编程理论篇:源码浅析WebClient_第14张图片
接下来分析ResponseSpec接口,该接口是处理响应结果的规约,
如onStatus方法,根据响应状态码处理结果,当异常时,进行对应的处理,
成功时,数据流往下传递;
bodyToMono将结果转换为Mono对象流,传递给调用方。
结果处理是非常重要的功能,这里分类讲解:

2.5.1 onStatus

onStatus:提取当前响应的状态,做对应的处理,
HTTP响应状态码:1xx/2xx/3xx/4xx/5xx,
当响应状态异常,如出现4xx和5xx时,可直接做出合适的处理,
如抛出异常,返回自定义的响应信息。
响应式编程理论篇:源码浅析WebClient_第15张图片
onStatus中通过onRawStatus处理状态码,这个可以在DefaultWebClient中查看。
响应式编程理论篇:源码浅析WebClient_第16张图片

默认实现DefaultWebClient的onStatus实现源码如下,
由源码可知,通过onRawStatus处理。
响应式编程理论篇:源码浅析WebClient_第17张图片

2.5.2 bodyToMono

HTTP响应码正常时,通过bodyToMono将响应结果处理为自定义的目标类型,使用Mono包装,
不过,接口之间的响应约定,一般是接口提供方先定好,调用者兼容该约定,
如果是公司内部,则可以按照统一的约定来设计。
bodyToMono将结果映射到约定的类型后,以Mono形式传递。
响应式编程理论篇:源码浅析WebClient_第18张图片

2.5.3 bodyToFlux

和bodyToMono功能一样,不同的是响应结果使用Flux包装起来。
响应式编程理论篇:源码浅析WebClient_第19张图片

2.5.4 toEntity

将响应实体使用ResponseEntity进行映射,使用Mono包装。
由响应类型可知:Mono>
响应式编程理论篇:源码浅析WebClient_第20张图片

2.5.5 toEntityList

与toEntity功能一样,不同的是将响应结果处理为List格式。
响应式编程理论篇:源码浅析WebClient_第21张图片

2.5.6 toEntityFlux

这个就不多解释了,toEntityMono一样。

响应式编程理论篇:源码浅析WebClient_第22张图片
到这里将响应结果处理方式简单过了一遍,
通过以上的知识,我们就可以使用WebClient请求接口,并合适地处理接口响应结果。

3 小结

(1)WebClient请求接口过程:创建实例->请求方法->请求URI->请求体->结果解析;
(2)接口传递参数使用:contentType,contentLength方法配置请求头;body、bodyValue方法配置请求体;
(3)接口响应结果提取使用:retrieve()方法;
(4)接口响应状态判断使用:onStatus()方法;
(5)接口响应结果处理方法有:bodyToMoon/bodyToFlux/toEntity/toEntityFlux;

你可能感兴趣的:(#,Spring,java,开发语言)