В новом переводе от команды Spring АйО команда Spring делает важное объявление — RestTemplate уходит в прошлое. С выходом Spring Framework 7.0 разработчики официально заявляют о плане поэтапного прекращения поддержки одного из самых популярных HTTP-клиентов в экосистеме. Его место занимает RestClient
, современный fluent-клиент с расширенными возможностями: API-версионирование, гибкая конфигурация конвертеров, группы HTTP-интерфейсов и новый тестовый клиент RestTestClient
.
Кроме того, в Spring Boot 4.0 появятся отдельные стартеры для каждого типа клиента, а RestClient
теперь можно удобно переиспользовать с уже существующей инфраструктурой RestTemplate
.
Это новая запись в блоге из серии "Путь к GA", на этот раз посвящённая новым возможностям наших HTTP-клиентов. Также это подходящий момент, чтобы оценить текущее состояние HTTP-клиентов в Spring, и мы воспользуемся этой возможностью, чтобы сделать важное объявление: мы официально объявляем о прекращении поддержки RestTemplate.
Комментарий от эксперта Spring АйО Михаила Поливахи
Тут у тех людей, кто пишет с использованием Spring Framework хотя бы лет 5 возникнет ряд вопросов. Как минимум потому, что с выходом Spring Framework 5 и с выходом WebClient
, вроде как, RestTemplate
же задепрекейтили? На самом деле, нет. Всё было сложнее.
Тут очень зпутанная история с RestTemplate
/RestClient
/WebClient
и т.д. Её в одну сноску уместить не получится. На подкасте сообщества отдельно посвятим время обсуждению этой истории
Новые функции RestClient
RestClient
был представлен в Spring Framework 6.1 и продолжил развиваться в линейке 6.x. В предстоящей мажорной версии 7.0 мы сохраняем темп, добавляя ряд новых возможностей.
Версионирование API
Аннотация @Controller
в Spring теперь поддерживает концепцию версионирования API, что позволяет удобнее реализовывать разные поколения вашего REST API в рамках одного приложения. Эта функция также поддерживается и на стороне клиента — с помощью ApiVersionInserter
. Например, вы можете вставлять информацию о версии API в пользовательский HTTP-заголовок. Это настраивается при создании клиента:
RestClient customClient = RestClient.builder()
.baseUrl("https://spring.io/api")
.defaultVersion("1.2")
.apiVersionInserter(ApiVersionInserter.fromHeader("API-Version").build())
.build();
Spring поддерживает вставку и разбор версий API из HTTP-заголовков, медиатипов, путей запросов, параметров запроса или с помощью любой пользовательской реализации.
HttpMessageConverters
Мы пересмотрели подход к настройке конвертеров сообщений в приложениях Spring. Новый API HttpMessageConverters предлагает специализированный интерфейс и значительно упрощает настройку пользовательских конвертеров — как для замены существующих, так и для добавления собственных. В этом примере мы автоматически определяем конвертеры на основе classpath и переопределяем только поддержку JSON, используя пользовательский Jackson JsonMapper:
JsonMapper jsonMapper = JsonMapper.builder()
.findAndAddModules()
.enable(SerializationFeature.INDENT_OUTPUT)
.defaultDateFormat(new SimpleDateFormat("yyyy-MM-dd"))
.build();
RestClient restClient = RestClient.builder()
.configureMessageConverters(client -> {
client.registerDefaults().jsonMessageConverter(new JacksonJsonHttpMessageConverter(jsonMapper));
})
.baseUrl("https://spring.io/api")
.build();
Ранее Spring Boot предоставлял аналогичную возможность через свой собственный тип HttpMessageConverters
; новая реализация во фреймворке призвана заменить его в приложениях Spring Boot. В WebFlux уже доступен реактивный эквивалент — CodecConfigurer
.
Группы HTTP-интерфейсов
Когда приложению требуется настроить множество клиентов HTTP-интерфейсов, конфигурация может становиться повторяющейся и трудноуправляемой. В этом релизе появилась концепция групп — мощный способ объявлять и настраивать несколько клиентов одновременно, позволяя им использовать общий RestClient, если это оправдано.
В следующем примере определяется группа stackexchange для работы с API StackOverflow и ServerFault. Другая группа — github — будет использовать один и тот же HTTP-клиент для всех интерфейсов, определённых в общем базовом пакете:
@Configuration
@ImportHttpServices(group = "stackexchange", types = {StackOverflowClient.class, ServerFaultClient.class})
@ImportHttpServices(group = "github", basePackageClasses = GitHubProjects.class)
public class ClientConfig {
}
Подробнее об этой возможности можно узнать в блоге "HTTP Service Client Enhancements".
RestTestClient
Spring Framework 7.0 включает новый клиент для тестирования серверных приложений — RestTestClient. Он позволяет выполнять интеграционные тесты с реальными HTTP запросами, что означает полное прохождение сетевого стека и преобразование сообщений. RestTestClient
также поддерживает тестирование отдельных Controller-ов или RouterFunction-ов с использованием мок-запросов и ответов — аналогично MockMvc. И в случае работы как с реальными HTTP запросами, так и при использовании моков используется единый API в рамках RestTestClient
.
Эта фича стала ответом на частые запросы сообщества, поскольку в реактивном стеке эту задачу выполнял WebTestClient
, а эквивалента для RestClient
не было.
Новая фича предоставляет больше возможностей по сравнению с TestRestTemplate
из Spring Boot и может рассматриваться как его замена, поэтому команда рассматривает возможность его удаления в будущем.
Новые стартеры Spring Boot
Сообщество не раз высказывало обеспокоенность по поводу того, как HTTP-клиенты распределены по артефактам Spring. RestClient
и RestTemplate
находятся в org.springframework:spring-web
, а WebClient
— в org.springframework:spring-webflux
. Ни один из них не поставляется в виде отдельного, специализированного артефакта для клиентов.
Такая структура упаковки затрудняла понимание намерений разработчиков со стороны Spring Boot. Следует ли только запускать веб-сервер, или же стоит автоматически настраивать HTTP-клиент — или же, нужно и то, и другое? Эта проблема теперь решена одной из ключевых функций в грядущем релизе Spring Boot: весь код Spring Boot был модульно переработан, и автоконфигурации теперь разделены на отдельные артефакты.
С выходом Spring Boot 4.0 приложения могут использовать org.springframework.boot:spring-boot-starter-webclient
или org.springframework.boot:spring-boot-starter-restclient
, чтобы явно указать необходимость подключения HTTP-клиента.
И это ещё не всё!
Мы также реализовали множество мелких улучшений, таких как встроенная поддержка буферизации, поддержка хинтов Jackson-у на стороне клиента, а также интеграция Spring Security с HTTP-интерфейс-клиентами.
Ограничения RestTemplate
Если ваше приложение использует RestTemplate
, вы быстро заметите, что большинство новых функций, описанных выше, для него недоступны. В этом разделе мы объясним, почему мы не смогли реализовать эти возможности для RestTemplate
.
RestTemplate был выпущен вместе с Spring Framework 3.0 — более 15 лет назад, и с тех пор в экосистеме Java многое изменилось.
Наша основная мотивация, лежащая в основе создания RestTemplate
и всех других HTTP-клиентов Spring, на протяжении всех этих лет оставалась неизменной: предоставить сообществу высокоуровневый HTTP-клиент, который хорошо интегрируется с библиотеками Spring. Конвертация тела сообщений, обработка ошибок, механизм перехвата и безопасность — всё это функции, которые можно использовать с привычной моделью программирования Spring. Поддерживаются различные библиотеки HTTP-клиентов, но мы не раскрываем низкоуровневые детали взаимодействия или специфические настройки: вы выбираете то, что подходит под ваши требования, но общий опыт разработки при этом не должен меняться.
Такой подход долгое время отлично работал для RestTemplate
, но в нём начали проявляться ограничения.
API в "шаблонном" стиле работает хорошо в рамках ограниченного набора задач, но становится проблемным по мере добавления новых функций. Это распространённый шаблон в Spring Framework, начиная с JdbcTemplate
и JmsTemplate
, которые появились раньше RestTemplate
. В этом стиле имена методов быстро перенасыщаются, а использование перегрузки методов усугубляет ситуацию. Javadoc RestTemplate демонстрирует множество перегруженных методов — и то же самое видит разработчик при автодополнении в IDE. Каждое добавление новой функциональности может ухудшить developer experience. Например, поддержка версионирования API в RestTemplate
потребовала бы новых конструкторов, что только добавило бы путаницы в API. В результате мы не смогли реализовать эту возможность для RestTemplate
.
Асинхронные вызовы поддерживались через AsyncRestTemplate
, но и там были проблемы. Из-за шаблонного стиля API перегрузка методов становилась ещё большей проблемой. Использование ListenableFuture
от Spring тогда было необходимым выбором, но он плохо подходил для композиции параллельных вызовов и эффективного управления HTTP-ресурсами. Сегодня в платформе Java доступны более современные и мощные альтернативы.
Комментарий от эксперта Spring АйО Михаила Поливахи
ListenableFuture
deprecated начиная с Spring Framework 6. Он создавался давно, ещё до Java 8, как некоторый аналог тому, что сейчас может делать CompletableFuture
, а именно позволять чейнить коллбеки. С приходом Java 8, ListenableFuture
утратил свою актуальность, и сейчас является устаревшим. Не используйте его.
Потоковые HTTP-протоколы
Потоковые протоколы HTTP, такие как Server-Sent Events, стали более востребованными. Для RestTemplate такая задача особенно сложна: типичный подход — получить и обработать весь ответ целиком, а затем, если нужно, закрыть соединение. Однако для стриминга необходимо держать соединение открытым на протяжении всей передачи и выполнять конвертацию сообщений поэлементно.
Несмотря на эти ограничения, RestTemplate остаётся очень популярным в сообществе Spring. Тем не менее, шаблонный API достиг предела своих возможностей и потребовал кардинального переосмысления. Команда Spring смогла решить эту проблему в Spring Framework 5, представив новый HTTP-клиент — WebClient
.
WebClient и реактивное программирование
Во время поддержки Spring Framework 4.x мы всё чаще слышали от сообщества Java и Spring о необходимости асинхронных, неблокирующих веб-стеков, позволяющих эффективно контролировать latency. Появлялись новые веб-фреймворки, многие из которых использовали функциональный стиль для композиции асинхронных операций. Стандартизировались Reactive Streams, появились новые протоколы, такие как RSocket. Несмотря на порог вхождения, многие команды выбирали этот подход, чтобы преодолеть ограничения традиционных асинхронных примитивов Java и работы с пулом потоков.
С выпуском Spring Framework 5.0 команда Spring представила полноценный реактивный стек, основанный на Reactive Streams и проекте Reactor. С самого начала мы чётко дали понять, что традиционный стек на базе сервлетов никуда не исчезает, и что переход на реактивный подход следует рассматривать только при наличии реальных проблем на этапе runtime-а. Ключевыми задачами были управление latency и композиция асинхронных операций — а не достижение максимальной производительности любой ценой.
Новый взгляд на клиентскую сторону HTTP
Для HTTP-клиента это стало возможностью пересмотреть прежние архитектурные решения и применить накопленный опыт.
Вместо "шаблонного" API мы выбрали fluent API для нового HTTP-клиента — WebClient. Это был первый в новой серии fluent-клиентов, за которым последовали JdbcClient
и JmsClient
. Fluent API значительно сокращает количество методов в типах. Опыт работы в IDE при автодополнении становится более удобным, поскольку в каждом звене цепочки методов отображаются только доступные в данный момент опции, а не весь массив возможных методов сразу.
Асинхронная, неблокирующая инфраструктура это нативная фича Reactor-а. Стриминг данных — естественная концепция в Reactive Streams. Однако стриминг запросов и ответов меняет подход к конвертации сообщений из массива байт и обратно. Вместо обработки всего потока целиком, данные читаются и записываются как байтовые буферы, содержащие часть сообщения. Для этого используется контракт DataBuffer (вместо обычного byte[]), что позволяет использовать буферизацию и повторное использование памяти более эффективно.
Комментарий от эксперта Spring АйО Михаила Поливахи
DataBuffer
это просто абстракция в Spring Framework над обычными Java-овыми ByteBuffer
-ами. Апи байт буферов в Java имеет ряд проблем, о чём говорил сам Брайен Гоетц на Java One, и часто фреймворки пишут свои абстракции над ним. Например, ByteBuf
в netty или вот DataBuffer
в Spring Framework.
Таким образом, WebClient стал достойной альтернативой RestTemplate
. Точки расширения и стиль API соответствуют современным требованиям. Если в приложении важны высокая степень параллелизации или стриминг HTTP-запросов, WebClient
— вполне себе жизнеспособное решение. Мы не ожидали, что ради этого приложения начнут полностью переписывать на WebFlux. Именно поэтому мы предусмотрели, чтобы контроллеры Spring MVC могли работать с реактивными типами как с обычными асинхронными вызовами. При необходимости можно также вызвать block() для возвращения в синхронный мир.
Именно поэтому мы в своё время заявили, что RestTemplate
считается функционально завершённым (feature complete): из-за его архитектурных ограничений мы больше не могли добавлять в него новые функции. Тогда же мы объявили об устаревании AsyncRestTemplate
, так как WebClient
был гораздо более продвинутым решением для асинхронной и неблокирующей работы, а также для построения потоковых конвейеров. В целом, WebClient
оказался лучшим выбором по всем параметрам, и мы надеялись, что сообщество со временем придёт к единому решению.
Представляем RestClient
С переходом на Java 17 в качестве базовой версии в Spring Framework 6.0 и предстоящей поддержкой виртуальных потоков в Java 21 перед нами открылась возможность по-новому взглянуть на RestTemplate
. Мы применили опыт, накопленный при разработке WebClient, чтобы устранить ограничения шаблонного API и создать современный, fluent API. При этом мы решили использовать уже существующую HTTP-инфраструктуру от RestTemplate
и разместили новый клиент в том же пакете. Это упрощает переход: вы можете создать экземпляр RestClient
, используя уже имеющийся RestTemplate
. Мы также опубликовали отдельное руководство по миграции, чтобы помочь разработчикам в этом процессе.
Оглядываясь назад, можно сказать, что выбор в пользу императивного, блокирующего API был верным: Structured Concurrency в Java открывает возможности для асинхронной композиции в RestClient
— и это не требует дополнительных изменений в самом клиенте. Мы по-прежнему изучаем вопрос поддержки стриминга (подробнее об этом ниже).
За последние релизы мы наблюдаем быстрое распространение RestClient
в сообществе, но до настоящего момента не меняли политику поддержки RestTemplate
.
Будущее HTTP-клиентов в Spring
На сегодняшний день между RestTemplate
и RestClient
существует значительный разрыв, который невозможно устранить из-за ограничений шаблонного API. Продолжение поддержки RestTemplate
ставит часть сообщества в невыгодное положение. Поэтому мы считаем, что настало время пересмотреть расстановку сил среди HTTP-клиентов, и вот наш текущий план:
Spring Framework 7.0 (ноябрь 2025): объявить о намерении прекратить поддержку RestTemplate в этом блоге, в руководствах по обновлению и официальной документации.
Spring Framework 7.1 (предварительно — ноябрь 2026): официально пометить RestTemplate аннотацией @Deprecated и объявить о его удалении в будущем.
Spring Framework 8.0 (дата пока не определена): полностью удалить
RestTemplate
.
При текущем темпе выпусков, поддержка RestTemplate
в рамках Open Source будет сохраняться как минимум до 2029 года. Мы убеждены, что переход на RestClient
(с использованием той же HTTP-инфраструктуры) — лучшее долгосрочное решение. Если в вашем проекте используются собственные RequestFactory или интерцепторы (ClientInterceptors), их можно повторно использовать с RestClient
. Обновление может происходить поэтапно: сначала — обёртка над существующим RestTemplate
, затем — переработка общей конфигурации.
Таким образом, теперь у нас есть два основных клиента:
RestClient
— для традиционного (императивного) стекаWebClient
— для реактивного стека
Оба активно поддерживаются командой Spring. Выбор стал значительно проще: используйте RestClient
в большинстве случаев, либо WebClient
, если вашему приложению необходимы Reactive API или поддержка стриминга.
О стриминге
Возвращаясь к вопросу стриминга: мы по-прежнему исследуем возможные пути реализации полноценной поддержки стриминга в RestClient
. В текущей версии платформы Java нет чёткого решения, которое бы естественным образом сочеталось с виртуальными потоками и Structured Concurrency. Мы находимся в диалоге с командой Java Platform и представителями индустрии, чтобы найти оптимальное решение.

Присоединяйтесь к русскоязычному сообществу разработчиков на Spring Boot в телеграм — Spring АйО, чтобы быть в курсе последних новостей из мира разработки на Spring Boot и всего, что с ним связано.
spirit1984
Я правильно понимаю, что RestClient - это если пишешь на виртуальных потоках, и не хочешь все переписывать в асинхронном стиле, и под капотом он с ними нормально работает, а не создает thread pinning и прочие прелести? А как он ограничивается в таком случае - открывает соединения для каждого запроса со своим виртуальным потоком?