Spring Boot 2.7如何获取暴露的Actuator端点列表用于过滤器免过滤?
问题:Spring Boot 2.7中如何动态获取暴露的Actuator端点路径列表?
我有一个运行在不同环境的Spring Boot 2.7应用,不同环境会暴露不同的Actuator端点(开发环境暴露全部端点)。Actuator的基础路径已修改为:
management.endpoints.web.base-path=/
例如,health端点的访问路径为:
localhost:8080/health
我实现了一个OncePerRequestFilter,需要不对Actuator相关路径执行过滤逻辑。但开发环境中management.endpoints.web.exposure.include的值为*,无法直接用于shouldNotFilter方法的校验。我需要获取实际的端点路径列表(如[/info,/health,...]),路径不含前缀/也可,但最好包含。请问有没有无需硬编码列表就能获取暴露的Actuator端点列表的方案?
解决方案
可以通过Spring Boot提供的内置组件动态获取暴露的Actuator端点路径,无需硬编码,具体实现如下:
1. 注入核心依赖
在你的OncePerRequestFilter实现类中,注入EndpointMapping和WebEndpointProperties两个组件,前者持有所有已注册的Actuator端点信息,后者对应Actuator的Web配置项:
import org.springframework.boot.actuate.endpoint.web.EndpointMapping; import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties; import org.springframework.web.filter.OncePerRequestFilter; import java.util.Set; import java.util.Arrays; import java.util.stream.Collectors; // 你的过滤器类 public class CustomFilter extends OncePerRequestFilter { private final EndpointMapping endpointMapping; private final WebEndpointProperties webEndpointProperties; // 构造方法注入 public CustomFilter(EndpointMapping endpointMapping, WebEndpointProperties webEndpointProperties) { this.endpointMapping = endpointMapping; this.webEndpointProperties = webEndpointProperties; } }
2. 动态生成暴露的端点路径列表
编写方法根据配置规则筛选出实际暴露的端点,并拼接成完整路径:
private Set<String> getExposedActuatorPaths() { // 获取所有已注册的Actuator端点ID Set<String> allRegisteredEndpointIds = endpointMapping.getEndpoints().keySet(); // 获取配置中暴露规则(可能是*或具体逗号分隔的列表) String exposureRule = webEndpointProperties.getExposure().getInclude(); Set<String> exposedEndpointIds; if ("*".equals(exposureRule)) { // 通配符规则下,排除默认不暴露的shutdown端点 exposedEndpointIds = allRegisteredEndpointIds.stream() .filter(id -> !"shutdown".equals(id)) .collect(Collectors.toSet()); } else { // 按配置的具体列表筛选有效端点 exposedEndpointIds = Arrays.stream(exposureRule.split(",")) .map(String::trim) .filter(allRegisteredEndpointIds::contains) .collect(Collectors.toSet()); } // 拼接完整路径(因为base-path设为/,直接加前缀/即可) return exposedEndpointIds.stream() .map(id -> "/" + id) .collect(Collectors.toSet()); }
3. 在过滤逻辑中校验路径
在shouldNotFilter方法里判断当前请求是否属于Actuator路径:
@Override protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException { String requestPath = request.getRequestURI(); Set<String> exposedActuatorPaths = getExposedActuatorPaths(); return exposedActuatorPaths.contains(requestPath); }
注意:如果后续修改
management.endpoints.web.base-path,可以通过endpointMapping.getPath()获取基础路径,再和端点ID拼接,保证路径的正确性。
内容的提问来源于stack exchange,提问作者Ebad
相关产品推荐
相关产品推荐

