Что такое HATEOAS?
HATEOAS (Hypermedia as the Engine of Application State) — принцип REST, согласно которому сервер в ответе предоставляет клиенту ссылки на доступные действия и связанные ресурсы.
Аналогия из жизни: HATEOAS — как навигация в интернет-магазине. Вы открываете страницу товара, и на ней есть ссылки: «Добавить в корзину», «Похожие товары», «Отзывы». Вам не нужно знать URL-ы заранее — страница сама подсказывает, что можно сделать дальше.
Обычный ответ без HATEOAS:
Пример
{
"id": 42,
"name": "Иван",
"status": "active"
}
Ответ с HATEOAS:
Пример
{
"id": 42,
"name": "Иван",
"status": "active",
"_links": {
"self": {"href": "/api/users/42"},
"orders": {"href": "/api/users/42/orders"},
"deactivate": {"href": "/api/users/42/deactivate", "method": "POST"}
}
}
Преимущества
- Клиент не зависит от жёстко заданных URL.
- API становится самодокументируемым.
- Сервер может динамически управлять доступными действиями (например, скрывать ссылку
deactivateдля уже неактивного пользователя).
Реализация в Spring HATEOAS
@RestController
@RequestMapping("/api/users")
public class UserController {
@GetMapping("/{id}")
public EntityModel<User> getUser(@PathVariable Long id) {
User user = userService.findById(id);
EntityModel<User> model = EntityModel.of(user);
model.add(linkTo(methodOn(UserController.class).getUser(id)).withSelfRel());
model.add(linkTo(methodOn(OrderController.class).getOrdersByUser(id))
.withRel("orders"));
if ("active".equals(user.getStatus())) {
model.add(linkTo(methodOn(UserController.class).deactivateUser(id))
.withRel("deactivate"));
}
return model;
}
@GetMapping
public CollectionModel<EntityModel<User>> getAllUsers() {
List<EntityModel<User>> users = userService.findAll().stream()
.map(user -> EntityModel.of(user,
linkTo(methodOn(UserController.class).getUser(user.getId())).withSelfRel()))
.toList();
return CollectionModel.of(users,
linkTo(methodOn(UserController.class).getAllUsers()).withSelfRel());
}
}
Зависимость:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-hateoas</artifactId>
</dependency>
На практике HATEOAS используется нечасто из-за сложности реализации и того, что большинство клиентов (SPA, мобильные приложения) проще строить с заранее известными URL.
На собеседовании: нужно объяснить принцип и привести пример ответа с
_links. Бонус — упомянуть, что HATEOAS — это уровень 3 Richardson Maturity Model и что на практике он редко реализуется полностью.