VERSIONING DELLE API IN SPRING BOOT
Ogni API evolve: nuovi requisiti, cambiamenti nei modelli di dati, funzionalità deprecate. Senza una strategia di versionamento, ogni modifica rischia di diventare una breaking change per chi consuma i tuoi servizi. Il versioning delle API è la risposta a questo problema: permette di introdurre cambiamenti in modo controllato, garantendo la continuità per i client esistenti e la libertà di innovare per il team di sviluppo.
In questo articolo esploreremo quattro diverse strategie di API versioning:
- URI versioning
- Request parameter versioning
- Custom Header versioning
- Content-negotiation Versioning
URI Versioning
Questa strategia prevede l'aggiunta della versione all'interno dell'URL delle API. Sebbene sia facilmente realizzabile e immediatamente comprensibile, non è la sicuramente la più elegante.
@RestController@RequestMapping("/api/v1/orders") public class OrderV1Controller { @GetMapping public String getOrdersV1() { return "Order list from API v1"; } } @RestController @RequestMapping("/api/v2/orders") public class OrderV2Controller { @GetMapping public String getOrdersV2() { return "Order list from API v2 with extra fields"; } }
Request Parameter versioning
A differenza della precedente strategia, questa prevede l'aggiunta della versione non nell'URI ma come request parameter. E' sicuramente meno "intrusiva" ma tuttavia meno intuitiva ed immediata: è il client a dover discriminare la versione sulla base del parametro.
@RestController
public class OrderParamController {
@GetMapping("/api/orders")
public Object getOrders(@RequestParam(name = "version", defaultValue = "1") String version) {
if ("1".equals(version)) {
return List.of("Order1", "Order2");
} else if ("2".equals(version)) {
return List.of(
new OrderV2(1, 30),
new OrderV2(2, 25)
);
}
return "Unsupported API version";
}
}Custom Header versioning
Simile alla precedente, questa strategia prevede l'aggiunta di un custom header da aggiungere alla richiesta HTTP. Le API ed i relativi URL restano puliti ed è il client a dover ricordare di aggiungere tale parametro.
@RestController
public class OrderHeaderController {
@GetMapping(value = "/api/orders", headers = "X-API-VERSION=1")
public List<UserV1> getOrdersV1() {
return List.of(
new OrderV1(1),
new OrderV1(2)
);
}
@GetMapping(value = "/api/orders", headers = "X-API-VERSION=2")
public List<UserV2> getOrdersV2() {
return List.of(
new OrderV2(1, 30),
new OrderV2(2, 25)
);
}
}
Content-negotiation Versioning
Questa strategia sfrutta l'header HTTP Accept per specificare la versione API desiderata. Questo metodo aderisce al principio HATEOAS, poiché la versione fa parte della negoziazione dei contenuti.
@RestController
@RequestMapping("/api/orders")
public class OrderContentNegotiationController {
@GetMapping(produces = "application/vnd.company.v1+json")
public String getOrdersV1() {
return "Order list v1";
}
@GetMapping(produces = "application/vnd.company.v2+json")
public String getOrdersV2() {
return "Order list v2";
}
}A queste 4 strategie se ne aggiunge una quinta, ma a condizione che usiate Spring 7 o Spring Boot 4. Infatti, a partire dalle versioni menzionate, è stato introdotto il supporto nativo al versionamento delle API attraverso l'utilizzo delle annotazioni ed evitando in tal modo il ricorso a soluzioni custom.
@RestController
@RequestMapping("/api/orders")
public class OrderController {
@GetMapping
@ApiVersion("1")
public List ordersV1() {
return List.of(
new OrderV1(1),
new OrderV1(2)
);
}
@GetMapping
@ApiVersion("2")
public List ordersV2() {
return List.of(
new OrderV2(1, 30),
new OrderV2(2, 25)
);
}
}
Comments
Post a Comment