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

是否有配置多个命名OidcClient的Quarkus响应式项目示例用于多服务调用?

Quarkus 响应式项目多OIDC客户端配置实现方案

1. 引入必要依赖

在项目pom.xml中添加以下核心依赖:

<dependencies>
    <!-- 响应式OIDC客户端依赖 -->
    <dependency>
        <groupId>io.quarkus</groupId>
        <artifactId>quarkus-oidc-client-reactive</artifactId>
    </dependency>
    <!-- 响应式REST客户端依赖(可选,用于声明式服务调用) -->
    <dependency>
        <groupId>io.quarkus</groupId>
        <artifactId>quarkus-rest-client-reactive</artifactId>
    </dependency>
    <!-- 响应式WebClient依赖(可选,用于编程式服务调用) -->
    <dependency>
        <groupId>io.quarkus</groupId>
        <artifactId>quarkus-rest-client-reactive-jackson</artifactId>
    </dependency>
</dependencies>

2. 多客户端配置

在application.yml(或application.properties)中配置4个独立的OIDC客户端,适配Keycloak密码授权模式:

quarkus:
  oidc-client:
    clientA:
      auth-server-url: http://你的Keycloak地址/realms/你的领域名
      client-id: OidcClientA
      client-secret: 客户端A的密钥
      grant-type: password
      credentials:
        user:
          username: 授权用户名
          password: 授权密码
    clientB:
      auth-server-url: http://你的Keycloak地址/realms/你的领域名
      client-id: OidcClientB
      client-secret: 客户端B的密钥
      grant-type: password
      credentials:
        user:
          username: 授权用户名
          password: 授权密码
    clientC:
      # 同上格式配置客户端C参数
    clientD:
      # 同上格式配置客户端D参数

3. 指定客户端注入与Token获取

使用@Named注解匹配配置中的客户端名称,即可注入对应实例,自动完成Token获取:

import io.quarkus.oidc.client.reactive.OidcClient;
import io.vertx.ext.web.client.WebClient;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.inject.Named;
import io.smallrye.mutiny.Uni;

@ApplicationScoped
public class ServiceCallService {

    // 注入对应服务的OIDC客户端
    @Inject
    @Named("clientA")
    OidcClient oidcClientA;

    @Inject
    @Named("clientB")
    OidcClient oidcClientB;
    // 同理注入clientC、clientD对应的OidcClient实例

    // 示例:调用服务A接口,自动携带授权头
    public Uni<String> callServiceA() {
        // 先获取客户端A的Token,再发起请求
        return oidcClientA.getTokens()
                .onItem().transformToUni(tokens -> {
                    String authHeader = "Bearer " + tokens.getAccessToken();
                    // 此处使用WebClient或者声明式REST客户端发起请求,携带authHeader
                    return WebClient.create("http://服务A的地址")
                            .get()
                            .uri("/api/xxx")
                            .header("Authorization", authHeader)
                            .retrieve()
                            .bodyToMono(String.class)
                            .convert().toUni();
                });
    }
}

4. 声明式REST客户端自动携带授权头(推荐)

如果使用Quarkus声明式REST客户端,可以通过默认方法自动注入对应客户端的授权头,无需手动处理Token:

import io.quarkus.oidc.client.reactive.OidcClient;
import io.smallrye.mutiny.Uni;
import jakarta.enterprise.inject.spi.CDI;
import jakarta.inject.Named;
import org.eclipse.microprofile.rest.client.annotation.ClientHeaderParam;
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;

@RegisterRestClient(configKey = "serviceA")
@ClientHeaderParam(name = "Authorization", value = "{getAuthHeader}")
public interface ServiceAClient {

    @GET
    @Path("/api/xxx")
    Uni<String> getServiceAData();

    // 自动获取clientA的Token生成授权头
    default String getAuthHeader() {
        OidcClient clientA = CDI.current().select(OidcClient.class, new NamedLiteral("clientA")).get();
        return "Bearer " + clientA.getTokens().await().indefinitely().getAccessToken();
    }
}

注意事项

  • 配置中quarkus.oidc-client.后的客户端名称必须和@Named注解中的值完全匹配,否则会注入默认客户端或者抛出异常
  • 密码授权模式下必须配置对应客户端的用户名、密码参数,否则无法自动完成Token申请
  • 纯响应式场景下避免在链式调用外使用await().indefinitely()阻塞线程,建议通过Uni的流式处理完成Token获取和请求发起的全异步逻辑

内容的提问来源于stack exchange,提问作者ajith kumar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 13:27:02