it编程 > 编程语言 > Java

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

3人参与 2025-12-09 Java

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. 其他常见配置

例如日志拦截器:

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 性能调优建议

15. 常见问题解答

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

q2:如何打印 webclient 的请求和响应日志?a:可通过 exchangefilterfunction 实现,或配置日志框架:

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

q3:webclient 与 resttemplate 区别?

总结

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

(0)

您想发表意见!!点此发布评论

推荐阅读

使用Java读取Excel文件内容的三种方法

12-09

Java线程池核心参数原理及使用指南

12-09

SpringBoot 实现多租户架构的步骤实践

12-09

SpringBoot 启动时自动执行代码的几种方式讲解

12-09

使用Java将CSV文件转换为格式化的Excel文件

12-09

Java线程池配置原则与实战解析

12-09

猜你喜欢

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论