Primavera JSON-P com Jackson

Primavera JSON-P com Jackson

1. Visão geral

Se você tem desenvolvido algo na web, sabe quethe same-origin policy constraint navegadores têm ao lidar com solicitações AJAX. A visão geral simples da restrição é que qualquer solicitação originada de um domínio, esquema ou porta diferente não será permitida.

Uma maneira derelax this browser restriction ao trabalhar com dados JSON - é usando JSON com preenchimento (JSON-P).

Este artigo discute o suporte do Spring para trabalhar com dados JSON-P - com a ajuda deAbstractJsonpResponseBodyAdvice.

2. JSON-P em ação

A política de mesma origem não é imposta sobre a tag<script>, permitindo que os scripts sejam carregados em domínios diferentes. A técnica JSON-P tira proveito disso, passando a resposta JSON como argumento da função javascript.

2.1. Preparação

Em nossos exemplos, usaremos esta classeCompany simples:

public class Company {

    private long id;
    private String name;

    // standard setters and getters
}

Esta classe ligará os parâmetros de solicitação e será retornada do servidor como representação JSON.

O método Controller também é uma implementação simples - retornando a instânciaCompany:

@RestController
public class CompanyController {

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

No lado do cliente, podemos usar a bibliotecajQuery para criar e enviar uma solicitação AJAX:

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

Considere uma solicitação AJAX no seguinte URL:

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

A resposta do servidor seria a seguinte:

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

Como a solicitação foi enviada no mesmo esquema, domínio e porta, a resposta não será bloqueada e os dados JSON serão permitidos pelo navegador.

2.2. Solicitação de origem cruzada

Alterando o URL da solicitação para:

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

a resposta será bloqueada pelo navegador, devido à solicitação enviada delocalhost para127.0.0.1, que é considerado um domínio diferente e apresenta uma violação da política de mesma origem.

Com o JSON-P, podemos adicionar um parâmetro de retorno de chamada à solicitação:

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

No lado do cliente, é tão fácil quanto adicionar os seguintes parâmetros à solicitação AJAX:

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

OgetCompanyData será a função chamada quando a resposta for recebida.

Se o servidor formatar a resposta da seguinte maneira:

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

os navegadores não o bloquearão, pois tratarão a resposta como um script negociado e acordado entre o cliente e o servidor por causa da correspondência degetCompanyData na solicitação e na resposta.

3. @ControllerAdvice Anotação

Os beans anotados com@ControllerAdvice são capazes de auxiliar todos ou um subconjunto específico de Controladores e são usados ​​para encapsular o comportamento de corte cruzado compartilhado entre diferentes Controladores. Os padrões de uso típicos estão relacionados aexception handling,adding attributes to models ou registro de fichários.

Starting with Spring 4.1,@ControllerAdvice é capaz de registrar as implementações da interfaceResponseBodyAdvice que permite alterar a resposta após ela ser retornada por um método do controlador, mas antes de ser escrita por um conversor adequado.

4. Alterando a resposta usandoAbstractJsonpResponseBodyAdvice

Also starting with Spring 4.1, agora temos acesso à classeAbstractJsonpResponseBodyAdvice - que formata a resposta de acordo com os padrões JSON-P.

Esta seção explica como colocar a classe base em jogo e alterar a resposta sem fazer nenhuma alteração nos controladores existentes.

Para ativar o suporte do Spring ao JSON-P, vamos começar com a configuração:

@ControllerAdvice
public class JsonpControllerAdvice
  extends AbstractJsonpResponseBodyAdvice {

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

O suporte é feito usando a classeAbstractJsonpResponseBodyAdvice. A chave passada no super método é a que será usada na URL que solicita dados JSON-P.

Com este conselho de controlador, convertemos automaticamente a resposta em JSON-P.

5. JSON-P com Spring na prática

Com a configuração discutida anteriormente, podemos fazer com que nossos aplicativos REST respondam com JSON-P. No exemplo a seguir, retornaremos os dados da empresa, portanto, nosso URL de solicitação AJAX deve ser algo assim:

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

Como resultado da configuração anterior, a resposta terá a seguinte aparência:

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

Conforme discutido, a resposta neste formato não será bloqueada, apesar de ser originária de um domínio diferente.

OJsonpControllerAdvice pode ser facilmente aplicado a qualquer método que retorna uma resposta anotada com@ResponseBodyeResponseEntity.

Deve haver uma função com o mesmo nome passada no retorno de chamada,getCompanyData, para lidar com todas as respostas.

6. Conclusão

Este artigo rápido mostra como um trabalho tedioso de formatar a resposta para tirar proveito do JSON-P é simplificado usando a nova funcionalidade do Spring 4.1.

A implementação dos exemplos e trechos de código pode ser encontrada nesteGitHub project.