Конечные точки Spring Boot Actuator позволяют вам контролировать и взаимодействовать с вашим приложением. Spring Boot включает в себя ряд встроенных конечных точек, и вы также можете добавить свои собственные.
Добавить пользовательские конечные точки так же просто, как создать класс из org.springframework.boot.actuate.endpoint.AbstractEndpoint
. Но Spring Boot Actuator также предлагает возможность декорировать конечные точки слоем MVC.
Конечная точка
Существует много встроенных конечных точек, но одна из них отсутствует — это конечная точка, которая предоставляет все конечные точки. По умолчанию конечные точки предоставляются через HTTP, где идентификатор конечной точки сопоставляется с URL-адресом. В приведенном ниже примере создается новая конечная точка с идентификаторами endpoints
а ее метод invoke
возвращает все доступные конечные точки:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
|
@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
добавляет конечную точку в список существующих конечных точек. URL /endpoints
теперь будет отображать все конечные точки с id
, enabled
и sensitive
свойствами:
01
02
03
04
05
06
07
08
09
10
11
12
|
[ { "id" : "trace" , "sensitive" : true , "enabled" : true }, { "id" : "configprops" , "sensitive" : true , "enabled" : true } ] |
Новая конечная точка также будет зарегистрирована на сервере JMX как MBean: [org.springframework.boot:type=Endpoint,name=endpointsEndpoint]
Конечная точка MVC
Spring Boot Actuator предлагает дополнительную функцию, которая представляет собой стратегию для слоя MVC поверх org.springframework.boot.actuate.endpoint.mvc.MvcEndpoint
точки через интерфейсы org.springframework.boot.actuate.endpoint.mvc.MvcEndpoint
. MvcEndpoint
может использовать @RequestMapping
и другие функции Spring MVC.
Обратите внимание, что EndpointsEndpoint
возвращает все доступные конечные точки. Но было бы неплохо, если бы пользователь мог фильтровать конечные точки по enabled
и sensitive
свойствам.
Для этого необходимо создать новую MvcEndpoint
с допустимым методом @RequestMapping
. Обратите внимание, что использование @Controller
и @RequestMapping
на уровне класса недопустимо, поэтому @Component
использовался, чтобы сделать конечную точку доступной:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
|
@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
делегата:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
|
@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 находится в classpath, метод filter
может быть расширен для возврата org.springframework.hateoas.Resource
со ссылками на конечные точки:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
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.Bot Actuator management.contextPath
. Используется для установки префикса для конечной точки управления.
Изменения, требуемые в классе EndpointsMvcEndpoint
:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
|
@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
использовался UriComponentsBuilder
который извлекает информацию из HttpServletRequest
который будет вызывать исключение при вызове операции getData
MBean (если JMX не требуется).
Управление состоянием конечной точки
Конечные точки могут использоваться не только для мониторинга, но и для управления. Уже есть встроенная ShutdownEndpoint
(по умолчанию отключена), которая позволяет завершать ApplicationContext
. В приведенном ниже (гипотетическом) примере пользователь может изменить состояние выбранной конечной точки:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
|
@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
конечной точки пользователь должен получить следующий ответ:
1
2
3
|
{ "message" : "This endpoint is disabled" } |
Идти дальше
Следующим шагом может быть добавление пользовательского интерфейса для пользовательских (или существующих) конечных точек, но это не рассматривается в этой статье. Если вам интересно, вы можете взглянуть на Spring Boot Admin, который является простым интерфейсом администратора для приложений Spring Boot.
Резюме
Spring Boot Actuator предоставляет все готовые к работе функции Spring Boot с рядом встроенных конечных точек. С минимальными усилиями можно добавить пользовательские конечные точки, чтобы расширить возможности мониторинга и управления приложением.
использованная литература
Ссылка: | Spring Boot Actuator: пользовательская конечная точка со слоем MVC поверх нее от нашего партнера по JCG Рафаля Боровца в блоге Codeleak.pl . |