Spring JSON-P avec Jackson

Spring JSON-P avec Jackson

1. Vue d'ensemble

Si vous avez développé quelque chose sur le Web, vous connaissez les navigateurs dethe same-origin policy constraint lorsqu'ils traitent des requêtes AJAX. La vue d'ensemble de la contrainte est simple: toute requête provenant d'un domaine, d'un schéma ou d'un port différent ne sera pas autorisée.

Une façon derelax this browser restriction lorsque vous travaillez avec des données JSON - consiste à utiliser JSON avec padding (JSON-P).

Cet article décrit la prise en charge de Spring pour l'utilisation des données JSON-P - avec l'aide deAbstractJsonpResponseBodyAdvice.

2. JSON-P en action

La politique de même origine n'est pas imposée sur la balise<script>, ce qui permet de charger des scripts sur différents domaines. La technique JSON-P tire parti de cela en transmettant la réponse JSON en tant qu'argument de la fonction javascript.

2.1. Préparation

Dans nos exemples, nous utiliserons cette simple classeCompany:

public class Company {

    private long id;
    private String name;

    // standard setters and getters
}

Cette classe liera les paramètres de la demande et devra être renvoyée par le serveur sous forme de représentation JSON.

La méthode Controller est également une implémentation simple - renvoyant l'instanceCompany:

@RestController
public class CompanyController {

    @RequestMapping(value = "/companyRest",
      produces = MediaType.APPLICATION_JSON_VALUE)
    public Company getCompanyRest() {
        Company company = new Company(1, "Xpto");
        return company;
    }
}

Du côté client, nous pouvons utiliser la bibliothèquejQuery pour créer et envoyer une requête AJAX:

$.ajax({
    url: 'http://localhost:8080/spring-mvc-java/companyRest',
    data: {
        format: 'json'
    },
    type: 'GET',
    ...
});

Considérons une demande AJAX par rapport à l'URL suivante:

http://localhost:8080/spring-mvc-java/companyRest

La réponse du serveur serait la suivante:

{"id":1,"name":"Xpto"}

Comme la demande a été envoyée sur le même schéma, le même domaine et le même port, la réponse ne sera pas bloquée et les données JSON seront autorisées par le navigateur.

2.2. Demande d’origine croisée

En modifiant l'URL de la demande en:

http://127.0.0.1:8080/spring-mvc-java/companyRest

la réponse sera bloquée par le navigateur, en raison d'une demande envoyée delocalhost à127.0.0.1, ce qui est considéré comme un domaine différent et présente une violation de la politique de même origine.

Avec JSON-P, nous pouvons ajouter un paramètre de rappel à la demande:

http://127.1.1.1:8080/spring-mvc-java/companyRest?callback=getCompanyData

Du côté client, c'est aussi simple que d'ajouter les paramètres suivants à la requête AJAX:

$.ajax({
    ...
    jsonpCallback:'getCompanyData',
    dataType: 'jsonp',
    ...
});

LegetCompanyData sera la fonction appelée lorsque la réponse est reçue.

Si le serveur formate la réponse comme suit:

getCompanyData({"id":1,"name":"Xpto"});

les navigateurs ne le bloqueront pas, car il traitera la réponse comme un script négocié et convenu entre le client et le serveur en raison de la correspondance desgetCompanyData dans la requête et la réponse.

3. Annotation@ControllerAdvice

Les beans annotés avec@ControllerAdvice sont capables d'aider tout ou un sous-ensemble spécifique de contrôleurs et sont utilisés pour encapsuler un comportement transversal partagé entre différents contrôleurs. Les modèles d'utilisation typiques sont liés auxexception handling,adding attributes to models ou à l'enregistrement des classeurs.

Starting with Spring 4.1,@ControllerAdvice est capable d'enregistrer les implémentations de l'interfaceResponseBodyAdvice qui permet de changer la réponse après son retour par une méthode contrôleur mais avant d'être écrite par un convertisseur approprié.

4. Modification de la réponse à l'aide deAbstractJsonpResponseBodyAdvice

Also starting with Spring 4.1, nous avons maintenant accès à la classeAbstractJsonpResponseBodyAdvice - qui formate la réponse selon les standards JSON-P.

Cette section explique comment mettre en jeu la classe de base et modifier la réponse sans apporter de modification aux contrôleurs existants.

Pour activer la prise en charge de Spring par JSON-P, commençons par la configuration:

@ControllerAdvice
public class JsonpControllerAdvice
  extends AbstractJsonpResponseBodyAdvice {

    public JsonpControllerAdvice() {
        super("callback");
    }
}

Le support se fait à l'aide de la classeAbstractJsonpResponseBodyAdvice. La clé transmise à la super-méthode est celle qui sera utilisée dans l'URL demandant des données JSON-P.

Avec ces conseils de contrôleur, nous convertissons automatiquement la réponse en JSON-P.

5. JSON-P avec Spring en pratique

Avec la configuration précédemment décrite en place, nous sommes en mesure de faire en sorte que nos applications REST répondent avec JSON-P. Dans l'exemple suivant, nous retournerons les données de l'entreprise, donc notre URL de requête AJAX doit ressembler à ceci:

http://127.0.0.1:8080/spring-mvc-java/companyRest?callback=getCompanyData

Suite à la configuration précédente, la réponse se présentera comme suit:

getCompanyData({"id":1,"name":"Xpto"});

Comme indiqué précédemment, la réponse dans ce format ne sera pas bloquée, bien qu'elle provienne d'un domaine différent.

LesJsonpControllerAdvice peuvent facilement être appliqués à n'importe quelle méthode qui renvoie une réponse annotée avec@ResponseBody etResponseEntity.

Il devrait y avoir une fonction avec le même nom passé dans le rappel,getCompanyData, pour gérer toutes les réponses.

6. Conclusion

Cet article rapide montre comment un travail fastidieux de mise en forme de la réponse pour tirer parti de JSON-P est simplifié grâce à la nouvelle fonctionnalité de Spring 4.1.

L'implémentation des exemples et des extraits de code peut être trouvée dans ceGitHub project.