web-dev-qa-db-fra.com

Meilleure façon de gérer JAX-RS REST API URI versioning

J'ai fait ma recherche d'abord dans stackoverflow et je n'ai pas pu trouver de réponses liées à ma question. Tout ce que je peux trouver, ce sont des questions liées à REST uri design.

Ma question dans le côté backend. Supposons que nous ayons deux versions différentes de REST uri's

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

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

Quelle est la meilleure approche à suivre du côté du backend (code côté serveur) pour un routage, une gérabilité et une réutilisation corrects des classes existantes sur ces deux ensembles d'api en fonction de la version?

J'ai pensé à une approche pour définir des classes de ressources avec différentes annotations @Path, par exemple avoir un package pour v1 et v2 séparément et dans la classe ProductsResource de ce package, définir

    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 {...}

& ont ensuite la logique d'implémentation basée sur les versions. Le problème avec cette approche est que lorsque nous ne modifions qu'une seule API de ressource particulière de l'ensemble des API, nous devons également copier d'autres classes dans le package v2. Pouvons-nous l'éviter?

Que diriez-vous d'écrire une annotation personnalisée, par exemple @Version et avoir des valeurs des versions qu'il prend en charge? Maintenant, que ce soit v1 ou v2, les deux requêtes iront à la même classe de ressources.

Dites par exemple.

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

MISE À JOUR:

Il y avait une suggestion de version d'API par Jarrod pour gérer la version dans les en-têtes. C'est aussi une façon de le faire, cependant, j'attends avec impatience les meilleures pratiques à utiliser lorsque nous suivons le contrôle de version basé sur l'URI

46
Deepesh M

Le problème avec sa mise dans l'URL est que l'URL est censée représenter une ressource par emplacement. Une version d'API n'est pas un emplacement et ne fait pas partie de l'identifiant de la ressource.

Coller /v2/ dans l'URL rompt tous les liens existants précédents.

Il existe une façon correcte de spécifier le versionnage de l'API:

Mettez-le dans le type mime pour le Accept: en-tête que vous souhaitez. Quelque chose comme Accept: application/myapp.2.0.1+json

Chaîne de responsabilité le modèle va bien ici, surtout s'il y aura un nombre important de versions d'API suffisamment différentes pour avoir leur propre gestionnaire, de cette façon les méthodes ne deviennent pas incontrôlables.

16
user177800

Ce billet de blog contient un exemple de ce que certains considèrent comme la bonne approche, c'est-à-dire ne pas avoir la version dans l'URI: http://codebias.blogspot.ca/2014/03/versioning-rest- apis-with-custom-accept.html

En bref, il tire parti de JAX-RS @Consume annotation pour associer la demande d'une version particulière à une implémentation spécifique, comme:

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

Je me demandais juste pourquoi ne pas avoir une sous-classe de ProductService appelée

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


}


@Path(/v1/ProductService)
 class ProductService{


}

et ne remplacer que ce qui est changé dans la v2. Tout inchangé fonctionnera de la même manière que dans v1/ProductService.

Cela conduit sans aucun doute à plus de # classes, mais est un moyen plus facile de coder pour tout ce qui change dans la nouvelle version de l'api et de revenir à l'ancienne version sans dupliquer le code.

2
Chetya