(java || kotlin) && devOps
356 subscribers
7 photos
1 video
7 files
354 links
Полезное про Java и Kotlin - фреймворки, паттерны, тесты, тонкости JVM. Немного архитектуры. И DevOps, куда без него
Download Telegram
Версионирование для REST в Java - оно как бы есть, и его как бы нет)

Основная проблема с версионированием - которую многие, в т.ч. и я, не замечают - следующая.
Версионирование нужно и его почти везде используют, но при этом Spring, который также везде используют, не делает ничего для его поддержки.
Точнее не делал.
Начиная со Spring 7, который уже вышел, данный функционал наконец таки появился: https://habr.com/ru/companies/spring_aio/articles/967454/

Что добавили:
1) определение способа передачи версии:

# Path segment versioning (e.g., /api/v1/users)
spring.mvc.apiversion.use.path-segment=1

# Request header versioning (e.g., X-API-Version: 1.0)
spring.mvc.apiversion.use.header=X-API-Version

# Query parameter versioning (e.g., ?version=1.0)
spring.mvc.apiversion.use.query-parameter=version

# Media type parameter versioning (e.g., Accept: application/json;version=1.0)
spring.mvc.apiversion.use.media-type-parameter[application/json]=version


2) указание версию по умолчанию:

# Basic versioning configuration
spring.mvc.apiversion.default=1.0


3) указание списка поддерживаемых версий и, соответственно, их валидацию:

spring.mvc.apiversion.supported=1.0,2.0


или

# автоматическое детектирование по содержимому контроллеров
spring.mvc.apiversion.detect-supported = true


Естественно, все это можно сделать через код.

4) Стандартный парсер версий - по стандарту семантического версионирования

5) Само собой есть возможность определить нестандартный механизм передачи и формата версий через создание ApiVersionResolver и ApiVersionParser

6) Есть даже ApiVersionDeprecationHandler - стандартизация уведомления клиента об устаревших версиях и автоматическая 400-ка для неподдерживаемых

7) И конечно механизм маршрутизации по версиям, который автоматически разрешает вот такую конструкцию:

public class AccountController {
@GetMapping
public Account getAccount() {
}

@GetMapping(version = "1.1")
public Account getAccount1_1() {
}

@GetMapping(version = "1.2+")
public Account getAccount1_2() {
}

@GetMapping(version = "1.5")
public Account getAccount1_5() {
}
}


8) аналогично для endpoint в функциональном стиле:

RouterFunction<ServerResponse> route = RouterFunctions.route()
.GET("/hello-world", version("1.2"),
request -> ServerResponse.ok().body("Hello World")).build();


9) плюс все поддерживается для reactive stack

10) и на клиенте (для тестовых клиентов тоже):

RestClient client = RestClient.builder()
.baseUrl("http://localhost:8080")
.apiVersionInserter(ApiVersionInserter.useHeader("API-Version"))
.build();
...
Account account = client.get().uri("/accounts/1")
.apiVersion(1.1)
.retrieve()
.body(Account.class);


Еще одна важная фича, которая должна была появиться раньше.

#spring #versioning