Рубрики
Без рубрики

Пользовательский тип носителя для API Spring REST

Краткое введение в использование пользовательского типа носителя в API Spring REST.

Автор оригинала: baeldung.

1. Обзор

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

Хорошим вариантом использования пользовательского типа носителя является управление версиями API.

2. API – Версия 1

Давайте начнем с простого примера – API, предоставляющего один ресурс по идентификатору.

Мы начнем с версии 1 Ресурса, который мы предоставляем клиенту. Для этого мы будем использовать пользовательский HTTP – заголовок – “application/vnd.baeldung.api.v1+json” .

Клиент запросит этот пользовательский тип носителя через заголовок Accept .

Вот наша простая конечная точка:

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

Обратите внимание на параметр products здесь – указание пользовательского типа носителя, который может обрабатывать этот API.

Теперь ресурс BaeldungItem , который имеет одно поле – ItemId :

public class BaeldungItem {
    private String itemId;
    
    // standard getters and setters
}

И последнее, но не менее важное: давайте напишем интеграционный тест для конечной точки:

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

3. API – Версия 2

Теперь давайте предположим, что нам нужно изменить детали, которые мы предоставляем клиенту с помощью нашего Ресурса.

Раньше мы выставляли необработанный идентификатор – скажем, теперь нам нужно скрыть его и вместо этого выставить имя, чтобы получить немного больше гибкости.

Важно понимать, что это изменение не является обратно совместимым; в основном – это прорывное изменение.

Вот наше новое определение ресурсов:

public class BaeldungItemV2 {
    private String itemName;

    // standard getters and setters
}

Итак, что нам нужно сделать здесь, так это перенести наш API на вторую версию.

Мы собираемся сделать это, создав следующую версию нашего пользовательского типа носителя и определив новую конечную точку:

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

Таким образом, теперь у нас есть точно такая же конечная точка, но способная обрабатывать новую операцию V2.

Когда клиент запросит “application/vnd.baeldung.api.v1+json” – Spring делегирует старую операцию, и клиент получит BaeldungItem с полем ItemId (V1).

Но когда клиент теперь установит заголовок Accept в “application/vnd.baeldung.api.v2+json” – они правильно выполнят новую операцию и вернут ресурс с полем ItemName (V2):

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

Обратите внимание, что тест похож, но использует другой заголовок Accept .

4. Пользовательский тип носителя на уровне класса

Наконец, давайте поговорим об общеклассовом определении типа носителя-это тоже возможно:

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

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

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

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

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