actuator
添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
接口暴露模式
management.contextPath=/actuator
#取消鉴权模式
management.security.enabled=false
即所有actuator相关的接口都需要添加/actuator前缀
查看暴露的接口
http://localhost:8080/actuator/mappings
打开网页后搜索: /actuator/
actuator源码解析
先看下actuator是如何实现的,以beans为例子
- /beans请求是哪个spring-bean在处理(endpointHandlerMapping)
http://localhost:8080/actuator/mappings
{
[/actuator/beans || /actuator/beans.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}: {
bean: "endpointHandlerMapping",
method: "public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()"
}
访问mappings接口,可以看到 /beans的处理类是endpointHandlerMapping
- endpointHandlerMapping对应的类是哪个
http://localhost:8080/actuator/beans
{
bean: "endpointHandlerMapping",
aliases: [ ],
scope: "singleton",
type: "org.springframework.boot.actuate.endpoint.mvc.EndpointHandlerMapping",
resource: "class path resource [org/springframework/boot/actuate/autoconfigure/EndpointWebMvcManagementContextConfiguration.class]",
dependencies: [
"mvcEndpoints"
]
}
endpointHandlerMapping对应的类为org.springframework.boot.actuate.endpoint.mvc.EndpointHandlerMapping,初始化的configuration类为org/springframework/boot/actuate/autoconfigure/EndpointWebMvcManagementContextConfiguration.class。
- EndpointWebMvcManagementContextConfiguration的初始化过程
@Bean
@ConditionalOnMissingBean
public EndpointHandlerMapping endpointHandlerMapping() {
Set<MvcEndpoint> endpoints = mvcEndpoints().getEndpoints();
CorsConfiguration corsConfiguration = getCorsConfiguration(this.corsProperties);
EndpointHandlerMapping mapping = new EndpointHandlerMapping(endpoints,
corsConfiguration);
mapping.setPrefix(this.managementServerProperties.getContextPath());
MvcEndpointSecurityInterceptor securityInterceptor = new MvcEndpointSecurityInterceptor(
this.managementServerProperties.getSecurity().isEnabled(),
this.managementServerProperties.getSecurity().getRoles());
mapping.setSecurityInterceptor(securityInterceptor);
for (EndpointHandlerMappingCustomizer customizer : this.mappingCustomizers) {
customizer.customize(mapping);
}
return mapping;
}
@Bean
@ConditionalOnMissingBean
public MvcEndpoints mvcEndpoints() {
return new MvcEndpoints();
}
EndpointHandlerMapping的父类为RequestMappingHandlerMapping,RequestMappingHandlerMapping为springmvc的核心类,主要作用是转发请求到某个具体的方法。
MvcEndpoints神奇的地方在于其初始化代码:
public void afterPropertiesSet() throws Exception {
Collection<MvcEndpoint> existing = BeanFactoryUtils
.beansOfTypeIncludingAncestors(this.applicationContext, MvcEndpoint.class)
.values();
this.endpoints.addAll(existing);
this.customTypes = findEndpointClasses(existing);
@SuppressWarnings("rawtypes")
Collection<Endpoint> delegates = BeanFactoryUtils
.beansOfTypeIncludingAncestors(this.applicationContext, Endpoint.class)
.values();
for (Endpoint<?> endpoint : delegates) {
if (isGenericEndpoint(endpoint.getClass()) && endpoint.isEnabled()) {
EndpointMvcAdapter adapter = new EndpointMvcAdapter(endpoint);
String path = determinePath(endpoint,
this.applicationContext.getEnvironment());
if (path != null) {
adapter.setPath(path);
}
this.endpoints.add(adapter);
}
}
}
主要做了两件事:
1.查找spring的beanfactory中所有的MvcEndpoint类
2.查找spring的beanfactory中所有的Endpoint类
3.如果某个MvcEndpoint的getEndpointType方法的返回结果和某个Endpoint的class相冲突,则选取MvcEndpoint
4.查找选取的结果放在MvcEndpoints的endpoints方法中。
请注意MvcEndpoints和MvcEndpoint和Endpoint区别。
- Endpoint是actuator的基本元素,一个Endpoint代表一个接口
- Endpoint可以单独使用,单独使用时MvcEndpoints会使用EndpointMvcAdapter自动将Endpoint封装为MvcEndpoint对象
- 可以自己主动将Endpoint封装为MvcEndpoint
- MvcEndpoint可以单独使用
- MvcEndpoints的作用是将Endpoint和MvcEndpoint整合提供给EndpointHandlerMapping使用
自定义Endpoint
@Bean
public Endpoint<String> testEndPoint(){
return new Endpoint<String>() {
@Override
public String getId() {
return "test";
}
@Override
public boolean isEnabled() {
return true;
}
@Override
public boolean isSensitive() {
return false;
}
@Override
public String invoke() {
return "invokeingTestEndPoint";
}
};
}
getId方法是path,这个path为:/actuator/test
自定义MvcEndpoint
@Bean
public MvcEndpoint testMvcEndpoint(){
return new MvcEndpoint() {
@Override
public String getPath() {
return "/testMvcEndpoint";
}
@Override
public boolean isSensitive() {
return false;
}
@RequestMapping("testMvcEndpoint")
@ResponseBody
public String get(){
return "invokingTestMvcEndpoint";
}
@RequestMapping("testMvcEndpoint2")
@ResponseBody
public String ge2t(){
return "invokingTestMvcEndpoint2";
}
@Override
public Class<? extends Endpoint> getEndpointType() {
return null;
}
};
}
getPath()方法为path前缀,类似于controller类上的RequestMapping,实际的path需要拼接上各个方法定义的RequestMapping。
这个bean定义了两个path:
- /actuator/testMvcEndpoint/testMvcEndpoint
- /actuator/testMvcEndpoint/testMvcEndpoint2