Spring Boot Actuator:自定义端点,其顶部具有MVC层

logo-spring-io

Spring Boot Actuator端点允许您监视应用程序并与之交互。 Spring Boot包含许多内置端点,您也可以添加自己的端点。
添加自定义端点就像创建一个从org.springframework.boot.actuate.endpoint.AbstractEndpoint扩展的类一样容易。 但是Spring Boot Actuator也提供了用MVC层装饰端点的可能性。

端点端点

有许多内置端点,但是缺少一个端点是公开所有端点的端点。 默认情况下,终结点通过HTTP公开,其中终结点的ID映射到URL。 在下面的示例中,创建了具有ID endpoints的新端点,并且其invoke方法返回所有可用端点:

@Component
public class EndpointsEndpoint extends AbstractEndpoint<List<Endpoint>> {

    private List<Endpoint> endpoints;

    @Autowired
    public EndpointsEndpoint(List<Endpoint> endpoints) {
        super("endpoints");
        this.endpoints = endpoints;
    }


    @Override
    public List<Endpoint> invoke() {
        return endpoints;
    }
}

@Component注释将端点添加到现有端点列表中。 /endpoints URL现在将公开所有具有idenabledsensitive属性的端点:

[
    {
        "id": "trace",
        "sensitive": true,
        "enabled": true
    },
    {
        "id": "configprops",
        "sensitive": true,
        "enabled": true
    }
]

新端点还将作为MBean在JMX服务器上注册: [org.springframework.boot:type=Endpoint,name=endpointsEndpoint]

MVC端点

Spring Boot Actuator提供了一项附加功能,该功能是通过org.springframework.boot.actuate.endpoint.mvc.MvcEndpoint接口在终结点之上的MVC层的策略MvcEndpoint可以使用@RequestMapping和其他Spring MVC功能。

请注意, EndpointsEndpoint返回所有可用的端点。 但是,如果用户可以通过其enabled sensitive属性过滤端点,那就太好了。

MvcEndpoint必须使用有效的@RequestMapping方法创建一个新的MvcEndpoint 。 请注意,不允许在类级别使用@Controller@RequestMapping ,因此使用@Component来使端点可用:

@Component
public class EndpointsMvcEndpoint extends EndpointMvcAdapter {

    private final EndpointsEndpoint delegate;

    @Autowired
    public EndpointsMvcEndpoint(EndpointsEndpoint delegate) {
        super(delegate);
        this.delegate = delegate;
    }

    @RequestMapping(value = "/filter", method = RequestMethod.GET)
    @ResponseBody
    public Set<Endpoint> filter(@RequestParam(required = false) Boolean enabled,
                          @RequestParam(required = false) Boolean sensitive) {

    }
}

新方法将在/endpoints/filter URL下可用。 该方法的实现很简单:它获取可选的enabled sensitive参数,并过滤委托的invoke方法结果:

@RequestMapping(value = "/filter", method = RequestMethod.GET)
@ResponseBody
public Set<Endpoint> filter(@RequestParam(required = false) Boolean enabled,
                            @RequestParam(required = false) Boolean sensitive) { 

    Predicate<Endpoint> isEnabled =
        endpoint -> matches(endpoint::isEnabled, ofNullable(enabled));

    Predicate<Endpoint> isSensitive =
        endpoint -> matches(endpoint::isSensitive, ofNullable(sensitive));

    return this.delegate.invoke().stream()
                 .filter(isEnabled.and(isSensitive))
                 .collect(toSet());
}

private <T> boolean matches(Supplier<T> supplier, Optional<T> value) {
    return !value.isPresent() || supplier.get().equals(value.get());
}

用法示例:

  • 所有启用的端点: /endpoints/filter?enabled=true
  • 所有敏感端点: /endpoints/filter?sensitive=true
  • 所有已启用和敏感的端点: /endpoints/filter?enabled=true&sensitive=true

使端点可发现

EndpointsMvcEndpoint使用MVC功能,但仍返回纯终结点对象。 如果Spring HATEOAS在类路径中,则可以扩展filter方法以返回org.springframework.hateoas.Resource以及指向端点的链接:

class EndpointResource extends ResourceSupport {

    private final String managementContextPath;
    private final Endpoint endpoint;

    EndpointResource(String managementContextPath, Endpoint endpoint) {
        this.managementContextPath = managementContextPath;
        this.endpoint = endpoint;

        if (endpoint.isEnabled()) {

            UriComponentsBuilder path = fromCurrentServletMapping()
                    .path(this.managementContextPath)
                    .pathSegment(endpoint.getId());

            this.add(new Link(path.build().toUriString(), endpoint.getId()));    
        }
    }

    public Endpoint getEndpoint() {
        return endpoint;
    }
}

EndpointResource将包含指向每个已启用端点的链接。 请注意,构造函数采用managamentContextPath变量。 该变量包含一个Spring Boot Actuator management.contextPath属性值。 用于设置管理端点的前缀。

EndpointsMvcEndpoint类中所需的更改:

@Component
public class EndpointsMvcEndpoint extends EndpointMvcAdapter {

    @Value("${management.context-path:/}") // default to '/'
    private String managementContextPath;

    @RequestMapping(value = "/filter", method = RequestMethod.GET)
    @ResponseBody
    public Set<Endpoint> filter(@RequestParam(required = false) Boolean enabled,
                          @RequestParam(required = false) Boolean sensitive) {

        // predicates declarations

        return this.delegate.invoke().stream()
                .filter(isEnabled.and(isSensitive))
                .map(e -> new EndpointResource(managementContextPath, e))
                .collect(toSet());
    }
}

我的Chrome浏览器中安装了JSON Formatter的结果:

act-jsonviewer

但是,为什么不直接从EndpointsEnpoint返回资源呢? 在EndpointResource了从HttpServletRequest中提取信息的UriComponentsBuilder ,它将在调用MBean的getData操作时引发异常(除非不需要JMX)。

管理端点状态

端点不仅可以用于监视,还可以用于管理。 已经有内置的ShutdownEndpoint (默认情况下禁用),可以关闭ApplicationContext 。 在以下(假设的)示例中,用户可以更改所选端点的状态:

@RequestMapping(value = "/{endpointId}/state")
@ResponseBody
public EndpointResource enable(@PathVariable String endpointId) {
    Optional<Endpoint> endpointOptional = this.delegate.invoke().stream()
            .filter(e -> e.getId().equals(endpointId))
            .findFirst();
    if (!endpointOptional.isPresent()) {
        throw new RuntimeException("Endpoint not found: " + endpointId);
    }

    Endpoint endpoint = endpointOptional.get();        
    ((AbstractEndpoint) endpoint).setEnabled(!endpoint.isEnabled());

    return new EndpointResource(managementContextPath, endpoint);
}

呼叫disabled端点用户时,应收到以下响应:

{
    "message": "This endpoint is disabled"
}

更进一步

下一步可能是为自定义(或现有)端点添加用户界面,但这不在本文讨论范围之内。 如果您有兴趣,可以看看Spring Boot Admin ,它是Spring Boot应用程序的简单管理界面。

摘要

Spring Boot Actuator 提供了Spring Boot的所有生产就绪功能以及许多内置端点。 只需花费很少的精力,即可添加自定义端点,以扩展应用程序的监视和管理功能。

参考文献

翻译自: https://www.javacodegeeks.com/2014/10/spring-boot-actuator-custom-endpoint-with-mvc-layer-on-top-of-it.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值