Мой первый контакт с декларативным REST-клиентом был с Feign, который тогда был частью стека Spring Cloud Netflix, давно переименованного в Spring Cloud OpenFeign. До этого всегда было утомительно писать эти HTTP-вызовы через RestTemplate, каждый раз похожий код. С помощью Feign вы только что определили интерфейс с контрактами методов, отражающими конечную точку службы, а некоторая магия прокси в фоновом режиме сгенерировала готовый к использованию HTTP-клиент. Удивительный!

Теперь, с выпуском Spring Framework 6, такой декларативный REST-клиент стал встроенной частью базовой веб-инфраструктуры: поздоровайтесь с Интерфейсом HTTP!

Все необходимые компоненты находятся в модуле spring-web, который является транзитивной зависимостью для модулей spring-boot-starter-web или spring-boot-starter-webflux. Однако на практике всегда требуется зависимость WebFlux из-за HttpServiceProxyFactory для создания клиентов. Если у вас есть обходной путь для этого, просто дайте мне знать в комментариях :)

Внутри новые декларативные HTTP-клиенты используют WebClient, который является рекомендуемым клиентом для HTTP-запросов, начиная с Spring 5. Но, как вы увидите, в целом с ним будет не так много точек соприкосновения.

Пример HTTP-клиента

Во-первых, давайте определим клиента для нашего небольшого приложения:

Как вы уже видите, никакой реализации нет, только объявление интерфейса с аннотированными полями и методами. Для полей аннотации типа @RequestParam, @PathVariable или @RequestBody должны быть хорошо известны. Это то же самое, что мы используем в контроллере Spring REST. Что касается методов, у нас есть @...Exchange методов для наиболее распространенных HTTP-глаголов (получить, поставить, опубликовать, удалить и исправить). Мы также можем использовать общую аннотацию @HttpExchange на уровне метода, но это не приносит никакой дополнительной пользы. Однако на уровне типа мы можем использовать аннотацию @HttpExchange для определения общих атрибутов, таких как URL-адрес или типы мультимедиа для нашего клиента.

CharacterClient можно автоматически связать, как и любой другой компонент, и использовать аналогично клиенту Feign:

Это уже выглядит очень просто и, прежде всего, удобно в использовании. Как уже упоминалось, в реализации используется файл WebClient. Однако, к счастью, все внутренности WebClient абстрагированы. Если мы сравним это с прямыми обращениями к нему, мы сразу увидим, сколько шаблонного кода мы можем избежать:

Довольно аккуратно! Зачем вам реализовывать что-то самостоятельно, если вы можете сгенерировать это так же хорошо?

HttpServiceProxyFactory для генерации клиентов

Если вы следовали коду до этого момента, вы уже обнаружили, что наш декларативный HTTP-клиент CharacterClient не может быть автоматически подключен без дополнительной работы. Не хватает одного: как на самом деле связать WebClient с нашим декларативным HTTP-клиентом?

Клиент должен быть сгенерирован HttpServiceProxyFactory и вручную привязан к экземпляру WebClient, который вы определяете. В нашем примере класс конфигурации выглядит так:

В настоящее время, в отличие от OpenFeign, клиент еще не поставляется с помощью автоматической настройки в настройке Spring Boot (в этом отношении, пожалуйста, отследите Поддержка декларативных HTTP-клиентов # 31337). Поэтому мы сами создаем WebClient и создаем из него декларативный HTTP-клиент, используя метод createClient из HttpServiceProxyFactory. Это какой-то шаблонный код, но я совершенно уверен, что ребята из Spring Boot придумают хорошее решение для дальнейшего упрощения. До этого момента вам потребуется такое определение bean-компонента для каждого декларативного HTTP-клиента в вашем приложении.

Остается сказать еще одно: просто попробуйте новый декларативный HTTP-клиент сами! По сравнению с использованием WebClient напрямую, большая часть шаблонного кода абстрагируется. Другое преимущество заключается в том, что нам не нужна дополнительная зависимость для HTTP-клиента, поскольку он транзитивно входит в состав spring-web в Spring Framework 6 или Spring Boot 3.

Спасибо за прочтение! Не стесняйтесь комментировать или сообщение мне, когда у вас есть вопросы или предложения. Вас могут заинтересовать другие посты, опубликованные в Блоге Digital Frontiers, анонсированные в нашем аккаунте Twitter.