#java #spring #rest #spring-hateoas
#java #spring #остальное #spring-ненависть к
Вопрос:
Я пытаюсь создать единый фасад REST, который возвращает ResourceSupport
классы Spring HATEOAS, представляющие ресурсы моего домена, используя @ResponseBody
для JSON и Thymeleaf для HTML. У меня есть Painting
класс, который выглядит следующим образом:
public class PaintingResource extends ResourceSupport {
private String title;
private Integer year;
// artist is a Link rel="artist"
}
Для рендеринга как в формате JSON, так и в формате HTML Painting
мне нужно иметь доступный фрагмент информации об исполнителе (например, имя и URL для изображения профиля), но нет смысла встраивать весь ArtistResource
класс и Link
не позволяет прикреплять какие-либо дополнительные метаданные.
Должен ли я создать вложенный Artist
класс для хранения только фрагмента и создать все это в ассемблере ресурсов, или есть более идиоматичный способ привязки фрагмента к PaintingResource
? Если я использую вложенный класс, должен ли я просто вставлять значения name и URL и использовать отдельный Link
объект для указания на страницу исполнителя?
Ответ №1:
Предложение HAL (проект спецификации здесь) описывает решение, которое, я думаю, вы ищете — «встроенные» ресурсы внутри других ресурсов, в «зарезервированном» _embedded
свойстве. Следуя этой спецификации, вы можете включать полные или частичные фрагменты других ресурсов в другой.
Spring HATEOAS поддерживает HAL, добавив в вашу конфигурацию следующее, я не уверен во всем, что он делает для вас, но он будет выводить ваши ResourceSupport
ссылки как _links
свойство.
@EnableHypermediaSupport(type = EnableHypermediaSupport.HypermediaType.HAL)
Похоже, это не делает ничего конкретного для встроенных ресурсов (пока), но это достаточно просто реализовать с помощью свойства
private Map<String, List<ResourceSummary>> _embedded;
в данном случае в вашем PaintingResource
классе. Вероятно, вы захотите добавить сюда какую-то сводную / фрагментарную версию вашего ArtistResource
, но это позволит вам включить собственные ссылки и набор свойств, которые вы хотите предоставить. Итак, в вашем случае
private Map<String, ArtistSummaryResource> _embedded;
Обратите внимание, что в соответствии с предложением _embedded
значениями могут быть либо объекты, либо список объектов. Мы решили всегда реализовывать список объектов для уменьшения сложности в клиенте.
Я ожидаю, что в итоге вы получите что-то вроде следующего:
{
"title": "Painting title",
"year": 2014,
"_links": {
"self": {
"href": "http://your.server.com/path/to/painting"
}
},
"_embedded": {
"artist": {
"name": "J Smith",
"_links": {
"self": {
"href": "http://your.server.com/path/to/artist"
}
}
}
}
}
Комментарии:
1. Я прочитал о поддержке Spring HATEOAS HAL несколько лет назад, и в то время HAL выглядел как потенциально многообещающая, напоминающая XML, но потенциально неуклюжая попытка нормализовать семантику элементов ссылок. Я знаю, что включение шаблонов URI значительно улучшило ситуацию, и использование
_embedded
поля выглядит разумным подходом (я склонялся к прямому включению поля в класс snippet, но это чистое решение для встраивания ссылок).