当前位置:首页技术社开发笔记Spring框架中使用WebClient发送请求

Spring框架中使用WebClient发送请求

从 Spring 5 开始,Spring 中全面引入了 Reactive 响应式编程。而 WebClient 则是 Spring WebFlux 模块提供的一个非阻塞的基于响应式编程的进行 Http 请求的客户端工具。

由于 WebClient 的请求模式属于异步非阻塞,能够以少量固定的线程处理高并发的 HTTP 请求。因此,从 Spring 5 开始,HTTP 服务之间的通信我们就可以考虑使用 WebClient 来取代之前的 RestTemplate。

下面记录 WebClient 的基本使用方法,并记录如何通过 WebClient 发送 GET 和 POST 请求。

1.添加依赖

要使用 WebClient,首先需要在 Maven 项目中添加 Spring WebFlux 依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-webflux</artifactId>
</dependency>

对于 Gradle 项目:

implementation 'org.springframework.boot:spring-boot-starter-webflux'

2.创建 WebClient 实例

可以通过多种方式创建 WebClient 实例:

方式一:全局 WebClient Bean(推荐)

在 Spring 项目中,通常会通过定义一个 WebClient.Builder Bean,并在需要的地方注入。

@Configuration
public class WebClientConfig {

    @Bean
    public WebClient.Builder webClientBuilder() {
        return WebClient.builder();
    }
}

然后在服务中使用:

@Service
public class MyService {

    private final WebClient webClient;

    public MyService(WebClient.Builder webClientBuilder) {
        this.webClient = webClientBuilder.baseUrl("https://example.com").build();
    }

    public String getData() {
        return webClient.get()
                        .uri("/api/data")
                        .retrieve()
                        .bodyToMono(String.class)
                        .block(); // 这里使用 block() 表示阻塞操作
    }
}

方式二:使用静态创建方法

可以直接使用 WebClient.create() 创建客户端实例:

WebClient webClient = WebClient.create("https://example.com");

3.发送请求

3.1 发送 GET 请求

public String getData() {
    WebClient webClient = WebClient.create("https://jsonplaceholder.typicode.com");

    String response = webClient.get()
                               .uri("/posts/1")
                               .retrieve()
                               .bodyToMono(String.class) 
                               .block(); 
    return response;
}
  • retrieve():用于发出请求并获取响应。
  • bodyToMono(String.class):将响应体转换为 Mono<String>Mono 表示一个异步的单值序列。
  • block():阻塞当前线程,直到请求完成并返回结果。

3.2 发送 POST 请求

下面是一个发送 POST 请求并传递 JSON 数据的例子:

public String postData() {
    WebClient webClient = WebClient.create("https://jsonplaceholder.typicode.com");

    String response = webClient.post()
                               .uri("/posts")
                               .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) 
                               .bodyValue("{ \"title\": \"foo\", \"body\": \"bar\", \"userId\": 1 }") 
                               .retrieve()
                               .bodyToMono(String.class)
                               .block();

    return response;
}
  • bodyValue():设置请求体的数据,可以传递字符串、对象、或者其他序列化格式。
  • block():同步等待请求完成。

3.3 异步请求

如果不想阻塞线程,可以使用 WebClient 的异步处理功能。例如,使用 subscribe() 来处理异步请求:

public void getDataAsync() {
    WebClient webClient = WebClient.create("https://jsonplaceholder.typicode.com");

    webClient.get()
             .uri("/posts/1")
             .retrieve()
             .bodyToMono(String.class)
             .subscribe(response -> {
                 System.out.println("异步响应: " + response);
             });
}

这里使用了 subscribe() 方法,它接受一个 Consumer 回调函数,当响应到达时触发这个回调函数。

4. 处理错误响应

通过 WebClient,可以使用 onStatus() 来处理特定的 HTTP 响应状态码:

public String getDataWithErrorHandling() {
    WebClient webClient = WebClient.create("https://jsonplaceholder.typicode.com");

    return webClient.get()
                    .uri("/posts/invalid") 
                    .retrieve()
                    .onStatus(HttpStatus::is4xxClientError, response -> {
                        return response.bodyToMono(String.class)
                                       .flatMap(errorBody -> Mono.error(new RuntimeException("4xx 错误: " + errorBody)));
                    })
                    .onStatus(HttpStatus::is5xxServerError, response -> {
                        return response.bodyToMono(String.class)
                                       .flatMap(errorBody -> Mono.error(new RuntimeException("5xx 错误: " + errorBody)));
                    })
                    .bodyToMono(String.class)
                    .block();
}

5. 超时配置

可以通过自定义 WebClientHttpClient 来设置超时时间:

import reactor.netty.http.client.HttpClient;
import java.time.Duration;

HttpClient httpClient = HttpClient.create()
                                  .responseTimeout(Duration.ofSeconds(5)); // 设置响应超时

WebClient webClient = WebClient.builder()
                               .clientConnector(new ReactorClientHttpConnector(httpClient))
                               .build();

6. 文件上传

通过 WebClient 实现文件上传,可以使用 multipart/form-data 来传递文件:

import org.springframework.http.MediaType;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;

public String uploadFile() {
    WebClient webClient = WebClient.create("https://example.com");

    Resource file = new FileSystemResource("/path/to/file.txt");

    return webClient.post()
                    .uri("/upload")
                    .contentType(MediaType.MULTIPART_FORM_DATA)
                    .bodyValue(file)
                    .retrieve()
                    .bodyToMono(String.class)
                    .block();
}

总结:

  • 同步调用:可以使用 .block()WebClient 的调用同步阻塞,方便传统开发者的过渡。
  • 异步调用:通过 MonoFlux 支持异步和响应式的编程模型,非常适合处理大量并发请求。
  • 丰富的错误处理:可以通过 onStatus() 针对不同的状态码进行错误处理。
  • 灵活性强:可以自定义超时、拦截器、连接池等,适应各种复杂场景。
除笔记和教程外,其它资源均收集于互联网,版权争议与本站无关,其它资源仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容,否则,一切后果请用户自负。
本站如果侵犯你的利益,请务必携带权利证明请发送邮箱到doraera@163.com ,我们会第一时间为您处理。

给TA打赏
共{{data.count}}人
人已打赏
开发笔记

[WIN安装] MySQL安装 ZIP版本

2024-8-6 15:31:30

源码社科技资讯

[WIN]开源虚拟显示器工具:Easy Virtual Display

2023-10-14 13:03:53

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索