26 февраля 2026
Тэги: Java, json, rest, Spring Boot, yaml.
По мере развития вашего приложения REST API может претерпевать значительные изменения. И при каждом изменении требуется сохранять обратную совместимость. Мы не можем просто так удалять эндпоинты, входные параметры этих эндпоинтов или часть возвращаемых полей, т.к. они могут использоваться на клиентской стороне. Безопасным можно считать только добавление новых полей или новых эндпоинтов, т.к. их ещё пока никто не использует.
Но как быть, если нам всё-таки требуется сделать несовместимые изменения в REST API? Тут нам на помощь придёт версионирование эндпоинтов.
Предположим, у нас был эндпоинт, который возвращает строку приветствия для пользователя. Этот эндпоинт изначально не принимал никаких параметров.
Обратите внимание, что для аннотации @GetMapping (а также для @PostMapping, @PutMapping и т.д.) появился новый параметр version. Это произвольная строка, в которой мы можем сразу указать версию. Хоть этот параметр и является опциональным, лучше его заполнять для каждого эндпоинта (или на уровне всего контроллера), предусмотрев дальнейшую возможность изменения API.
Затем мы решили сделать более персонализированное приветствие, обращаясь к пользователю по имени. Для этого нам нужно, чтобы имя приходило как параметр запроса. Это изменение несовместимо со старым эндпоинтом, поэтому делаем вторую версию:
Интересно, что обе версии эндпоинта (т.е. маппинг на один и тот же урл) мы можем держать рядом в одном контроллере. До появления Spring Boot 4 это было невозможно.
Теперь осталось решить, как мы будем передавать номер версии в запросе. Есть несколько способов сделать это. Рассмотрим наиболее популярные:
Схема такая: клиент отправляет кастомный http-заголовок (например, X-API-Version), указывая в нём номер версии и в зависимости от этого заголовка на серверной стороне вызывается нужный эндпоинт.
Добавим в файл application.yaml параметр spring.mvc.apiversion.use.header и в качестве значение укажем имя этого заголовка:
Теперь вызываем первую версию эндпоинта:
Ответ сервера:
Вызываем вторую версию эндпоинта с указанием имени пользователя:
В ответе увидим имя из запроса:
Теперь мы можем держать рядом разные версии этого эндпоинта.
Альтернативой передаче номера версии в заголовке является передача номера версии как одного из параметров запроса.
Добавим в application.yaml параметр spring.mvc.apiversion.use.query-parameter и в качестве значения укажем желаемое название этого параметра:
Теперь мы можем вот так выполнять запрос к первому («старому») эндпоинту:
А вот так к «новому»:
Однако мне эта схема не нравится, т.к. происходит смешивание мета-данных запроса (version) и параметров бизнес-логики (name).
Третий способ - это указание номера версии в сегменте урла. То есть когда все эндпоинты первой версии начинаются с /api/v1, а второго - с /api/v2. Spring позволяет поддержать и такую схему.
Немного модифицируем @RequestMapping контроллера, добавив второй сегмент с произвольным именем, чтобы он стал общим для всех эндпоинтов:
Также добавим в файл application.yaml параметр spring.mvc.apiversion.use.path-segment. В качестве значения указываем порядковый номер сегмента, в котором указывается версия (начиная с 0). В данном случае у нас версия во втором сегменте, поэтому пишем 1.
Теперь делаем запрос к первому эндпоинту:
А вот так ко второму:
Мы рассмотрели новый механизм версионирования REST API, который предлагает Spring Boot 4. Он позволяет держать разные версии эндпоинта рядом, что облегает поддержку обратной совместимости. В зависимости от той схемы версионирования, которая принята у вас на проекте, вы можете передавать номер версии в http-заголовке, в параметре запроса или в сегменте урла.
Kotlin, Java, Spring, Spring Boot, Spring Data, Spring AI, SQL, PostgreSQL, Oracle, H2, Linux, Hibernate, Collections, Stream API, многопоточность, чат-боты, нейросети, файлы, devops, Docker, Nginx, Apache, maven, gradle, JUnit, YouTube, новости, руководство, ООП, алгоритмы, головоломки, rest, GraphQL, Excel, XML, json, yaml.