Перейти к основному содержимому

Spring JSON-P с Джексоном

· 4 мин. чтения

1. Обзор

Если вы занимаетесь разработкой чего-либо в Интернете, вы знаете об ограничениях политики одного и того же источника, которые браузеры имеют при работе с запросами AJAX. Простой обзор ограничения заключается в том, что любой запрос, исходящий из другого домена, схемы или порта, не будет разрешен.

Один из способов ослабить это ограничение браузера при работе с данными JSON — использовать JSON с дополнением ( JSON-P ).

В этой статье рассматривается поддержка Spring для работы с данными JSON-P — с помощью AbstractJsonpResponseBodyAdvice .

2. JSON-P в действии

Политика одинакового происхождения не применяется к тегу <script> , что позволяет загружать сценарии из разных доменов. Техника JSON-P использует это преимущество, передавая ответ JSON в качестве аргумента функции javascript.

2.1. Подготовка

В наших примерах мы будем использовать этот простой класс Company :

public class Company {

private long id;
private String name;

// standard setters and getters
}

Этот класс будет связывать параметры запроса и должен возвращаться с сервера в виде JSON-представления.

Метод Controller также является простой реализацией — он возвращает экземпляр Company :

@RestController
public class CompanyController {

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

На стороне клиента мы можем использовать библиотеку jQuery для создания и отправки запроса AJAX:

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

Рассмотрим запрос AJAX по следующему URL-адресу:

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

Ответ от сервера будет следующим:

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

Поскольку запрос был отправлен для той же схемы, домена и порта, ответ не будет заблокирован, а данные JSON будут разрешены браузером.

2.2. Запрос между источниками

Изменив URL-адрес запроса на:

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

ответ будет заблокирован браузером из-за отправки запроса с локального хоста на 127.0.0.1 , который считается другим доменом и представляет собой нарушение политики того же происхождения.

С помощью JSON-P мы можем добавить в запрос параметр обратного вызова:

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

На стороне клиента это так же просто, как добавить в AJAX-запрос следующие параметры:

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

getCompanyData будет функцией, вызываемой при получении ответа .

Если сервер форматирует ответ следующим образом:

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

браузеры не будут его блокировать, так как он будет рассматривать ответ как сценарий, согласованный между клиентом и сервером на основании совпадения getCompanyData как в запросе, так и в ответе.

3. Аннотация @ControllerAdvice

Bean -компоненты, аннотированные @ControllerAdvice , могут помогать всем или определенному подмножеству контроллеров и используются для инкапсуляции междисциплинарного поведения, общего для разных контроллеров. Типичные шаблоны использования связаны с обработкой исключений , добавлением атрибутов в модели или регистрацией биндеров.

Начиная с Spring 4.1 , @ControllerAdvice может регистрировать реализации интерфейса ResponseBodyAdvice , который позволяет изменять ответ после его возврата методом контроллера, но до записи подходящим преобразователем.

4. Изменение ответа с помощью AbstractJsonpResponseBodyAdvice

Также, начиная с Spring 4.1 , теперь у нас есть доступ к классу AbstractJsonpResponseBodyAdvice , который форматирует ответ в соответствии со стандартами JSON-P.

В этом разделе объясняется, как запустить базовый класс и изменить ответ, не внося никаких изменений в существующие контроллеры.

Чтобы включить поддержку Spring для JSON-P, начнем с конфигурации:

@ControllerAdvice
public class JsonpControllerAdvice
extends AbstractJsonpResponseBodyAdvice {

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

Поддержка осуществляется с помощью класса AbstractJsonpResponseBodyAdvice . Ключ, переданный суперметоду, будет использоваться в URL-адресе, запрашивающем данные JSON-P.

С помощью этого совета контроллера мы автоматически преобразуем ответ в JSON-P.

5. JSON-P со Spring на практике

С ранее обсужденной конфигурацией мы можем заставить наши REST-приложения отвечать с помощью JSON-P. В следующем примере мы вернем данные компании, поэтому наш URL-адрес запроса AJAX должен выглядеть примерно так:

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

В результате предыдущей настройки ответ будет выглядеть следующим образом:

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

Как уже говорилось, ответ в этом формате не будет заблокирован, несмотря на то, что он исходит из другого домена.

JsonpControllerAdvice можно легко применить к любому методу, который возвращает ответ, аннотированный с помощью @ResponseBody и ResponseEntity .

В обратном вызове должна быть передана функция с тем же именем, getCompanyData , для обработки всех ответов.

6. Заключение

В этой быстрой статье показано, как утомительная работа по форматированию ответа для использования преимуществ JSON-P упрощается с помощью новых функций в Spring 4.1.

Реализацию примеров и фрагментов кода можно найти в этом проекте GitHub .