如何为Quarkus实现自定义Dev Service并在DevUI中展示?
自定义Quarkus Dev Service的最佳实践
要在Quarkus开发模式中复用你的容器逻辑并作为Dev Service展示在DevUI中,核心是实现Quarkus的DevServicesProvider接口,同时通过DevUI扩展添加状态展示。以下是具体步骤:
1. 抽离容器复用逻辑
先把测试代码里的容器创建、启停逻辑抽成工具类,让测试和Dev Service共享代码,避免重复实现:
import org.testcontainers.containers.GenericContainer; import org.testcontainers.images.builder.ImageFromDockerfile; import org.testcontainers.wait.strategy.Wait; import java.io.File; import java.util.Map; public class ExternalServiceContainerUtil { private static GenericContainer<?> container; public static Map<String, String> startContainer() { // 复用你原有的镜像与容器配置 ImageFromDockerfile image = new ImageFromDockerfile() .withDockerfile(new File("src/main/docker/your-service.Dockerfile")); container = new GenericContainer<>(image) .withExposedPorts(8080) .waitingFor(Wait.forHttp("/health").forStatusCode(200)); container.start(); // 返回应用需要的配置属性,比如服务地址 return Map.of( "external-service.base-url", String.format("http://%s:%d", container.getHost(), container.getMappedPort(8080)) ); } public static void stopContainer() { if (container != null && container.isRunning()) { container.stop(); } } }
2. 实现DevServicesProvider接口
这个接口是Quarkus自定义Dev Service的核心,负责在开发模式启动时创建、管理容器:
import io.quarkus.deployment.dev.devservices.DevServicesContext; import io.quarkus.deployment.dev.devservices.DevServicesProvider; import io.quarkus.deployment.dev.devservices.DevServicesResult; import jakarta.inject.Singleton; import org.eclipse.microprofile.config.Config; import org.eclipse.microprofile.config.ConfigProvider; import java.util.Map; @Singleton public class ExternalServiceDevServicesProvider implements DevServicesProvider { @Override public DevServicesResult start(DevServicesContext context) { // 通过配置开关控制是否启用该Dev Service Config config = ConfigProvider.getConfig(); boolean enabled = config.getOptionalValue("quarkus.devservices.external-service.enabled", Boolean.class) .orElse(true); if (!enabled) { return null; } // 启动容器并获取配置属性 Map<String, String> serviceProperties = ExternalServiceContainerUtil.startContainer(); // 定义服务停止回调 DevServicesResult.RunningDevService runningService = new DevServicesResult.RunningDevService( "external-service", ExternalServiceContainerUtil::stopContainer, serviceProperties ); return DevServicesResult.builder() .addRunningService(runningService) .build(); } @Override public boolean supports(String name) { return "external-service".equals(name); } @Override public int priority() { return 50; // 优先级数值,按需调整,避免与其他Dev Service冲突 } }
3. 添加DevUI展示
要让你的Dev Service出现在Quarkus的DevUI中,创建一个DevUI扩展类:
import io.quarkus.devui.page.PageTitle; import io.quarkus.devui.runtime.component.DevUIComponent; import jakarta.inject.Inject; import org.eclipse.microprofile.config.Config; @DevUIComponent(title = "External Service", category = "External Services") public class ExternalServiceDevUI { @Inject Config config; @PageTitle("Service Status") public String getServiceStatus() { String serviceUrl = config.getOptionalValue("external-service.base-url", String.class) .orElse("Not running"); return String.format("External Service is running at: %s", serviceUrl); } // 可扩展添加更多信息,比如容器ID、日志查看链接等 }
4. 复用测试逻辑
你的QuarkusTestResourceLifecycleManager可以直接复用工具类,保持测试与开发环境的一致性:
import io.quarkus.test.common.QuarkusTestResourceLifecycleManager; import java.util.Map; public class ExternalServiceTestResource implements QuarkusTestResourceLifecycleManager { @Override public Map<String, String> start() { return ExternalServiceContainerUtil.startContainer(); } @Override public void stop() { ExternalServiceContainerUtil.stopContainer(); } }
相关API文档说明
Quarkus官方文档的Extending Quarkus章节下,有针对DevServicesProvider接口和DevUI扩展的详细说明,核心内容包括:
- Dev Service的生命周期管理逻辑
- 配置属性的传递方式
- DevUI组件的注册与自定义展示
内容的提问来源于stack exchange,提问作者Jakob Graf
相关产品推荐
相关产品推荐

