Ho cercato come gestire le versioni di un'API REST utilizzando Spring 3.2.x, ma non ho trovato nulla di facile da mantenere. Spiegherò prima il problema che ho e poi una soluzione ... ma mi chiedo se sto reinventando la ruota qui.
Voglio gestire la versione in base all'intestazione Accept e, ad esempio, se una richiesta ha l'intestazione Accept application/vnd.company.app-1.1+json
, voglio che Spring MVC la inoltri al metodo che gestisce questa versione. E poiché non tutti i metodi in un'API cambiano nella stessa versione, non voglio andare su ciascuno dei miei controller e cambiare qualcosa per un gestore che non è cambiato tra le versioni. Inoltre, non voglio avere la logica per capire quale versione usare nel controller stesso (usando i localizzatori di servizi) poiché Spring sta già scoprendo quale metodo chiamare.
Quindi, presa un'API con le versioni 1.0, alla 1.8 dove un gestore è stato introdotto nella versione 1.0 e modificato nella v1.7, vorrei gestirlo nel modo seguente. Immagina che il codice sia all'interno di un controller e che ci sia del codice in grado di estrarre la versione dall'intestazione. (Quanto segue non è valido in primavera)
@RequestMapping(...)
@VersionRange(1.0,1.6)
@ResponseBody
public Object method1() {
// so something
return object;
}
@RequestMapping(...) //same Request mapping annotation
@VersionRange(1.7)
@ResponseBody
public Object method2() {
// so something
return object;
}
Questo non è possibile in primavera poiché i 2 metodi hanno la stessa RequestMapping
annotazione e Spring non si carica. L'idea è che l' VersionRange
annotazione possa definire un intervallo di versioni aperto o chiuso. Il primo metodo è valido dalle versioni 1.0 alla 1.6, mentre il secondo per la versione 1.7 in poi (inclusa l'ultima versione 1.8). So che questo approccio si interrompe se qualcuno decide di passare la versione 99.99, ma è qualcosa con cui posso convivere.
Ora, poiché quanto sopra non è possibile senza una seria rielaborazione di come funziona la primavera, stavo pensando di armeggiare con il modo in cui i gestori corrispondevano alle richieste, in particolare per scrivere la mia ProducesRequestCondition
, e avere la gamma di versioni lì dentro. Per esempio
Codice:
@RequestMapping(..., produces = "application/vnd.company.app-[1.0-1.6]+json)
@ResponseBody
public Object method1() {
// so something
return object;
}
@RequestMapping(..., produces = "application/vnd.company.app-[1.7-]+json)
@ResponseBody
public Object method2() {
// so something
return object;
}
In questo modo, posso avere intervalli di versioni chiusi o aperti definiti nella parte produce dell'annotazione. Sto lavorando a questa soluzione ora, con il problema che avevo ancora a sostituire alcune classi nucleo Spring MVC ( RequestMappingInfoHandlerMapping
, RequestMappingHandlerMapping
e RequestMappingInfo
), che non mi piace, perché vuol dire lavoro extra ogni volta che decido di effettuare l'aggiornamento a una nuova versione di primavera.
Apprezzerei qualsiasi pensiero ... e soprattutto, qualsiasi suggerimento per farlo in un modo più semplice e facile da mantenere.
modificare
Aggiunta di una taglia. Per ottenere la taglia, rispondi alla domanda sopra senza suggerire di avere questa logica nel controller stesso. Spring ha già molta logica per selezionare il metodo del controller da chiamare, e voglio tornare su questo.
Modifica 2
Ho condiviso il POC originale (con alcuni miglioramenti) in github: https://github.com/augusto/restVersioning
produces={"application/json-1.0", "application/json-1.1"}
ecc