Spring in Action Covers Spring 5-1--11 — страница 35 из 63

   private TacoRepository tacoRepo;

   public RecentTacosController(TacoRepository tacoRepo) {

       this.tacoRepo = tacoRepo;

   }

   @GetMapping(path="/tacos/recent", produces="application/hal+json")

   public ResponseEntity> recentTacos() {

       PageRequest page = PageRequest.of(

           0, 12, Sort.by("createdAt").descending());

       List tacos = tacoRepo.findAll(page).getContent();

       List tacoResources = new TacoResourceAssembler().toResources(tacos);

       Resources recentResources = new Resources(tacoResources);

       recentResources.add(

           linkTo(methodOn(RecentTacosController.class).recentTacos())

       .withRel("recents"));

       return new ResponseEntity<>(recentResources, HttpStatus.OK);

   }

}

Несмотря на то, что @GetMapping сопоставляется с путем /tacos/recent, аннотация @RepositoryRestController на уровне класса гарантирует, что к нему будет добавлен базовый путь Spring Data REST. Метод recentTacos() будет обрабатывать запросы GET для /api/tacos/recent.

Важно отметить, что хотя @RepositoryRestController назван так же, как @RestController, он не обладает той же семантикой, что и @RestController. В частности, он не гарантирует, что значения, возвращаемые из методов-обработчиков, автоматически записываются в тело ответа. Поэтому вам нужно либо аннотировать метод с помощью @ResponseBody, либо возвращать ResponseEntity, который оборачивает данные ответа. Здесь решили вернуть ResponseEntity.

При использовании RecentTacosController в запросах на /api/tacos/recent будет возвращено до 15 самых последних созданных тако без необходимости разбивать на страницы и сортировать параметры в URL-адресе. Но он все еще не появляется в списке гиперссылок при запросе /api/tacos. Давайте исправим это.

6.3.4 Добавление пользовательских гиперссылок в endpoint Spring Data

Если endpoint недавно созданных тако не входит в число гиперссылок, возвращаемых из /api/tacos, как клиент будет знать, как получить самые последние тако? Он должен либо угадать, либо использовать параметры страницы и сортировки. В любом случае, это будет жестко закодировано в клиентском коде, что не идеально.

Однако, объявив ресурс обработчик bean-компонентов (resource processor bean), вы можете добавить ссылки в список ссылок Spring Data REST. Spring Data HATEOAS предлагает ResourceProcessor, интерфейс для управления ресурсами до их возврата через API. Для ваших целей вам нужна реализация ResourceProcessor, которая добавляет recents ссылку на любой ресурс типа PagedResources> (тип, возвращаемый для /api/tacos endpoint). В следующем листинге показан метод объявления bean-компонента, определяющий ResourceProcessor.

Листинг 6.8. Добавление пользовательских ссылок в REST Spring Data endpoint

@Bean

public ResourceProcessor>>

       tacoProcessor(EntityLinks links) {

   return new ResourceProcessor>>() {

       @Override

       public PagedResources> process(

               PagedResources> resource) {

           resource.add(

               links.linkFor(Taco.class)

               .slash("recent")

               .withRel("recents"));

           return resource;

       }

   };

}

ResourceProcessor, показанный в листинге 6.8, определяется как анонимный внутренний класс и объявляется как bean-компонент, создаваемый в контексте приложения Spring. Spring HATEOAS обнаружит этот bean-компонент (как и любые другие bean-компоненты типа ResourceProcessor) автоматически и применяет их к соответствующим ресурсам. В этом случае, если из контроллера возвращается PagedResources>, он получит ссылку на самые последние созданные тако. Это включает в себя ответ на запросы для /api/tacos.

Итог

REST endpoint могут быть созданы с помощью Spring MVC с контроллерами, которые следуют той же модели программирования, что и контроллеры, ориентированные на браузер.

Методы обработчика контроллера могут быть аннотированы с помощью @ResponseBody или возвращать объекты ResponseEntity для обхода модели, просмотра и записи данных непосредственно в тело ответа.

Аннотация @RestController упрощает контроллеры REST, устраняя необходимость использования @ResponseBody в методах-обработчиках.

Spring HATEOAS обеспечивает включение гиперссылок ресурсов, возвращаемых контроллерами Spring MVC.

Репозитории Spring Data могут автоматически отображаться как API REST с помощью Spring Data REST.

Spring in Action Covers Spring 5.0 перевод на русский. Глава 7

 REST сервисы

 В этой главе рассматриваются

Использование RestTemplate для REST API

Навигация по API гипермедиа с помощью Traverson

Вы когда-нибудь ходили в кино и были единственный человек в театре? Это, безусловно, замечательный опыт, который по сути является приватным просмотром фильма. Вы можете выбрать любое место, которое захотите, поговорить с персонажами на экране и, возможно, даже открыть свой телефон и написать об этом в Твиттере, чтобы никто не рассердился за то, что нарушил их просмотр фильма. И самое приятное то, что никто больше не портит фильм для вас!

Это случалось не часто со мной. Но когда это произошло, я подумал, что бы случилось, если бы я не появился. Они все еще показали бы фильм? Герой все еще спас бы день? Должны ли сотрудники театра убирать театр после окончания фильма?

Фильм без аудитории - это как API без клиента. Он готов принимать и предоставлять данные, но если API никогда не вызывается, действительно ли это API? Как и кот Шредингера, мы не можем знать, активен ли API или возвращает ответы HTTP 404, пока мы не отправим к нему запрос.

В предыдущей главе мы сосредоточились на определении REST endpoint, которые могут использоваться некоторыми клиентами, внешними по отношению к вашему приложению. Хотя движущей силой для разработки такого API было одностраничное приложение Angular, которое служило веб-сайтом Taco Cloud, реальность такова, что клиент может быть любым приложением на любом языке - даже другим приложением Java.

Приложения Spring нередко предоставляют API и отправляют запросы к API другого приложения. Фактически, это становится распространенным в мире микросервисов. Поэтому стоит потратить немного времени на изучение того, как использовать Spring для взаимодействия с REST API.

Приложение Spring может использовать REST API с

RestTemplate - простой, синхронный REST-клиент, предоставляемый ядром Spring Framework.

Traverson - синхронный REST-клиент с поддержкой гиперссылок, предоставляемый Spring HATEOAS. Вдохновленный из одноименной библиотеки JavaScript.

WebClient - реактивный, асинхронный клиент REST, представленный в Spring 5.

Я отложу обсуждение WebClient до тех пор, пока мы не рассмотрим реактивную веб-инфраструктуру Spring в главе 11. Сейчас мы сосредоточимся на двух других REST клиентах, начиная с RestTemplate.

7.1 Использование REST endpoint с RestTemplate

Есть много, что входит во взаимодействие с ресурсом REST с точки зрения клиента-в основном скука и шаблонность. Работая с низкоуровневыми библиотеками HTTP, клиент должен создать экземпляр клиента и объект запроса, выполнить запрос, интерпретировать ответ, сопоставить ответ с объектами домена и обработать любые исключения, которые могут быть брошены по пути. И все это шаблонное повторяется, независимо от того, какой HTTP-запрос отправляется.

Чтобы избежать такого стандартного кода, Spring предоставляет RestTemplate. Так же, как JDBCTemplate обрабатывает уродливые части работы с JDBC, RestTemplate освобождает вас от скуки при использовании ресурсов REST.

RestTemplate предоставляет 41 метод для взаимодействия с ресурсами REST. Вместо того чтобы изучать все методы, которые он предлагает, проще рассмотреть только дюжину уникальных операций, каждая из которых перегружена, и в конечном итоге составляет полный набор в 41 метод. Эти 12 операций описаны в таблице 7.1.

Таблица 7.1 RestTemplate определяет 12 уникальных операций, каждая из которых перегружена, обеспечивая в общей сложности 41 метод.

Метод - Описание

delete(...) - Выполняет HTTP-запрос на удаление ресурса по указанному URL-адресу

exchange(...) - Выполняет указанный метод HTTP для URL, возвращая ResponseEntity, содержащий объект, сопоставленный с телом ответа

execute(...) - Выполняет указанный метод HTTP для URL, возвращая объект, сопоставленный с телом ответа

getForEntity(...) - Отправляет HTTP-запрос GET, возвращая ResponseEntity, содержащий объект, сопоставленный с телом ответа.

getForObject(...) - Отправляет HTTP-запрос GET, возвращая объект, сопоставленный с телом ответа.

headForHeaders(...) - Отправляет запрос HTTP HEAD, возвращая заголовки HTTP для указанного URL ресурса

optionsForAllow(...) - Отправляет запрос HTTP OPTIONS, возвращая заголовок Allow для указанного URL

patchForObject(...) - Отправляет запрос HTTP PATCH, возвращая полученный объект, сопоставленный с телом ответа.

postForEntity(...) - помещает POST данные в URL, возвращая ResponseEntity, содержащий объект, сопоставленный с телом ответа

postForLocation(...) - помещает POST данные в URL, возвращая URL вновь созданного ресурса

postForObject(...) - помещает POST данные в URL, возвращая объект, сопоставленный с телом ответа

put(...) - Помещает PUT данные ресурса в указанный URL

За исключением TRACE, RestTemplate имеет по крайней мере один метод для каждого из стандартных методов HTTP. Кроме того, execute () и exchange () предоставляют низкоуровневые методы общего назначения для отправки запросов любым методом HTTP.

Большинство методов в таблице 7.1 перегружены в три формы методов: