Spring Boot 异步HTTP客户端配置使用

 更新时间:2025年12月09日 10:07:28   作者:猩火燎猿  
本文详细介绍SpringBoot中使用WebClient实现异步HTTP请求的完整方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

1. 添加依赖

如果是 Spring Boot 2.x 或 3.x,WebClient 已包含在 spring-boot-starter-webflux 中:

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

2. WebClient 配置

可以通过 Bean 全局配置,也可以直接使用 WebClient.create()

2.1 全局 Bean 配置

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.function.client.WebClient;

@Configuration
public class WebClientConfig {
    @Bean
    public WebClient webClient(WebClient.Builder builder) {
        return builder
                .baseUrl("https://api.example.com") // 可配置默认 baseUrl
                .build();
    }
}

2.2 自定义连接池和超时(高级配置)

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

@Bean
public WebClient webClient() {
    ConnectionProvider provider = ConnectionProvider.builder("custom")
        .maxConnections(100)
        .pendingAcquireTimeout(Duration.ofSeconds(60))
        .build();

    HttpClient httpClient = HttpClient.create(provider)
        .responseTimeout(Duration.ofSeconds(5));

    return WebClient.builder()
        .clientConnector(new ReactorClientHttpConnector(httpClient))
        .build();
}

3. 异步调用示例

WebClient 默认就是异步非阻塞的(基于 Reactor 响应式流)。

3.1 GET 请求

@Autowired
private WebClient webClient;

public Mono<String> getDataAsync() {
    return webClient.get()
        .uri("/data")
        .retrieve()
        .bodyToMono(String.class);
}

3.2 POST 请求

public Mono<ResponseDto> postDataAsync(RequestDto request) {
    return webClient.post()
        .uri("/submit")
        .bodyValue(request)
        .retrieve()
        .bodyToMono(ResponseDto.class);
}

3.3 在 Controller 中使用

@RestController
public class DemoController {
    @Autowired
    private WebClient webClient;

    @GetMapping("/call-remote")
    public Mono<String> callRemote() {
        return webClient.get()
            .uri("/remote-api")
            .retrieve()
            .bodyToMono(String.class);
    }
}

4. 异步并发请求

比如同时请求多个接口并合并结果:

Mono<String> call1 = webClient.get().uri("/api1").retrieve().bodyToMono(String.class);
Mono<String> call2 = webClient.get().uri("/api2").retrieve().bodyToMono(String.class);

Mono<Tuple2<String, String>> result = Mono.zip(call1, call2);

5. 错误处理

webClient.get().uri("/api")
    .retrieve()
    .onStatus(HttpStatus::isError, response -> 
        response.bodyToMono(String.class)
            .flatMap(errorBody -> Mono.error(new RuntimeException(errorBody)))
    )
    .bodyToMono(String.class);

6. 配置超时和连接池参数

如前文 2.2,使用 Reactor Netty 的 ConnectionProvider 和 HttpClient 可以灵活设置连接数、超时等。

7. 其他常见配置

  • 代理设置
  • SSL 配置
  • 请求/响应日志
  • 拦截器(ExchangeFilterFunction)

例如日志拦截器:

WebClient.builder()
    .filter((request, next) -> {
        System.out.println("Request: " + request.url());
        return next.exchange(request);
    })
    .build();

8. 与 Spring MVC Controller 集成

如果你用的是 Spring MVC Controller,可以用 Mono<T> 或 Flux<T> 作为返回值,Spring Boot 会自动处理响应式类型。

9. 自定义请求头、参数、Cookie

设置请求头/参数:

webClient.get()
    .uri(uriBuilder -> uriBuilder
        .path("/search")
        .queryParam("keyword", "spring")
        .build())
    .header("Authorization", "Bearer xxx")
    .cookie("SESSIONID", "abcdefg")
    .retrieve()
    .bodyToMono(String.class);

10. 全局异常处理与重试机制

全局异常处理:

可以通过 ExchangeFilterFunction 实现全局异常拦截与处理:

@Bean
public WebClient webClient() {
    return WebClient.builder()
        .filter((request, next) -> next.exchange(request)
            .flatMap(response -> {
                if (response.statusCode().isError()) {
                    return response.bodyToMono(String.class)
                        .flatMap(errorBody -> Mono.error(new RuntimeException(errorBody)));
                }
                return Mono.just(response);
            }))
        .build();
}

重试机制(reactor-retry):

import reactor.util.retry.Retry;

webClient.get()
    .uri("/unstable-api")
    .retrieve()
    .bodyToMono(String.class)
    .retryWhen(Retry.fixedDelay(3, Duration.ofSeconds(2)));

11. 文件上传与下载(异步)

文件上传(multipart/form-data):

import org.springframework.core.io.FileSystemResource;

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

webClient.post()
    .uri("/upload")
    .contentType(MediaType.MULTIPART_FORM_DATA)
    .body(BodyInserters.fromMultipartData("file", file))
    .retrieve()
    .bodyToMono(String.class);

文件下载:

webClient.get()
    .uri("/download")
    .retrieve()
    .bodyToFlux(DataBuffer.class)
    .map(dataBuffer -> {
        // 将 DataBuffer 写入文件
        // 省略具体实现
        return dataBuffer;
    });

12. 与服务发现、负载均衡集成

如果用 Spring Cloud,可直接注入带负载均衡的 WebClient:

import org.springframework.cloud.client.loadbalancer.LoadBalanced;

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

// 使用
@Autowired
private WebClient.Builder webClientBuilder;

webClientBuilder.build()
    .get()
    .uri("http://service-name/api")
    .retrieve()
    .bodyToMono(String.class);

这里的 service-name 是注册中心(如 Eureka、Nacos)中的服务名,WebClient 会自动负载均衡。

13. 与 OAuth2 等安全机制集成

Spring Security 提供了对 OAuth2 的支持,可以自动为 WebClient 请求加上 Token。

import org.springframework.security.oauth2.client.web.reactive.function.client.ServerOAuth2AuthorizedClientExchangeFilterFunction;

@Bean
public WebClient webClient(ReactiveOAuth2AuthorizedClientManager manager) {
    ServerOAuth2AuthorizedClientExchangeFilterFunction oauth2 = 
        new ServerOAuth2AuthorizedClientExchangeFilterFunction(manager);
    return WebClient.builder()
        .apply(oauth2.oauth2Configuration())
        .build();
}

14. WebClient 性能调优建议

  • 连接池参数调整合理设置最大连接数、每主机最大连接数、连接超时等
  • 响应式编程配合线程池对于非响应式 Controller 推荐 @Async 或线程池配合
  • 避免阻塞操作在响应式流中避免 block(),否则会失去异步性能优势
  • 合理的重试和超时防止雪崩和资源耗尽

15. 常见问题解答

Q1:WebClient 如何同步调用?A:可以用 .block(),但这会阻塞线程,失去异步优势。一般只在测试或特殊场景下使用。

Q2:如何打印 WebClient 的请求和响应日志?A:可通过 ExchangeFilterFunction 实现,或配置日志框架:

logging.level.reactor.netty.http.client=DEBUG

Q3:WebClient 与 RestTemplate 区别?

  • RestTemplate 是同步阻塞的
  • WebClient 是异步非阻塞的,支持响应式流
  • 官方推荐新项目优先用 WebClient

总结

  • 推荐使用 WebClient 作为 Spring Boot 异步 HTTP 客户端
  • 支持灵活配置连接池、超时、代理、SSL 等
  • 默认就是异步非阻塞
  • 适合高并发、微服务场景
  • WebClient 支持丰富的异步 HTTP 场景,配置灵活
  • 可与 Spring Cloud、Spring Security 等生态无缝集成
  • 适合微服务、网关、爬虫等高并发异步场景

到此这篇关于Spring Boot 异步HTTP客户端配置使用的文章就介绍到这了,更多相关Spring Boot 异步HTTP内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • SpringBoot中日志输出规范的五种策略

    SpringBoot中日志输出规范的五种策略

    在企业级应用开发中,合理规范的日志记录是系统稳定运行、问题排查和性能优化的关键保障,SpringBoot作为流行的Java开发框架,提供了强大而灵活的日志支持,但如何建立统一、高效的日志输出规范却是许多团队面临的挑战,本文将介绍SpringBoot中5种日志输出规范策略
    2025-06-06
  • java算法导论之FloydWarshall算法实现代码

    java算法导论之FloydWarshall算法实现代码

    这篇文章主要介绍了算法导论之FloydWarshall算法实现代码的相关资料,需要的朋友可以参考下
    2017-05-05
  • MybatisPlus多表查询及分页查询完整代码

    MybatisPlus多表查询及分页查询完整代码

    这篇文章主要介绍了MybatisPlus多表查询及分页查询完整代码,本文通过示例代码给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧
    2024-08-08
  • Java中的反射机制基本运用详解

    Java中的反射机制基本运用详解

    这篇文章主要介绍了Java 反射机制原理与用法,结合实例形式详细分析了Java反射机制的相关概念、原理、基本使用方法及操作注意事项,需要的朋友可以参考下
    2021-08-08
  • Java中ByteArrayInputStream和ByteArrayOutputStream用法详解

    Java中ByteArrayInputStream和ByteArrayOutputStream用法详解

    这篇文章主要介绍了Java中ByteArrayInputStream和ByteArrayOutputStream用法详解, ByteArrayInputStream 的内部额外的定义了一个计数器,它被用来跟踪 read() 方法要读取的下一个字节
    2022-06-06
  • IDEA下创建SpringBoot+MyBatis+MySql项目实现动态登录与注册功能

    IDEA下创建SpringBoot+MyBatis+MySql项目实现动态登录与注册功能

    这篇文章主要介绍了IDEA下创建SpringBoot+MyBatis+MySql项目实现动态登录与注册功能,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-02-02
  • java如何将一个float型数的整数部分和小数分别输出显示

    java如何将一个float型数的整数部分和小数分别输出显示

    这篇文章主要介绍了java如何将一个float型数的整数部分和小数分别输出显示,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-07-07
  • Java 带参数与带返回值的方法的定义和调用

    Java 带参数与带返回值的方法的定义和调用

    在java中,方法就是用来完成解决某件事情或实现某个功能的办法。方法实现的过程中,会包含很多条语句用于完成某些有意义的功能——通常是处理文本,控制输入或计算数值,这篇文章我们来探究一下带参数与带返回值的方法的定义和调用
    2022-04-04
  • 使用java实现猜拳小游戏

    使用java实现猜拳小游戏

    这篇文章主要为大家详细介绍了使用java实现猜拳小游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-07-07
  • Java基于正则表达式获取指定HTML标签指定属性值的方法

    Java基于正则表达式获取指定HTML标签指定属性值的方法

    这篇文章主要介绍了Java基于正则表达式获取指定HTML标签指定属性值的方法,涉及java基于正则的HTML元素匹配相关操作技巧,需要的朋友可以参考下
    2017-01-01

最新评论