Открыть сервис

Spring HATEOAS

Spring HATEOAS — это библиотека для платформы Java Spring, предназначенная для упрощения создания гипермедийных REST-веб-сервисов, соответствующих принципам HATEOAS (Hypermedia as the Engine of Application State). Она предоставляет набор абстракций и утилит для добавления в ответы API ссылок (hypermedia links), которые направляют клиента по возможным состояниям приложения, делая API самодокументируемым и менее зависимым от жёсткой логики на стороне клиента.

История

Библиотека Spring HATEOAS была создана как часть экосистемы Spring для решения проблемы, связанной с отсутствием стандартизированной поддержки гипермедиа в ранних версиях Spring MVC. Первоначально разработанная как отдельный проект, она была включена в состав Spring Framework в качестве модуля. Основной вклад в её развитие внесла компания Pivotal Software (ныне часть VMware). Первый стабильный релиз состоялся в 2013 году. С тех пор библиотека активно развивается, поддерживая различные форматы представления гипермедиа, такие как HAL (Hypertext Application Language), JSON:API и UBER.

Основные концепции

Гипермедиа и HATEOAS

HATEOAS — это ограничение архитектурного стиля REST, согласно которому сервер в каждом ответе должен предоставлять клиенту не только запрошенные данные, но и набор ссылок на возможные дальнейшие действия. Это позволяет клиенту динамически навигировать по API, не зная заранее его структуры. Spring HATEOAS реализует эту концепцию, предоставляя классы для представления ссылок и ресурсов.

Ключевые классы и интерфейсы

  • Link — основной класс, представляющий одну гиперссылку. Содержит атрибуты rel (отношение, например, «self», «next», «delete») и href (URL). Также может содержать необязательные атрибуты, такие как type, hreflang и title.
  • EntityModel — обёртка для любого объекта, добавляющая к нему коллекцию ссылок. Используется для представления одного ресурса.
  • CollectionModel — обёртка для коллекции объектов, также с возможностью добавления ссылок на уровне всей коллекции.
  • PagedModel — специализированная обёртка для постраничных ответов, содержащая информацию о номере страницы, размере, общем количестве элементов и ссылки на первую, последнюю, следующую и предыдущую страницы.
  • RepresentationModel — базовый класс для всех моделей, поддерживающих ссылки. От него наследуются EntityModel, CollectionModel и PagedModel.
  • WebMvcLinkBuilder — утилитный класс для построения ссылок на основе методов контроллеров Spring MVC. Позволяет избежать жёсткого кодирования URL, генерируя их из аннотаций @RequestMapping, @GetMapping и т.д.

Применение

Добавление ссылок в ответы

Основной способ использования Spring HATEOAS — это создание контроллеров, которые возвращают не простые объекты, а их обёртки с ссылками. Например, для ресурса «Книга» можно добавить ссылку на самого себя (self) и на связанные ресурсы, такие как «Автор» или «Рецензии».

Пример типичного контроллера: ```java @RestController @RequestMapping("/books") public class BookController {

@GetMapping("/{id}") public EntityModel<Book> getBook(@PathVariable Long id) { Book book = service.findById(id); EntityModel<Book> model = EntityModel.of(book); model.add(linkTo(methodOn(BookController.class).getBook(id)).withSelfRel()); model.add(linkTo(methodOn(AuthorController.class).getAuthor(book.getAuthorId())).withRel("author")); return model; } } ```

Построение ссылок с помощью WebMvcLinkBuilder

WebMvcLinkBuilder использует рефлексию для анализа методов контроллера и автоматического генерирования URL. Это снижает вероятность ошибок при изменении маршрутов. Метод linkTo(methodOn(Controller.class).method()) создаёт ссылку, соответствующую определённому методу контроллера.

Обработка коллекций и постраничных ответов

Для коллекций ресурсов используется CollectionModel, а для постраничных — PagedModel. В последнем случае библиотека автоматически добавляет ссылки на первую, последнюю, следующую и предыдущую страницы на основе переданных параметров пагинации.

Пример: ``java @GetMapping public PagedModel<EntityModel<Book>> getAllBooks(Pageable pageable) { Page<Book> page = service.findAll(pageable); PagedModel<EntityModel<Book>> pagedModel = PagedModel.of( page.getContent().stream().map(book -> EntityModel.of(book)).collect(Collectors.toList()), new PagedModel.PageMetadata(page.getSize(), page.getNumber(), page.getTotalElements()) ); pagedModel.add(linkTo(methodOn(BookController.class).getAllBooks(pageable)).withSelfRel()); return pagedModel; } ``

Форматы представления

Spring HATEOAS поддерживает несколько форматов сериализации гипермедиа, которые выбираются на основе заголовка Accept запроса или конфигурации приложения.

HAL (Hypertext Application Language)

Формат HAL (Hypertext Application Language) — наиболее распространённый и поддерживаемый по умолчанию. В этом формате ссылки выносятся в отдельное поле _links, а вложенные ресурсы — в поле _embedded. HAL-ответы легко читаемы и широко используются в промышленных REST API.

JSON:API

JSON:API — это спецификация, описывающая, как клиенты должны запрашивать и изменять ресурсы. Spring HATEOAS поддерживает её через отдельный модуль. В этом формате ссылки могут быть представлены как в корневом объекте, так и в атрибутах ресурсов.

UBER

UBER (Uniform Basis for Exchanging Representations) — менее распространённый формат, ориентированный на простоту и единообразие. Он также поддерживается библиотекой, но используется реже.

Интеграция с другими компонентами Spring

Spring MVC

Spring HATEOAS тесно интегрируется с Spring MVC. Контроллеры, возвращающие EntityModel или CollectionModel, автоматически сериализуются в нужный формат с помощью HttpMessageConverter, который регистрируется при добавлении зависимости в проект.

Spring Data REST

Spring Data REST автоматически добавляет поддержку HATEOAS в репозитории Spring Data. При создании REST-эндпоинтов для репозиториев библиотека генерирует ссылки на связанные ресурсы, коллекции и операции поиска.

Spring WebFlux

Для реактивных приложений на основе Spring WebFlux существует отдельная версия библиотеки — spring-hateoas-webflux. Она предоставляет аналогичные возможности, но адаптированные для работы с реактивными типами, такими как Mono и Flux.

Критика и ограничения

Несмотря на полезность, Spring HATEOAS имеет ряд недостатков. Основной критикой является усложнение кода контроллеров: добавление ссылок требует дополнительных вызовов и обёрток, что может снизить читаемость. Кроме того, библиотека не всегда оптимально работает с большими коллекциями, так как генерация ссылок для каждого элемента может быть ресурсоёмкой. Некоторые разработчики также отмечают, что HATEOAS в целом редко применяется на практике, так как большинство REST API не следуют этому принципу строго, предпочитая заранее документированные маршруты.

Примеры использования

Источники

  • Официальная документация Spring HATEOAS (spring.io/projects/spring-hateoas)
  • «Spring in Action» by Craig Walls, 6th edition, 2022
  • «RESTful Web Services» by Leonard Richardson and Sam Ruby, 2007
  • Документация Spring Framework по REST-сервисам (docs.spring.io/spring-framework/reference/web/webmvc/mvc-controller/ann-rest.html)

BFOmetr — база данных и аналитика по компаниям России.

На главную BFOmetr →