spring boot Actuator之自定义Endpoint

2023年8月2日13:07:17

本文基于spring boot 2.2.0 release版本。

在上一篇文章《spring boot Actuator原理详解之启动》详细介绍了在web环境下,Actuator是如何启动的,这里对流程做一个简单的总结:

  1. 扫描所有@Endpoint注解的类,这些类都是Endpoint;
  2. 使用过滤器对Endpoint对象进行过滤,没有被过滤掉的才可以进入下一步;
  3. 读取Endpoint对象的每个方法,判断是否有@ReadOperation、@WriteOperation、@DeleteOperation三个注解,如果有,则针对每个被注解的方法创建操作对象Operation;
  4. 根据操作对象、Endpoint对象、Endpoint名创建为RequestMappingInfo,并将其注册到spring mvc中;
  5. 注册成功之后,Endpoint对象便可以对外提供服务。

明白了上面整个启动流程之后,我们也可以编写一个自定义的Endpoint。
自定义Endpoint的关键点:

  1. 类上必须有注解@Endpoint,注解必须设置id值,否则启动抛出如下异常:Caused by: java.lang.IllegalStateException: No @Endpoint id attribute specified for XXXClass
  2. 必须指定方法注解为下面三个中一个:@ReadOperation、@WriteOperation、@DeleteOperation
  3. 注解@Selector可以指定路径参数,比如/actuator/caches/{cache}花括号里面的内容是路径参数,我们可以在方法入参上添加@Selector来指定路径参数,比如public String counters(@Selector int value)
  4. 默认Endpoint对象的方法都是以json格式返回客户端,可以通过设置@ReadOperation、@WriteOperation、@DeleteOperation的produces属性指定其他格式。

下面给出一个自定义Endpoint的例子:

/**
 * 统计方法该Endpoint对象的次数
 */
@Component
@Endpoint(id="counter")
public class Counter  {
    private AtomicInteger cnt=new AtomicInteger(0);
    @ReadOperation
    public int counter() {
        return cnt.getAndAdd(1);
    }
    @ReadOperation
    public int counters(@Selector int value) {
        return cnt.getAndAdd(value);
    }
}

上面这个类只是一个示例,并没有实际意义。运行起来后,访问http://localhost:8079/actuator/counter,每次访问都会返回一个比之前大1的数字。

我们还可以使用注解@EndpointWebExtension扩展已有的Endpoint。
下面是spring提供的对EnvironmentEndpoint的扩展:

@EndpointWebExtension(endpoint = EnvironmentEndpoint.class)
public class EnvironmentEndpointWebExtension {
	private final EnvironmentEndpoint delegate;
	public EnvironmentEndpointWebExtension(EnvironmentEndpoint delegate) {
		this.delegate = delegate;
	}

	@ReadOperation
	public WebEndpointResponse<EnvironmentEntryDescriptor> environmentEntry(@Selector String toMatch) {
		EnvironmentEntryDescriptor descriptor = this.delegate.environmentEntry(toMatch);
		return new WebEndpointResponse<>(descriptor, getStatus(descriptor));
	}

	private int getStatus(EnvironmentEntryDescriptor descriptor) {
		if (descriptor.getProperty() == null) {
			return WebEndpointResponse.STATUS_NOT_FOUND;
		}
		return WebEndpointResponse.STATUS_OK;
	}
}

就web环境下来说,如果扩展类的方法有与原类相同的http请求路径,那么扩展类会替换掉原来的方法,也就是说,访问该路径时,不会访问到原类的方法,而是访问到扩展类。

  • 作者:龚厂长
  • 原文链接:https://blog.csdn.net/weixin_38308374/article/details/114422004
    更新时间:2023年8月2日13:07:17 ,共 2025 字。