直接访问 Spring 引导执行器运行状况 beans/data?

Direct access to Spring Boot Actuator Health beans/data?

是否可以从 Sprig Boot 应用程序直接访问 actuator/health 数据而不进行 rest 调用和解析结果?

理想情况下,我可以自动装配一个 bean,然后能够通过方法调用获取健康数据的对象表示。

例如,如果我的健康端点显示如下内容:

{
    "status": "UP",
    "components": {
        "db": {
            "status": "UP",
            "details": {
                "database": "PostgreSQL",
                "result": 1,
                "validationQuery": "SELECT 1"
            }
        },
        "diskSpace": {
            "status": "UP",
            "details": {
                "total": 499963174912,
                "free": 389081399296,
                "threshold": 10485760
            }
        },
        "ping": {
            "status": "UP"
        },
        "redis": {
            "status": "UP",
            "details": {
                "version": "3.2.12"
            }
        }
    }
}

那么我可以自动装配哪些组件来找出这些信息中的每一个?

当然可以注入Endpoint。例如,如果您对 HealthEndpoint 感兴趣,您可以这样做:

@RestController
public class ActuatorController {

    private final HealthEndpoint healthEndpoint;

    public ActuatorController(HealthEndpoint healthEndpoint) {
        this.healthEndpoint = healthEndpoint;
    }

    @GetMapping("health")
    public String health() {
        return healthEndpoint.health().getStatus().getCode();
    }
}

此外,默认情况下,信息和健康点在执行器中启用,您无需手动公开它们。当您将依赖项添加到 pom.xml 时,它将被启用,您可以访问 url 端点而不公开它们

可能有更好的方法来获取健康数据,但这对我有用。

@RestController
public class HealthController {
    @Autowired
    HealthContributor[] healthContributors;
    
    
    @GetMapping("/health")
    public Map<String, String> health() {
        Map<String, String> components = new HashMap<String, String>();
        for(HealthContributor healthContributor : healthContributors) {
            String componentName = healthContributor.getClass().getSimpleName().replace("HealthIndicator", "").replace("HealthCheckIndicator", "");
            String status = ((HealthIndicator)(healthContributor)).health().getStatus().toString();
            //To get details
            //Map<String,Object> details = ((HealthIndicator)(healthContributor)).health().getDetails();
            
            components.put(componentName, status);
            
        }
        return components;
    }
    
}

示例输出:

{
  "Mail":"UP",
  "Ping":"UP",
  "Camel":"UP",
  "DiskSpace":"UP"
}

要模拟 HealthContributor[],您可以尝试像下面这样使用 Mockito:

@Profile("test")
@Configuration
public class HealthContributorsMockConfig {


    @Primary
    @Bean(name = "healthContributors")
    public HealthContributor[] healthContributors() {
        HealthContributor[] healthContributors = new HealthContributor[2];
        
        HealthContributor healthContributorA = Mockito.mock(HealthIndicator.class, new Answer<Object>() {

            @Override
            public Object answer(InvocationOnMock invocation) throws Throwable {
                // TODO Auto-generated method stub
                Health health = Health.up().build();
                return health;
            }
            
        });
        
        HealthContributor healthContributorB = Mockito.mock(HealthIndicator.class, new Answer<Object>() {

            @Override
            public Object answer(InvocationOnMock invocation) throws Throwable {
                // TODO Auto-generated method stub
                Health health = Health.down().build();
                return health;
            }
            
        });
        
        healthContributors[0] = healthContributorA;
        healthContributors[1] = healthContributorB;
        return healthContributors;
        
    }
}