2013-02-12 13 views
37

Ho effettuato la prima ricerca in StackOverflow & Non sono riuscito a trovare alcuna risposta relativa alla mia domanda. Tutto quello che posso trovare sono domande relative al progetto uri REST.Il modo migliore per gestire la versione dell'URI dell'API REST JAX-RS

La mia domanda sul lato back-end. Supponiamo di avere due differenti versioni di REST uri di

http://api.abc.com/rest/v1/products

http://api.abc.com/rest/v2/products

Qual è l'approccio migliore per seguire sul lato backend (codice lato server) per il corretto instradamento, gestibilità & riutilizzo dell'esistente le classi attraverso questi due set di API si basano sulla versione?

Ho pensato ad un approccio per definire le classi di risorse con diverse annotazioni @Path per es. avere un pacchetto per v1 & v2 separatamente & in classe ProductsResource di quel pacchetto, definire

package com.abc.api.rest.v1.products; 
    @Path("/rest/v1/products") 
    public class ProductsResource {...} 

    package com.abc.api.rest.v2.products; 
    @Path("/rest/v2/products") 
    public class ProductsResource {...} 

& quindi hanno la logica implementazione basata sulle versioni. I problemi con questo approccio sono quando cambiamo solo una particolare risorsa API dal set di API, dobbiamo copiare anche altre classi nel pacchetto v2. Possiamo evitarlo?

Come scrivere un'annotazione personalizzata dire @Version & hanno valori delle versioni che supporta? Ora se è v1 o v2, entrambe le richieste andranno alla stessa classe di risorse.

Dire per es.

package com.abc.api.rest.products; 
    @Path("/rest/{version: [0-9]+}/products") 
    @Version(1,2) 
    public class ProductsResource {...} 

UPDATE:

C'era un'API delle versioni suggerimento di Jarrod per gestire la versione nelle intestazioni. Anche questo è un modo per farlo, sto cercando le migliori pratiche da utilizzare quando stiamo seguendo il controllo delle versioni degli URI

+4

le best practice è ** non ** inserire le informazioni sulla versione api nell'URL –

+5

Questa è stata una grande domanda, sono molto sorpreso della mancanza di risposte. Ci sono centinaia di persone che discutono a favore e contro la versione di URI, ma tutti i principali siti lo fanno perché è esplicito e facile da usare per i client. @Deepesh M - quale soluzione hai usato alla fine? – arcseldon

+4

solo perché molte persone fanno le cose in modo non corretto non ne fanno una buona idea! significa solo che molte persone lo stanno facendo in modo errato. –

risposta

13

Il problema con il metterlo nell'URL è che l'URL dovrebbe rappresentare una risorsa in base alla posizione. Una versione API non è un percorso e non fa parte dell'identificatore della risorsa.

L'inserimento di /v2/ nell'URL interrompe tutti i collegamenti esistenti precedenti.

Ci sono due modi adeguati per specificare API delle versioni:

  1. metterlo nel mime-type per il Accept: intestazione che si desidera. Qualcosa come Accept: application/myapp.2.0.1+json

  2. Non inserirlo nell'URL Header. Quindi il tuo metodo che sta gestendo la risorsa può guardare allo Header e determinare quale metodo o oggetto di gestione da inviare a. Qualcosa di simile Version: 2.0.1

Chain of Responsiblity modello va bene qui, specialmente se ci sarà significativo numero di versioni di API che sono abbastanza diversi per avere il proprio gestore, che i metodi di modo non ci sfugga di mano.

+4

Tacking su questo - in un'applicazione RESTful, il tuo URL dovrebbe rappresentare una risorsa. La risorsa probabilmente non è 'versionata'; è lo stesso indipendentemente dallo stile di accesso. Se la risorsa è versionata, dovrebbe essere rappresentata all'interno della risorsa, non nel suo identificatore. – cmonkey

+0

@cmonkey, puoi fare un esempio? –

+5

Esempio: il mio account utente è una risorsa su SO. L'URL è: http://stackoverflow.com/users/322722/cmonkey. Quando/Se SO cambia funzionalità, apis o aggiunge dati al mio account utente, l'account è sempre la stessa risorsa. Non diventerebbe improvvisamente http: //.../cmonkey_v2. In caso contrario, il contenuto collegato (come questo commento) non funzionerà più. – cmonkey

6

Questo post del blog ha un esempio di quello che è considerato il da alcuni come l'approccio corretto, vale a dire non avere la versione nella URI: http://codebias.blogspot.ca/2014/03/versioning-rest-apis-with-custom-accept.html

In breve, si sfrutta JAX-RS @Consume annotazioni per associare la richiesta per una particolare versione di una specifica implementazione, come:

@Consumes({"application/vnd.blog.v1+xml", "application/vnd.blog.v1+json"}) 
+2

Chi ha definito ciò che è considerato il percorso corretto? REST è uno stile architettonico e nessun protocollo! A meno che non si violi HTTP o non aderiscano ai [vincoli architetturali] (https://en.wikipedia.org/wiki/Representational_state_transfer#Architectural_constraints) non vi è alcun diritto o errato, forse alcune buone pratiche sebbene alcuni servizi REST auto-rivendicati non siano RESTful in ogni modo quindi alcune affermazioni dovrebbero essere trattate con cura speciale. –

+0

Hai ragione, ho attenuato e aggiunto "da alcuni di essere" per sottolineare che non tutti sono d'accordo. –

2

mi stavo chiedendo perché non hanno una sottoclasse di ProductService chiamato

@Path(/v2/ProductService) 
ProductServiceV2 extends ProductService { 


} 


@Path(/v1/ProductService) 
class ProductService{ 


} 

e sovrascrive solo ciò che è cambiato in v2. Tutto invariato funzionerà come in v1/ProductService.

Questo defintely porta a più # di classi, ma è un modo più semplice di codifica per solo ciò che sta cambiando nella nuova versione di API e ripristinando la vecchia versione senza duplicare il codice.

+0

Anche questo era il mio pensiero iniziale :) Ho ricordato come EclipseLink implementa il supporto dei dialetti JPA in un modo simile (Oracle11Platform estende Oracle10Platform, ecc.). Ma poi, ho pensato che sarebbe stato molto complicato con REST. Immagina di dover estendere tutte le versioni delle tue classi dopo la versione. Mi piace l'approccio con i parametri di intestazione. – jFrenetic

+4

Questo è così miope non è nemmeno divertente. Dovrai mantenere "30" diversi metodi o classi per ogni 'URL' nella tua applicazione quando arrivi a' v30'? Non scala. –

Problemi correlati