Un type de support personnalisé pour une API REST Spring

Un type de support personnalisé pour une API REST Spring

1. Vue d'ensemble

Dans ce didacticiel, nous allons examiner la définition des types de supports personnalisés et leur production par le contrôleur Spring REST.

Un bon exemple d'utilisation du type de support personnalisé est le contrôle de version d'une API.

2. API - Version 1

Commençons par un exemple simple: une API exposant une seule ressource par identifiant.

Nous allons commencer par une version 1 de la ressource que nous exposons au client. Pour ce faire, nous allons utiliser un en-tête HTTP personnalisé -“application/vnd.example.api.v1+json”.

Le client demandera ce type de média personnalisé via l'en-têteAccept.

Voici notre point de terminaison simple:

@RequestMapping(
  method = RequestMethod.GET,
  value = "/public/api/items/{id}",
  produces = "application/vnd.example.api.v1+json"
)
@ResponseBody
public exampleItem getItem( @PathVariable("id") String id ) {
    return new exampleItem("itemId1");
}

Notez le paramètreproduces ici - spécifiant le type de média personnalisé que cette API est capable de gérer.

Maintenant, la ressourceexampleItem - qui a un seul champ -itemId:

public class exampleItem {
    private String itemId;

    // standard getters and setters
}

Enfin, écrivons un test d'intégration pour le point de terminaison:

@Test
public void givenServiceEndpoint_whenGetRequestFirstAPIVersion_then200() {
    given()
      .accept("application/vnd.example.api.v1+json")
    .when()
      .get(URL_PREFIX + "/public/api/items/1")
    .then()
      .contentType(ContentType.JSON).and().statusCode(200);
}

3. API - Version 2

Supposons maintenant que nous devions modifier les détails que nous exposons au client avec notre ressource.

Nous avions l'habitude d'exposer un identifiant brut - disons que nous devons maintenant le cacher et exposer un nom à la place, pour obtenir un peu plus de flexibilité.

Il est important de comprendre que ce changement n’est pas rétrocompatible; en gros, c’est un changement radical.

Voici notre nouvelle définition de ressource:

public class exampleItemV2 {
    private String itemName;

    // standard getters and setters
}

Et donc, ce que nous devons faire ici, c'est - migrer notre API vers une deuxième version.

Nous allons le faire encreating the next version of our custom media type et en définissant un nouveau point de terminaison:

@RequestMapping(
  method = RequestMethod.GET,
  value = "/public/api/items/{id}",
  produces = "application/vnd.example.api.v2+json"
)
@ResponseBody
public exampleItemV2 getItemSecondAPIVersion(@PathVariable("id") String id) {
    return new exampleItemV2("itemName");
}

Nous avons donc exactement le même terminal, mais nous sommes capables de gérer la nouvelle opération V2.

Lorsque le client demandera“application/vnd.example.api.v1+json” - Spring déléguera à l'ancienne opération et le client recevra unexampleItem avec un champitemId (V1).

Mais lorsque le client définit maintenant l'en-têteAccept sur“application/vnd.example.api.v2+json” –, il accède correctement à la nouvelle opération et récupère la ressource avec le champitemName (V2):

@Test
public void givenServiceEndpoint_whenGetRequestSecondAPIVersion_then200() {
    given()
      .accept("application/vnd.example.api.v2+json")
    .when()
      .get(URL_PREFIX + "/public/api/items/2")
    .then()
      .contentType(ContentType.JSON).and().statusCode(200);
}

Notez comment le test est similaire mais utilise l'en-têteAccept différent.

4. Type de support personnalisé au niveau de la classe

Enfin, parlons d'une définition à l'échelle de la classe du type de média - c'est également possible:

@RestController
@RequestMapping(
  value = "/",
  produces = "application/vnd.example.api.v1+json"
)
public class CustomMediaTypeController

Comme prévu, l'annotation@RequestMapping fonctionne facilement au niveau de la classe et nous permet de spécifier les paramètresvalue,produces etconsumes.

5. Conclusion

Ces articles illustrant des exemples lors de la définition de types de supports personnalisés pourraient être utiles dans le contrôle de version de l'API publique.

L'implémentation de tous ces exemples et extraits de code se trouve dansthe GitHub project - c'est un projet Maven, il devrait donc être facile à importer et à exécuter tel quel.