是否有配置多个命名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
相关产品推荐
相关产品推荐

