Включение фрагментов связанных объектов в ResourceSupports

#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, но это чистое решение для встраивания ссылок).