You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Jakarta ClientBuilder调用第三方API时遭遇BlockingNotAllowedException

解决Vert.x事件循环线程阻塞问题

问题根源

你遇到的异常是因为fetchUserInfo方法里的同步HTTP调用(get(JSONObject.class))在Vert.x事件循环线程上执行了阻塞IO操作,之前仅在控制器级别添加@Blocking/@NonBlocking注解无效,是因为实际执行阻塞逻辑的是WenTokenInfoResolver类的方法,控制器的注解无法覆盖这个独立类的方法执行线程。

解决方案

方案1:给阻塞方法/类添加@Blocking注解

直接在执行阻塞IO的fetchUserInfo方法或者整个WenTokenInfoResolver类上添加@io.smallrye.common.annotation.Blocking注解,让该方法被调度到Vert.x的工作线程池执行:

import io.smallrye.common.annotation.Blocking;
import static jakarta.ws.rs.core.HttpHeaders.AUTHORIZATION;
import jakarta.ws.rs.client.Client;
import jakarta.ws.rs.client.ClientBuilder;

public class WenTokenInfoResolver {
    private final Client client;

    public WenTokenInfoResolver() {
        client = ClientBuilder.newBuilder().register(JacksonFeature.class).build();
    }

    @Blocking
    public UserInfo fetchUserInfo(final String userToken) throws WenTokenInfoResolverFailureException {
        return UserInfo.fromResponse(client.target(ConfigHelper.wenBaseUrl)
                .path(ConfigHelper.wenInfoOAuth)
                .request()
                .header(AUTHORIZATION, "Bearer " + userToken)
                .get(JSONObject.class));
    }
}

方案2:改用异步HTTP调用(推荐)

使用Jakarta Client的异步API,避免阻塞事件循环线程,无需添加@Blocking注解:

import java.util.concurrent.CompletionStage;
import static jakarta.ws.rs.core.HttpHeaders.AUTHORIZATION;
import jakarta.ws.rs.client.Client;
import jakarta.ws.rs.client.ClientBuilder;

public class WenTokenInfoResolver {
    private final Client client;

    public WenTokenInfoResolver() {
        client = ClientBuilder.newBuilder().register(JacksonFeature.class).build();
    }

    public CompletionStage<UserInfo> fetchUserInfo(final String userToken) {
        return client.target(ConfigHelper.wenBaseUrl)
                .path(ConfigHelper.wenInfoOAuth)
                .request()
                .header(AUTHORIZATION, "Bearer " + userToken)
                .rx() // 启用反应式异步API
                .get(JSONObject.class)
                .thenApply(UserInfo::fromResponse);
    }
}

调用该方法时,需处理CompletionStage的异步结果,比如在控制器方法中直接返回CompletionStage<UserInfo>,框架会自动处理异步调度。

方案3:使用Vert.x适配的Jakarta Client

如果项目基于Quarkus等Vertx生态框架,推荐使用VertxClientBuilder创建客户端,更好适配Vert.x异步模型:

import io.vertx.mutiny.core.Vertx;
import io.vertx.mutiny.ext.web.WebClient;
import io.vertx.ext.web.client.WebClientOptions;
import jakarta.enterprise.context.ApplicationScoped;

@ApplicationScoped
public class WenTokenInfoResolver {
    private final WebClient webClient;

    public WenTokenInfoResolver(Vertx vertx) {
        this.webClient = WebClient.create(vertx, new WebClientOptions()
                .setDefaultHost(ConfigHelper.wenBaseUrl)
                .setDefaultPort(80)); // 根据实际服务端口调整
    }

    public Uni<UserInfo> fetchUserInfo(final String userToken) {
        return webClient.get(ConfigHelper.wenInfoOAuth)
                .putHeader(AUTHORIZATION, "Bearer " + userToken)
                .send()
                .onItem().transform(response -> {
                    JSONObject json = response.bodyAsJsonObject();
                    return UserInfo.fromResponse(json);
                });
    }
}

内容的提问来源于stack exchange,提问作者hemanth reddy m

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 09:51:07