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现在将公开所有具有id
, enabled
和sensitive
属性的端点:
[
{
"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的结果:
但是,为什么不直接从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的所有生产就绪功能以及许多内置端点。 只需花费很少的精力,即可添加自定义端点,以扩展应用程序的监视和管理功能。