首页 > 解决方案 > Spring Boot 健康检查 - 继承

问题描述

我正在尝试使用弹簧执行器进行健康检查。我需要执行健康检查的网址很少,但调用它们的方法非常相似。我试图创建一个基类,它实现 healthindicator 和从 base 扩展的子类,它们传递实际的 url,然后调用 health 方法。有没有更好的方法来做到这一点?

基础健康检查类

@Component
public class BaseHealthCheck implements HealthIndicator{

    private String url;

    @Override
    public Health health() {
        // call url
        return Health.up().build();
    }

    private void setUrl(String url){
       this.url = url
    }

}

儿童1班

@Component
public class Child1HealthCheck extends BaseHealthCheck {

    @Value("${childurl1}")
    private String url;

    @Override
    public Health health() {
        super.health();
    }

    @PostConstruct
    private void setUrl(){
       super.setUrl(url);
    }

}

儿童班 2

@Component
public class Child2HealthCheck extends BaseHealthCheck {

    @Value("${childurl2}")
    private String url;

    @Override
    public Health health() {
        super.health();
    }

    @PostConstruct
    private void setUrl(){
       super.setUrl(url);
    }

}

标签: javaspringspring-boot

解决方案


恕我直言,您的解决方案的两个主要缺点是您需要为每个新的健康检查和使用字段注入一个新类。实现这一点的另一种方法如下。

我为“业务逻辑”创建了一个简单的类。此类实现 HealthIndicator 并且不是 Spring 托管 bean。它从构造函数中获取所有必需的依赖项以避免字段注入。

public class CustomHealthCheck implements HealthIndicator {

    private final String url; // use URL or URI instead of String?

    public CustomHealthCheck(String url) {
        this.url = url;
    }

    @Override
    public Health health() {
        // call url
        return Health.up().build();
    }
}

为了让它们与 Spring 一起工作,我创建了一个配置类来创建 Spring bean。因此,无需为每个新的健康检查创建一个与现有健康检查具有相同逻辑的新类,只需在该类中创建一个新方法即可。

@Configuration
public class CustomHealthChecks {

    @Bean
    public CustomHealthCheck firstHealthCheck(@Value("${url1}") String url) {
        return new CustomHealthCheck(url);
    }

    @Bean
    public CustomHealthCheck secondHealthCheck(@Value("${url2}") String url) {
        return new CustomHealthCheck(url);
    }
}

还有一个简单的测试来验证我的 spring 上下文中有两个 HealthIndicator 对象。

@Test
public void produces_expected_health_indicators() {
    ApplicationContextRunner runner = new ApplicationContextRunner();
    runner.withPropertyValues("url1=https://stackoverflow.com/", "url2=https://start.spring.io/")
          .withUserConfiguration(CustomHealthChecks.class)
          .run(context -> {
        assertThat(context).getBeans(HealthIndicator.class).hasSize(2);
    });
}

推荐阅读