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
源码位置: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->请求体->结果解析。
2.1 构建实例
构建WebClinet实例的方法有三个:create()、create(String)、builder()
这三个静态工厂方法都是使用WebClient接口的默认实现类:DefaultWebClientBuilder,
不同的是参数不同:
- create():默认构建,不带参数;
- create(String):构建基础URL前缀,如公用的IP和PORT;
- builder():默认构建,不带参数,构建一个构造器;
构建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方法。
方法列表:
接口方法:org.springframework.web.reactive.function.client.WebClient
具体的实现在实现类:
org.springframework.web.reactive.function.client.DefaultWebClient
到这,细节可各位读者深究。
2.3 配置URI
实例化WebClient,确定请求方法后,接下来需要配置实际请求接口的URI。
方法列表:
接口类:org.springframework.web.reactive.function.client.WebClient.UriSpec
默认实现类:
org.springframework.web.reactive.function.client.DefaultWebClient.DefaultRequestBodyUriSpec
具体源码如下:
2.4 发送请求参数
接下来构建请求参数,如Form-Data、Body类型
WebClient中提供的接口:RequestBodySpec用于配置请求头和请求体。
方法列表:分为两类
- 请求头:contentType,contentLength
- 请求体:body、bodyValue
其中,body既可以填充请求体,又可以填充表单数据,或为文件数据。
RequestBodySpec接口:
org.springframework.web.reactive.function.client.WebClient.RequestBodySpec
默认实现:
org.springframework.web.reactive.function.client.DefaultWebClient.DefaultRequestBodyUriSpec
2.5 提取响应结果:retrieve()
WebClient请求接口后,通过retrieve()方法提取接口响应的结果。
ResponseSpec提供的方法如下:
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 | 服务端响应异常 |
接下来分析ResponseSpec接口,该接口是处理响应结果的规约,
如onStatus方法,根据响应状态码处理结果,当异常时,进行对应的处理,
成功时,数据流往下传递;
bodyToMono将结果转换为Mono对象流,传递给调用方。
结果处理是非常重要的功能,这里分类讲解:
2.5.1 onStatus
onStatus:提取当前响应的状态,做对应的处理,
HTTP响应状态码:1xx/2xx/3xx/4xx/5xx,
当响应状态异常,如出现4xx和5xx时,可直接做出合适的处理,
如抛出异常,返回自定义的响应信息。
onStatus中通过onRawStatus处理状态码,这个可以在DefaultWebClient中查看。
默认实现DefaultWebClient的onStatus实现源码如下,
由源码可知,通过onRawStatus处理。
2.5.2 bodyToMono
HTTP响应码正常时,通过bodyToMono将响应结果处理为自定义的目标类型,使用Mono包装,
不过,接口之间的响应约定,一般是接口提供方先定好,调用者兼容该约定,
如果是公司内部,则可以按照统一的约定来设计。
bodyToMono将结果映射到约定的类型后,以Mono形式传递。
2.5.3 bodyToFlux
和bodyToMono功能一样,不同的是响应结果使用Flux包装起来。
2.5.4 toEntity
将响应实体使用ResponseEntity进行映射,使用Mono包装。
由响应类型可知:Mono<ResponseEntity<T>>
。
2.5.5 toEntityList
与toEntity功能一样,不同的是将响应结果处理为List格式。
2.5.6 toEntityFlux
这个就不多解释了,toEntityMono一样。
到这里将响应结果处理方式简单过了一遍,
通过以上的知识,我们就可以使用WebClient请求接口,并合适地处理接口响应结果。
3 小结
(1)WebClient请求接口过程:创建实例->请求方法->请求URI->请求体->结果解析;
(2)接口传递参数使用:contentType,contentLength方法配置请求头;body、bodyValue方法配置请求体;
(3)接口响应结果提取使用:retrieve()方法;
(4)接口响应状态判断使用:onStatus()方法;
(5)接口响应结果处理方法有:bodyToMoon/bodyToFlux/toEntity/toEntityFlux;