Подтвердить что ты не робот

Лучший способ обработки JAX-RS REST API URI

Сначала я выполнил поиск в stackoverflow, и я не смог найти ответы на мои вопросы. Все, что я могу найти, это вопросы, связанные с дизайном REST uri.

Мой вопрос на стороне сервера. Предположим, у нас есть две разные версии REST uri

http://api.abc.com/rest/v1/products

http://api.abc.com/rest/v2/products

Каков наилучший подход к поддержке на стороне сервера (серверный код) для правильной маршрутизации, управления и повторного использования существующих классов в этих двух наборах api на основе версии?

Я думал о подходе к определению классов ресурсов с различными аннотациями @Path, например. иметь пакет для v1 и v2 отдельно и в классе ProductsResource этого пакета, определить

    package com.abc.api.rest.v1.products;
    @Path("/rest/v1/products")
    public class ProductsResource {...}

    package com.abc.api.rest.v2.products;
    @Path("/rest/v2/products")
    public class ProductsResource {...}

& то есть логика реализации на основе версий. Проблемы с этим подходом состоят в том, что когда мы изменяем только один ресурс api из набора api, нам также нужно скопировать другие классы в пакет v2. Мы можем избежать этого?

Как написать пользовательскую аннотацию, скажем @Version и иметь значения поддерживаемых ею версий? Теперь, будь то v1 или v2, оба запроса перейдут в тот же класс ресурсов.

Скажите, например,

    package com.abc.api.rest.products;
    @Path("/rest/{version: [0-9]+}/products")
    @Version(1,2)
    public class ProductsResource {...}

UPDATE:

В Jarrod было предложено управление версиями API, чтобы обрабатывать версию в заголовках. Это также один из способов сделать это, однако, я с нетерпением жду лучших практик, которые будут использоваться, когда мы будем следить за версиями, основанными на URI.

4b9b3361

Ответ 1

Проблема с помещением в URL-адрес заключается в том, что URL-адрес должен представлять ресурс по местоположению. Версия API не является местом и не является частью идентификатора ресурса.

Приклеивание /v2/ в URL-адресе разбивает все существующие ссылки, которые раньше были.

Существует два правильных способа указания версии управления версиями API:

  • Поместите его в тип mime для заголовка Accept:, который вы хотите. Что-то вроде Accept: application/myapp.2.0.1+json

  • Поместите его в Header не в URL. Затем ваш метод, который обрабатывает ресурс, может посмотреть на Header и определить, какой метод или объект обработчика отправляется. Что-то вроде Version: 2.0.1

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

Ответ 2

В этом сообщении блога есть пример того, что некоторые считают правильным, т.е. не имеют версии в URI: http://codebias.blogspot.ca/2014/03/versioning-rest-apis-with-custom-accept.html

Короче говоря, он использует аннотацию JAX-RS @Consume, чтобы связать запрос конкретной версии с конкретной реализацией, например:

@Consumes({"application/vnd.blog.v1+xml", "application/vnd.blog.v1+json"})

Ответ 3

Мне просто интересно, почему не существует подкласса ProductService, называемого

@Path(/v2/ProductService)
ProductServiceV2 extends ProductService {


}


@Path(/v1/ProductService)
 class ProductService{


}

и только переопределить все, что было изменено в v2. Все неизменное будет работать так же, как в v1/ProductService.

Это defintely приводит к большему количеству классов, но является одним из простых способов кодирования только для того, что меняется в новой версии api и возвращается к старой версии без дублирования кода.