Quarkus中如何编程获取Keycloak Dev Services自动分配的运行端口
你注入的quarkus.keycloak.devservices.port是预配置固定端口用的配置项,只有当你手动给这个参数赋值的时候才会存在。当使用系统自动分配端口时,这个配置项未被赋值,所以注入时会抛出配置不存在的异常,你可以用以下两种方法获取实际运行端口:
方法1:从自动生成的认证服务地址提取端口
Keycloak Dev Service启动完成后,会自动将实际可访问的服务地址写入配置项quarkus.oidc.auth-server-url,该配置项在自动分配端口场景下也会存在,你可以注入该配置后从中提取端口:
import org.eclipse.microprofile.config.inject.ConfigProperty; import java.net.URL; import java.net.MalformedURLException; import jakarta.enterprise.context.ApplicationScoped; @ApplicationScoped public class KeycloakConfig { @ConfigProperty(name = "quarkus.oidc.auth-server-url") String authServerUrl; public int getDevServicePort() { try { URL url = new URL(authServerUrl); return url.getPort(); } catch (MalformedURLException e) { throw new RuntimeException("解析Keycloak服务地址失败", e); } } }
如果你的项目未引入OIDC扩展,也可以注入quarkus.keycloak.devservices.auth-server-url配置项,取值和上述配置完全一致。
方法2:监听DevService启动事件直接获取端口
你可以监听Quarkus提供的DevServicesStartedEvent事件,在事件回调中直接从Keycloak容器实例中获取映射的宿主机端口,这种方式不需要解析URL,更直接:
import io.quarkus.devservices.common.DevServicesStartedEvent; import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.event.Observes; import org.testcontainers.containers.KeycloakContainer; import io.quarkus.arc.profile.IfBuildProfile; // 限制仅在开发/测试模式加载该Bean,避免生产模式报错 @IfBuildProfile(profile = {"dev", "test"}) @ApplicationScoped public class KeycloakPortHolder { private Integer devServicePort; public void onDevServicesReady(@Observes DevServicesStartedEvent event) { for (var service : event.getDevServices()) { if (service.getContainer() instanceof KeycloakContainer kcContainer) { // 8080为Keycloak容器内部默认监听端口 devServicePort = kcContainer.getMappedPort(8080); break; } } } public Integer getDevServicePort() { return devServicePort; } }
注意事项
- 方法2仅在开发模式和测试模式下生效,生产模式不会启动Dev Service,因此给Bean加上了profile限制,避免生产环境加载报错。
- 如果你需要同时兼容手动指定端口和自动分配端口的场景,可以给注入的配置项加上默认值,结合两种方法做兼容处理。
内容的提问来源于stack exchange,提问作者Sebastian S
相关产品推荐
相关产品推荐

