You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何配置Actuator Health根据请求返回不同详细程度的响应内容

完全可以实现,不需要改动你现有自定义HealthIndicator的核心逻辑,以下是两种可直接落地的实现方案,按需选择即可。

方案一:基于Actuator原生权限配置(推荐,零业务代码修改)

Spring Boot Actuator原生支持根据访问授权状态返回不同粒度的健康信息,仅需调整配置、按需适配权限规则即可实现需求:

  1. 添加应用配置(以YAML格式为例,Properties格式可自行转换配置键):
management:
  endpoint:
    health:
      # 仅授权用户可查看健康检查的详情字段
      show-details: when-authorized
      # 所有访问者都可查看聚合接口下的组件列表,列表中仅展示组件状态,不携带详情
      show-components: always
      # 配置查看详情所需的角色,可根据自身权限体系调整
      roles: HEALTH_VIEWER
  1. 如果你使用Spring Security做访问控制,添加如下路径权限规则:
@Bean
public SecurityFilterChain healthSecurityRule(HttpSecurity http) throws Exception {
    http
      .securityMatcher("/actuator/health/**")
      .authorizeHttpRequests(auth -> auth
        // 根聚合健康接口允许所有访问,仅返回全局状态+各组件状态,无详情
        .requestMatchers("/actuator/health").permitAll()
        // 单组件健康接口需要持有HEALTH_VIEWER角色才能访问,访问时返回全量详情
        .requestMatchers("/actuator/health/*").hasRole("HEALTH_VIEWER")
      )
      .httpBasic(Customizer.withDefaults());
    return http.build();
}

配置生效后的效果:

  • 匿名访问http://localhost:8080/actuator/health时,所有组件(包括你的my-custom-component)只会返回status字段,不会携带details块,完全满足聚合接口精简返回、减少非必要信息暴露的需求
  • 持有HEALTH_VIEWER角色的访问者请求http://localhost:8080/actuator/health/my-custom-component时,会返回包含detail-a、detail-b的全量详情,和你预期的单组件返回结果完全一致
  • 你当前编写的health()方法逻辑不需要做任何修改
方案二:无权限控制的返回过滤(适合不需要鉴权的场景)

如果你不需要做权限控制,要求所有访问者访问聚合接口都看不到敏感详情、访问单组件接口都能看到全量详情,可以通过自定义健康响应映射器实现,直接在聚合视图下过滤不需要返回的字段:

  1. 先修改配置,保证详情能被正常加载:
management:
  endpoint:
    health:
      show-details: always
      show-components: always
  1. 添加自定义响应映射器,聚合视图下移除组件的敏感详情:
import org.springframework.boot.actuate.endpoint.SecurityContext;
import org.springframework.boot.actuate.health.*;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import jakarta.servlet.http.HttpServletRequest;
import java.util.Map;

@Component
public class TrimmedHealthResponseMapper extends HealthWebEndpointResponseMapper {

    public TrimmedHealthResponseMapper(HealthContributorRegistry contributorRegistry,
                                       HealthEndpointGroups groups) {
        super(contributorRegistry, groups);
    }

    @Override
    public WebEndpointResponse<HealthComponent> map(Health health, SecurityContext securityContext) {
        WebEndpointResponse<HealthComponent> defaultResponse = super.map(health, securityContext);
        ServletRequestAttributes requestAttrs = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
        HttpServletRequest request = requestAttrs.getRequest();
        
        // 仅在访问根聚合健康接口时做字段裁剪
        if (request.getRequestURI().endsWith("/actuator/health")) {
            Health aggregateHealth = (Health) defaultResponse.getBody();
            if (aggregateHealth != null && aggregateHealth.getComponents() != null) {
                Map<String, HealthComponent> components = aggregateHealth.getComponents();
                components.replaceAll((componentName, component) -> {
                    if (component instanceof Health) {
                        Health componentHealth = (Health) component;
                        // 全量隐藏详情用这行即可
                        return Health.status(componentHealth.getStatus()).build();
                        
                        // 只隐藏部分字段(比如删detail-b留detail-a)就替换为下面的逻辑
                        // Health.Builder builder = Health.status(componentHealth.getStatus());
                        // componentHealth.getDetails().forEach((key, value) -> {
                        //     if (!"detail-b".equals(key)) {
                        //         builder.withDetail(key, value);
                        //     }
                        // });
                        // return builder.build();
                    }
                    return component;
                });
            }
        }
        return defaultResponse;
    }
}

提示:Spring Boot 2.x版本使用该代码时,需要把导入包中的jakarta.servlet替换为javax.servlet。

内容的提问来源于stack exchange,提问作者Sam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 18:12:58