`
234390216
  • 浏览: 10232986 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
博客专栏
A5ee55b9-a463-3d09-9c78-0c0cf33198cd
Oracle基础
浏览量:462624
Ad26f909-6440-35a9-b4e9-9aea825bd38e
springMVC介绍
浏览量:1775518
Ce363057-ae4d-3ee1-bb46-e7b51a722a4b
Mybatis简介
浏览量:1398358
Bdeb91ad-cf8a-3fe9-942a-3710073b4000
Spring整合JMS
浏览量:395022
5cbbde67-7cd5-313c-95c2-4185389601e7
Ehcache简介
浏览量:679983
Cc1c0708-ccc2-3d20-ba47-d40e04440682
Cas简介
浏览量:530892
51592fc3-854c-34f4-9eff-cb82d993ab3a
Spring Securi...
浏览量:1183946
23e1c30e-ef8c-3702-aa3c-e83277ffca91
Spring基础知识
浏览量:467928
4af1c81c-eb9d-365f-b759-07685a32156e
Spring Aop介绍
浏览量:151396
2f926891-9e7a-3ce2-a074-3acb2aaf2584
JAXB简介
浏览量:68153
社区版块
存档分类
最新评论

Spring(31)——WebClient介绍

阅读更多

 

WebClient是从Spring WebFlux 5.0版本开始提供的一个非阻塞的基于响应式编程的进行Http请求的客户端工具。它的响应式编程的基于Reactor的。WebClient中提供了标准Http请求方式对应的get、post、put、delete等方法,可以用来发起相应的请求。下面的代码是一个简单的WebClient请求示例。可以通过WebClient.create()创建一个WebClient的实例,之后可以通过get()post()等选择调用方式,uri()指定需要请求的路径,retrieve()用来发起请求并获得响应,bodyToMono(String.class)用来指定请求结果需要处理为String,并包装为Reactor的Mono对象。

WebClient webClient = WebClient.create();
Mono<String> mono = webClient.get().uri("https://www.baidu.com").retrieve().bodyToMono(String.class);
mono.subscribe(System.out::println);

响应结果解析为对象

当响应的结果是JSON时,也可以直接指定为一个Object,WebClient将接收到响应后把JSON字符串转换为对应的对象。比如下面这样。

WebClient webClient = WebClient.create();
Mono<User> mono = webClient.get().uri("http://localhost:8081/user/1").retrieve().bodyToMono(User.class);
User user = mono.block();

如果响应的结果是一个集合,则不能继续使用bodyToMono(),应该改用bodyToFlux(),然后依次处理每一个元素,比如下面这样。

String baseUrl = "http://localhost:8081";
WebClient webClient = WebClient.create(baseUrl);
Flux<User> userFlux = webClient.get().uri("users").retrieve().bodyToFlux(User.class);
userFlux.subscribe(System.out::println);

如果需要通过Flux取到所有的元素构造为一个List,则可以通过如下的方式获取。

List<User> users = userFlux.collectList().block();

URL中使用路径变量

URL中也可以使用路径变量,路径变量的值可以通过uri方法的第2个参数指定。下面的代码中就定义了URL中拥有一个路径变量id,然后实际访问时该变量将取值1。

webClient.get().uri("http://localhost:8081/user/{id}", 1);

URL中也可以使用多个路径变量,多个路径变量的赋值将依次使用uri方法的第2个、第3个、第N个参数。下面的代码中就定义了URL中拥有路径变量p1和p2,实际访问的时候将被替换为var1和var2。所以实际访问的URL是http://localhost:8081/user/var1/var2

webClient.get().uri("http://localhost:8081/user/{p1}/{p2}", "var1", "var2");

使用的路径变量也可以通过Map进行赋值。面的代码中就定义了URL中拥有路径变量p1和p2,实际访问的时候会从uriVariables中获取值进行替换。所以实际访问的URL是http://localhost:8081/user/var1/1

Map<String, Object> uriVariables = new HashMap<>();
uriVariables.put("p1", "var1");
uriVariables.put("p2", 1);
webClient.get().uri("http://localhost:8081/user/{p1}/{p2}", uriVariables);

指定baseUrl

在应用中使用WebClient时也许你要访问的URL都来自同一个应用,只是对应不同的URL地址,这个时候可以把公用的部分抽出来定义为baseUrl,然后在进行WebClient请求的时候只指定相对于baseUrl的URL部分即可。这样的好处是你的baseUrl需要变更的时候可以只要修改一处即可。下面的代码在创建WebClient时定义了baseUrl为http://localhost:8081,在发起Get请求时指定了URL为/user/1,而实际上访问的URL是http://localhost:8081/user/1

String baseUrl = "http://localhost:8081";
WebClient webClient = WebClient.create(baseUrl);
Mono<User> mono = webClient.get().uri("user/{id}", 1).retrieve().bodyToMono(User.class);

Form提交

当传递的请求体对象是一个MultiValueMap对象时,WebClient默认发起的是Form提交。下面的代码中就通过Form提交模拟了用户进行登录操作,给Form表单传递了参数username,值为u123,传递了参数password,值为p123。

String baseUrl = "http://localhost:8081";
WebClient webClient = WebClient.create(baseUrl);

MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
map.add("username", "u123");
map.add("password", "p123");

Mono<String> mono = webClient.post().uri("/login").syncBody(map).retrieve().bodyToMono(String.class);

请求JSON

假设现在拥有一个新增User的接口,按照接口定义客户端应该传递一个JSON对象,格式如下:

{
    "name":"张三",
    "username":"zhangsan"
}

客户端可以建立一个满足需要的JSON格式的对象,然后直接把该对象作为请求体,WebClient会帮我们自动把它转换为JSON对象。

String baseUrl = "http://localhost:8081";
WebClient webClient = WebClient.create(baseUrl);

User user = new User();
user.setName("张三");
user.setUsername("zhangsan");

Mono<Void> mono = webClient.post().uri("/user/add").syncBody(user).retrieve().bodyToMono(Void.class);
mono.block();

如果没有建立对应的对象,直接包装为一个Map对象也是可以的,比如下面这样。

String baseUrl = "http://localhost:8081";
WebClient webClient = WebClient.create(baseUrl);

Map<String, Object> user = new HashMap<>();
user.put("name", "张三");
user.put("username", "zhangsan");

Mono<Void> mono = webClient.post().uri("/user/add").syncBody(user).retrieve().bodyToMono(Void.class);
mono.block();

直接传递一个JSON字符串也是可以的,但是此时需要指定contentType为application/json,也可以加上charset。默认情况下WebClient将根据传递的对象在进行解析处理后自动选择ContentType。直接传递字符串时默认使用的ContentType会是text/plain。其它情况下也可以主动指定ContentType。

String baseUrl = "http://localhost:8081";
WebClient webClient = WebClient.create(baseUrl);

String userJson = 
        "{" + 
        "    \"name\":\"张三\",\r\n" + 
        "    \"username\":\"zhangsan\"\r\n" + 
        "}";

Mono<Void> mono = webClient.post().uri("/user/add").contentType(MediaType.APPLICATION_JSON_UTF8).syncBody(userJson).retrieve().bodyToMono(Void.class);
mono.block();

exchange

前面介绍的示例都是直接获取到了响应的内容,可能你会想获取到响应的头信息、Cookie等。那就可以在通过WebClient请求时把调用retrieve()改为调用exchange(),这样可以访问到代表响应结果的org.springframework.web.reactive.function.client.ClientResponse对象,通过它可以获取响应的状态码、Cookie等。下面的代码先是模拟用户进行了一次表单的登录操作,通过ClientResponse获取到了登录成功后的写入Cookie的sessionId,然后继续请求了用户列表。在请求获取用户列表时传递了存储了sessionId的Cookie。

String baseUrl = "http://localhost:8081";
WebClient webClient = WebClient.create(baseUrl);

MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
map.add("username", "u123");
map.add("password", "p123");

Mono<ClientResponse> mono = webClient.post().uri("login").syncBody(map).exchange();
ClientResponse response = mono.block();
if (response.statusCode() == HttpStatus.OK) {
    Mono<Result> resultMono = response.bodyToMono(Result.class);
    resultMono.subscribe(result -> {
        if (result.isSuccess()) {
            ResponseCookie sidCookie = response.cookies().getFirst("sid");
            Flux<User> userFlux = webClient.get().uri("users").cookie(sidCookie.getName(), sidCookie.getValue()).retrieve().bodyToFlux(User.class);
            userFlux.subscribe(System.out::println);
        }
    });
}

WebClient.Builder

除了可以通过WebClient.create()创建WebClient对象外,还可以通过WebClient.builder()创建一个WebClient.Builder对象,再对Builder对象进行一些配置后调用其build()创建WebClient对象。下面的代码展示了其用法,配置了baseUrl和默认的cookie信息。

String baseUrl = "http://localhost:8081";
WebClient webClient = WebClient.builder().baseUrl(baseUrl).defaultCookie("cookieName", "cookieValue").build();

Builder还可以通过clientConnector()定义需要使用的ClientHttpConnector,默认将使用org.springframework.http.client.reactive.ReactorClientHttpConnector,其底层是基于netty的,如果你使用的是Maven,需要确保你的pom.xml中定义了如下依赖。

<dependency>
    <groupId>io.projectreactor.ipc</groupId>
    <artifactId>reactor-netty</artifactId>
    <version>0.7.8.RELEASE</version>
</dependency>

如果对默认的发送请求和处理响应结果的编解码不满意,还可以通过exchangeStrategies()定义使用的ExchangeStrategies。ExchangeStrategies中定义了用来编解码的对象,其也有对应的build()方法方便我们来创建ExchangeStrategies对象。

WebClient也提供了Filter,对应于org.springframework.web.reactive.function.client.ExchangeFilterFunction接口,其接口方法定义如下。

Mono<ClientResponse> filter(ClientRequest request, ExchangeFunction next)

在进行拦截时可以拦截request,也可以拦截response。下面的代码定义的Filter就拦截了request,给每个request都添加了一个名为header1的header,值为value1。它也拦截了response,response中也是添加了一个新的header信息。拦截response时,如果新的ClientResponse对象是通过ClientResponse.from(response)创建的,新的response是不会包含旧的response的body的,如果需要可以通过ClientResponse.Builderbody()指定,其它诸如header、cookie、状态码是会包含的。

String baseUrl = "http://localhost:8081";
WebClient webClient = WebClient.builder().baseUrl(baseUrl).filter((request, next) -> {
    ClientRequest newRequest = ClientRequest.from(request).header("header1", "value1").build();
    Mono<ClientResponse> responseMono = next.exchange(newRequest);
    return Mono.fromCallable(() -> {
        ClientResponse response = responseMono.block();
        ClientResponse newResponse = ClientResponse.from(response).header("responseHeader1", "Value1").build();
        return newResponse;
    });
}).build();

如果定义的Filter只期望对某个或某些request起作用,可以在Filter内部通过request的相关属性进行拦截,比如cookie信息、header信息、请求的方式或请求的URL等。也可以通过ClientRequest.attribute(attrName)获取某个特定的属性,该属性是在请求时通过attribute("attrName", "attrValue")指定的。这跟在HttpServletRequest中添加的属性的作用范围是类似的。

关于WebClient使用的更多信息请参考其API文档。

参考文档

https://docs.spring.io/spring/docs/current/spring-framework-reference/web-reactive.html#webflux-client

(注:本文是基于Spring WebFlux 5.0.7所写)

 

0
0
分享到:
评论

相关推荐

    Spring5中的WebClient使用方法详解

    Spring5 中的 WebClient 使用方法详解 Spring5 中引入的 WebClient 是一个功能完善的 HTTP 客户端,相比 RestTemplate 有很多优势。下面将详细介绍 WebClient 的使用方法。 WebClient 的介绍 WebClient 是 Spring...

    spring boot使用WebClient调用HTTP服务代码示例

    Spring Boot 使用 WebClient 调用 HTTP 服务代码示例 Spring Boot 是一个基于 Java 的框架,旨在简化基于 Spring 框架的应用程序开发。WebClient 是 Spring WebFlux 模块提供的一个非阻塞的基于响应式编程的进行 ...

    spring5 webclient使用指南详解

    本文将详细介绍 Spring 5 WebClient 的使用指南,包括基本用法、携带请求头和 Cookie、基本认证、设置全局 User-Agent 等。 基本用法 WebClient 的基本用法非常简单,首先需要创建一个 WebClient 实例,然后使用 `...

    WebClient-2.2.5.exe

    WebClient是Spring 5中引入的非阻塞,反应式的Web客户端。它是在Project Reactor和Netty基础上构建的,非常适合用于创建高性能的微服务。 WebClient的主要优点是它的非阻塞和反应式的特性,这使得它在处理大量并发...

    spring实现的网上书店

    6. **支付集成**:可能与第三方支付平台(如支付宝或微信支付)进行集成,Spring的RestTemplate或WebClient可以用来发送和接收API请求。 在"chapter8"这个文件名中,虽然没有具体说明,但可能表示项目的某个章节或...

    WebClient下载文件展示进度条

    本篇将详细介绍如何使用WebClient下载文件并同时显示进度条。 首先,我们需要了解WebClient类的基本用法。WebClient类提供了DownloadData、DownloadFile等方法来下载数据或文件。例如,下载文件到指定路径可以使用...

    使用webclient下载图片实例

    本文将详细介绍如何使用.NET Framework中的`WebClient`类来实现这一功能,并通过一个具体的实例进行讲解。 #### 二、WebClient简介 `WebClient`类是.NET Framework中用于简化HTTP请求处理的重要工具之一。它提供了...

    C# WebClient 上传文件

    本文将详细介绍如何使用`WebClient`类上传文件,并对代码进行深入解析。 #### 二、`WebClient`类简介 `WebClient`是.NET Framework中的一个类,用于简化HTTP请求与响应处理。通过这个类可以很容易地从Web获取数据...

    Spring 5 英文文档全套.7z

    总览 历史,设计理念,反馈,入门。 核心 IoC容器,事件,资源,i18n...Spring WebFlux,WebClient,WebSocket。 整合 远程处理,JMS,JCA,JMX,电子邮件,任务,调度,缓存。 语言能力 Kotlin,Groovy,动态语言。

    C#中WebClient实现文件下载

    在C#编程中,WebClient类提供了一种简单的方式来实现文件下载。WebClient是一个高度封装的网络通信类,主要用于HTTP协议交互,包括上传和下载数据。以下是对标题和描述中涉及知识点的详细解释: 1. **WebClient下载...

    WebClientDemo_webclient_

    【WebClientDemo_webclient_】项目是一个C#编程示例,展示了如何使用`WebClient`类来实现文件的下载功能。在.NET Framework中,`WebClient`是System.Net命名空间下的一个类,它提供了一种简便的方法来上传和下载数据...

    WebClientDemo

    import org.springframework.web.reactive.function.client.WebClient; import reactor.core.publisher.Mono; public class WebClientDemo { public static void main(String[] args) { WebClient client = ...

    WebClient jar包

    WebClient jar包

    spring-cloud.pdf

    最后,文档介绍了Spring Cloud Commons提供的公共抽象部分,包括@EnableDiscoveryClient注解、服务注册和服务发现、Spring RestTemplate和Spring WebClient作为负载均衡客户端的使用,以及如何处理多个RestTemplate...

    C#使用WebClient获取网页源文件例子

    在这个“C#使用WebClient获取网页源文件例子”中,我们将深入探讨如何利用`WebClient`来下载网页源代码,并进行UTF8编码的解码处理。 首先,`WebClient`类是`System.Net`命名空间的一部分,它提供了一个简洁的接口...

    SpringBoot中RestTemplate和WebClient的使用区别及优缺点含完整代码

    ### Spring Boot中RestTemplate和WebClient的使用区别及优缺点含完整代码 #### 一、引言 在Spring Boot框架中,开发人员经常需要与外部服务进行交互,无论是调用第三方API还是与其他微服务通信。为了实现这些需求...

    Spring3,Spring4,Spring5 jar包

    这个压缩包包含了Spring框架的三个重要版本:Spring 3.2、Spring 4.3和Spring 5.0。每个版本都有其独特的特性和改进,下面我们将详细探讨这三个版本中的关键知识点。 首先,Spring 3.2作为Spring 3.x系列的最后一个...

    WebClient用法

    ### WebClient用法详解 在C#编程语言中,`WebClient` 类是处理网络操作的一种简单方式,尤其适用于HTTP协议的交互。...以上就是关于`WebClient`在C#中的基本使用方法及相关知识点的详细介绍。希望对你有所帮助!

    WebClient 的Post实现

    在本场景中,我们关注的是“WebClient的Post实现”,这通常涉及到使用Silverlight技术来模拟网页上的POST请求,从而实现数据上传。Silverlight是一种由微软开发的富互联网应用程序(RIA)平台,它允许开发者创建交互...

    Spring-5.0.0-官方中文文档

    5. **增强的HTTP客户端**:Spring 5的RestTemplate被替换为WebClient,这是一个反应式的HTTP客户端,支持链式调用和更丰富的错误处理,适合处理复杂的异步请求。 6. **Java 8和更高版本的支持**:Spring 5全面拥抱...

Global site tag (gtag.js) - Google Analytics