全部学科
Python全栈
python
NodeJS全栈
nodejs
小程序首页
📅 2026-05-18 8 分钟 ✍️ juanwangdev

Spring Boot Actuator端点扩展

Actuator 支持自定义端点暴露业务监控数据。

端点配置

YAML
management:
  endpoints:
    web:
      exposure:
        include: health,info,custom
      base-path: /actuator
  endpoint:
    custom:
      enabled: true

自定义端点方式

@Endpoint注解

Java
@Component
@Endpoint(id = "custom")
public class CustomEndpoint {

    @ReadOperation
    public Map<String, Object> info() {
        Map<String, Object> info = new HashMap<>();
        info.put("app", "my-application");
        info.put("version", "1.0.0");
        info.put("status", "running");
        return info;
    }

    @ReadOperation
    public Map<String, Object> detail(@Selector String name) {
        Map<String, Object> detail = new HashMap<>();
        detail.put("name", name);
        detail.put("value", System.getProperty(name));
        return detail;
    }

    @WriteOperation
    public void update(@Selector String name, String value) {
        System.setProperty(name, value);
    }

    @DeleteOperation
    public void delete(@Selector String name) {
        System.clearProperty(name);
    }
}

访问方式:

  • GET /actuator/custom
  • GET /actuator/custom/{name}
  • POST /actuator/custom/{name}?value=xxx
  • DELETE /actuator/custom/{name}

@WebEndpoint注解

Java
@Component
@WebEndpoint(id = "app-status")
public class AppStatusEndpoint {

    @ReadOperation
    public AppStatus status() {
        return AppStatus.builder()
            .uptime(getUptime())
            .memory(getMemoryInfo())
            .threads(getThreadInfo())
            .build();
    }

    @ReadOperation
    public AppStatus detail(@Selector String component) {
        switch (component) {
            case "memory":
                return AppStatus.memoryOnly(getMemoryInfo());
            case "threads":
                return AppStatus.threadsOnly(getThreadInfo());
            default:
                throw new IllegalArgumentException("Unknown component: " + component);
        }
    }
}

@RestControllerEndpoint注解

Java
@Component
@RestControllerEndpoint(id = "app-info")
public class AppInfoEndpoint {

    @GetMapping
    public Map<String, Object> info() {
        Map<String, Object> info = new HashMap<>();
        info.put("name", "my-app");
        info.put("version", "1.0.0");
        info.put("java", System.getProperty("java.version"));
        return info;
    }

    @GetMapping("/env")
    public Map<String, String> env() {
        return System.getenv();
    }

    @GetMapping("/props")
    public Properties props() {
        return System.getProperties();
    }
}

业务监控端点

Java
@Component
@Endpoint(id = "business-metrics")
public class BusinessMetricsEndpoint {

    @Autowired
    private OrderService orderService;

    @Autowired
    private UserService userService;

    @ReadOperation
    public Map<String, Object> metrics() {
        Map<String, Object> metrics = new HashMap<>();

        metrics.put("order", OrderMetrics.builder()
            .totalCount(orderService.getTotalCount())
            .todayCount(orderService.getTodayCount())
            .pendingCount(orderService.getPendingCount())
            .build());

        metrics.put("user", UserMetrics.builder()
            .totalCount(userService.getTotalCount())
            .activeCount(userService.getActiveCount())
            .newToday(userService.getNewToday())
            .build());

        return metrics;
    }
}

健康端点扩展

Java
@Component
@Endpoint(id = "app-health")
public class AppHealthEndpoint {

    private final List<HealthChecker> checkers;

    public AppHealthEndpoint(List<HealthChecker> checkers) {
        this.checkers = checkers;
    }

    @ReadOperation
    public HealthResponse health() {
        List<HealthDetail> details = checkers.stream()
            .map(this::check)
            .collect(Collectors.toList());

        boolean healthy = details.stream()
            .allMatch(HealthDetail::isHealthy);

        return HealthResponse.builder()
            .status(healthy ? "UP" : "DOWN")
            .checks(details)
            .timestamp(LocalDateTime.now())
            .build();
    }

    private HealthDetail check(HealthChecker checker) {
        try {
            boolean healthy = checker.check();
            return HealthDetail.builder()
                .name(checker.getName())
                .healthy(healthy)
                .message(healthy ? "OK" : "FAILED")
                .build();
        } catch (Exception e) {
            return HealthDetail.builder()
                .name(checker.getName())
                .healthy(false)
                .message(e.getMessage())
                .build();
        }
    }
}

操作类型

注解HTTP方法说明
@ReadOperationGET读取操作
@WriteOperationPOST写入操作
@DeleteOperationDELETE删除操作

参数注解

注解说明
@Selector路径参数
@Nullable可选参数
Java
@ReadOperation
public Map<String, Object> query(
        @Selector String id,
        @Nullable String filter) {
    // 实现逻辑
}

端点安全

Java
@Configuration
public class ActuatorSecurityConfig {

    @Bean
    public SecurityFilterChain actuatorSecurity(HttpSecurity http) throws Exception {
        http.requestMatcher(EndpointRequest.toAnyEndpoint())
            .authorizeRequests(requests ->
                requests.anyRequest().hasRole("ACTUATOR"))
            .httpBasic();
        return http.build();
    }
}

生产环境务必配置端点访问权限,避免敏感信息泄露。

要点总结

  • @Endpoint用于标准端点
  • @RestControllerEndpoint提供完整MVC能力
  • @ReadOperation/@WriteOperation/@DeleteOperation定义操作
  • @Selector提取路径参数

📝 发现内容有误?点击此处直接编辑

← 上一篇 Spring Boot @Enable注解与@Import原理
下一篇 → Spring Boot BeanPostProcessor扩展
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库