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

Spring Boot Actuator:端点被调用时触发方法及同名控制器问题

关于Spring Boot Actuator readiness端点的扩展与路径冲突问题

一、如何在actuator/health/readiness被访问时执行指定方法

有几种合规且低侵入的方式扩展该端点行为,无需替换原生端点:

1. 自定义ReadinessHealthIndicator

Readiness端点的就绪状态由ReadinessHealthIndicator的实现类驱动,你可以自定义该接口的实现,在健康检查逻辑中插入自定义操作:

import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.ReadinessHealthIndicator;
import org.springframework.stereotype.Component;

@Component
public class CustomReadinessHandler implements ReadinessHealthIndicator {

    @Override
    public Health health() {
        // 执行你的自定义逻辑
        executeCustomTask();
        // 返回就绪状态(可根据实际业务返回UP/DOWN)
        return Health.up().build();
    }

    private void executeCustomTask() {
        // 示例操作:日志记录、缓存刷新、状态同步等
        System.out.println("Readiness endpoint accessed - running custom logic");
    }
}

这种方式完全融入Actuator的健康检查体系,自定义逻辑会和原生就绪检查流程同步执行。

2. 使用@EndpointWebExtension扩展原生端点

通过@EndpointWebExtension包装原生ReadinessEndpoint,在不修改原有逻辑的前提下添加前置/后置操作:

import org.springframework.boot.actuate.health.ReadinessEndpoint;
import org.springframework.boot.actuate.endpoint.web.annotation.EndpointWebExtension;
import org.springframework.stereotype.Component;

@Component
@EndpointWebExtension(endpoint = ReadinessEndpoint.class)
public class ReadinessEndpointExtension {

    private final ReadinessEndpoint originalEndpoint;

    // 注入原生端点实例
    public ReadinessEndpointExtension(ReadinessEndpoint originalEndpoint) {
        this.originalEndpoint = originalEndpoint;
    }

    public Object getReadinessStatus() {
        // 执行自定义前置逻辑
        preHandleRequest();
        // 调用原生端点逻辑获取结果
        Object result = originalEndpoint.health();
        // 执行自定义后置逻辑
        postHandleRequest();
        return result;
    }

    private void preHandleRequest() {
        // 请求处理前的操作
    }

    private void postHandleRequest() {
        // 请求处理后的操作
    }
}

3. 使用Servlet Filter拦截请求

如果需要完全独立于Actuator体系的拦截逻辑,可以编写Servlet Filter匹配目标路径:

import jakarta.servlet.*;
import jakarta.servlet.annotation.WebFilter;
import jakarta.servlet.http.HttpServletRequest;
import java.io.IOException;

@WebFilter(urlPatterns = "/actuator/health/readiness")
public class ReadinessRequestFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest httpReq = (HttpServletRequest) request;
        if ("/actuator/health/readiness".equals(httpReq.getRequestURI())) {
            // 执行自定义逻辑
            handleRequest();
        }
        // 放行请求,让原生端点继续处理
        chain.doFilter(request, response);
    }

    private void handleRequest() {
        // 你的自定义操作
    }
}

二、创建同名路径的自定义控制器会发生什么

如果直接创建映射路径为/actuator/health/readiness的@RestController,会触发请求路径冲突,具体表现:

  • 默认情况下,Actuator端点的EndpointHandlerMapping优先级高于普通控制器的RequestMappingHandlerMapping,因此原生Readiness端点会优先处理请求,你的自定义控制器逻辑不会被执行。
  • 若通过调整优先级(比如给自定义控制器添加@Order(Ordered.HIGHEST_PRECEDENCE)),你的控制器会优先处理请求,此时原生Readiness端点会被完全覆盖,失去原有就绪检查功能,这会破坏Actuator的原生行为,不推荐此做法。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 12:31:01