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

如何在Spring Boot中默认启用自定义Actuator端点?

问题:Spring Boot Actuator自定义端点默认暴露的优雅实现方式

我开发了一个小型库,可为Actuator添加自定义端点jwks,希望默认暴露该端点。Spring Boot 2.7.4默认仅暴露health端点。目前我通过注册EnvironmentPostProcessor来修改management.endpoints.web.exposure.include属性,但这种操作PropertySource的方式略显脆弱。另外还有其他库需要默认暴露各自的端点(如metrics、prometheus等),当前实现代码如下:

public class PoCEnvironmentPostProcessor implements EnvironmentPostProcessor {
    private static final String PROPERTY_NAME = "management.endpoints.web.exposure.include";

    @Override
    public void postProcessEnvironment(
        ConfigurableEnvironment environment, 
        SpringApplication application
    ) {
        var propertySources = environment.getPropertySources();
        propertySources.stream()
            .filter(it -> it.containsProperty(PROPERTY_NAME))
            .findFirst().ifPresentOrElse(source -> {
                var property = source.getProperty(PROPERTY_NAME);
                var pocSource = new MapPropertySource(PROPERTY_NAME, Map.of(PROPERTY_NAME, property + ",jwks"));
                // Add the new property with more priority
                propertySources.addBefore(source.getName(), pocSource);
            }, () -> {
                var pocSource = new MapPropertySource(PROPERTY_NAME, Map.of(PROPERTY_NAME, "health,jwks"));
                propertySources.addLast(pocSource);
            });
    }
}

请问是否存在无需过多操作PropertySource,即可默认暴露端点并支持多库添加不同端点的方法?


解决方案

方法1:通过EndpointWebExtension控制端点暴露(推荐)

Spring Boot Actuator提供了端点扩展机制,每个库可以独立控制自身端点的默认暴露状态,无需修改全局配置属性。为自定义端点实现EndpointWebExtension并重写isExposed()方法:

import org.springframework.boot.actuate.endpoint.web.WebEndpointResponse;
import org.springframework.boot.actuate.endpoint.web.annotation.EndpointWebExtension;
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;

@Endpoint(id = "jwks")
public class JwksEndpoint {
    @ReadOperation
    public String getJwks() {
        // 端点业务逻辑
        return "jwks content";
    }
}

@EndpointWebExtension(endpoint = JwksEndpoint.class)
public class JwksEndpointWebExtension {
    private final JwksEndpoint delegate;

    public JwksEndpointWebExtension(JwksEndpoint delegate) {
        this.delegate = delegate;
    }

    @ReadOperation
    public WebEndpointResponse<String> getJwks() {
        return new WebEndpointResponse<>(delegate.getJwks(), 200);
    }

    // 核心:设置该端点默认通过Web暴露
    @Override
    public boolean isExposed() {
        return true;
    }
}

这种方式完全隔离了不同库的端点配置,不会出现属性覆盖或冲突问题。

方法2:自动配置中直接修改WebEndpointProperties

利用Spring Boot的自动配置和属性绑定机制,直接操作Actuator的端点配置属性,比手动修改PropertySource更安全可靠:

import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableConfigurationProperties(WebEndpointProperties.class)
public class JwksEndpointAutoConfiguration {

    public JwksEndpointAutoConfiguration(WebEndpointProperties webEndpointProperties) {
        // 将jwks添加到默认暴露列表,Spring会自动处理属性合并(用户配置优先级更高)
        var includeList = webEndpointProperties.getExposure().getInclude();
        if (!includeList.contains("jwks")) {
            includeList.add("jwks");
        }
    }

    @Bean
    @ConditionalOnMissingBean
    public JwksEndpoint jwksEndpoint() {
        return new JwksEndpoint();
    }
}

多个库可以通过各自的自动配置类向includeList中添加端点,Spring会自动完成列表合并,不会互相覆盖。

方法3:自定义配置属性增强灵活性

如果需要允许用户关闭端点的默认暴露,可以自定义配置属性,再在自动配置中根据属性值决定是否添加端点:

import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableConfigurationProperties({JwksEndpointProperties.class, WebEndpointProperties.class})
public class JwksAutoConfiguration {

    public JwksAutoConfiguration(JwksEndpointProperties jwksProps, WebEndpointProperties webEndpointProps) {
        // 根据自定义属性决定是否默认暴露
        if (jwksProps.isExposeByDefault()) {
            var includeList = webEndpointProps.getExposure().getInclude();
            if (!includeList.contains("jwks")) {
                includeList.add("jwks");
            }
        }
    }
}

@ConfigurationProperties(prefix = "management.endpoint.jwks")
public class JwksEndpointProperties {
    // 默认开启暴露
    private boolean exposeByDefault = true;

    // getter、setter
    public boolean isExposeByDefault() {
        return exposeByDefault;
    }

    public void setExposeByDefault(boolean exposeByDefault) {
        this.exposeByDefault = exposeByDefault;
    }
}

用户可通过management.endpoint.jwks.expose-by-default=false手动关闭该端点的默认暴露,兼顾默认行为和灵活性。


内容的提问来源于stack exchange,提问作者Víctor Herraiz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 10:35:29