Пару месяцев назад я смотрел, как собираюсь разрабатывать новый REST API для проекта Oracle Cloud. Однажды я планировал использовать декларативную инъекцию ссылок, созданную в Jersey 1.x Марком Хэдли. К сожалению, это еще не было переадресовано, поэтому я побеседовал с руководителем проекта, и я взялся за
работу среднего размера по обновлению кода.
небольшую
Одна из вещей, которая изменилась в новой версии, заключается в том, что в JAX-RS 2.0 есть Link
объект, поэтому вместо возможности вставлять только String и URI вы также можете вводить правильные атрибуты rel. Это означает, что существующие аннотации, закодированные Marc, были объединены в простой набор аннотаций как для заголовков Link, так и для внедренных свойств.
Эта функциональность доступно сейчас вместе с простым примером. Оригинальная версия функции , что я совершил имеют некоторые серьезные ограничения, которые описаны ниже, вам потребуется версия Джерси поста 2.8 или вы можете построить 2,9-SNAPSHOT изображение , которое содержит мои изменения в настоящее время для реализации примера в этом блоге.
В этом блоге рассматривается использование этого нового API, чтобы обеспечить простое внедрение для API коллекций. Одним из распространенных шаблонов в сервисах RESTful, в частности, основанных на JSON, является наличие массива структурных связей на верхнем уровне структуры. Для целей этого блога я собираюсь следовать форме гипермедиа типа Collection + JSON .
{ "collection" : { "version" : "1.0", "href" : "http://example.org/friends/?offset=10&limit=10", "links" : [ {"rel" : "create", "href" : "http://example.org/friends/"} {"rel" : "next", "href" : "http://example.org/friends/?offset=20&limit=10"} {"rel" : "previous", "href" : "http://example.org/friends/?offset=0&limit=10"} ], "items" : [ ... ] } }
Так что я могу вставить ссылки в следующем виде, но для ясности здесь не хватает пучка котлов. Это не самый аккуратный код; но в более позднем цикле должно быть возможно просто несколько их Проект в настоящее время использует EL для доступа к свойствам — это дает преимущество, позволяющее записывать значения, поскольку вы можете представлять свойства. Я могу понять, что это не нравится некоторым; но я не уверен, вижу ли я какой-либо смысл в переходе на JavaScript в данный момент. Также не стоит удивляться аннотациям @Xml, я использую MOXy для генерации JSON — это не только XML.
{ @XmlTransient private int limit, offset; // Getters for these @XmlTransient private int modelLimit; // Getters for these @InjectLink( resource = ItemsResource.class, method = "query", style = Style.ABSOLUTE, bindings = {@Binding(name = "offset", value="${instance.offset}"), @Binding(name = "limit", value="${instance.limit}") }, rel = "self" ) @XmlElement(name="link") private String href; @InjectLinks({ @InjectLink( resource = ItemsResource.class, style = Style.ABSOLUTE, method = "query", condition = "${instance.offset + instance.limit < instance.modelLimit}", bindings = { @Binding(name = "offset", value = "${instance.offset + instance.limit}"), @Binding(name = "limit", value = "${instance.limit}") }, rel = "next" ), @InjectLink( resource = ItemsResource.class, style = Style.ABSOLUTE, method = "query", condition = "${instance.offset - instance.limit >= 0}", bindings = { @Binding(name = "offset", value = "${instance.offset - instance.limit}"), @Binding(name = "limit", value = "${instance.limit}") }, rel = "prev" )}) @XmlElement(name="link") @XmlElementWrapper(name = "links") @XmlJavaTypeAdapter(Link.JaxbAdapter.class) List<Link> links; .... }
Исходное портирование декларативного кода связывания, существующее в версии Jersey до 2.8, имело очень наивный код в отношении определения того, каким должен быть URI для конкретного ресурса, оно не могло работать с любыми ресурсами, которые не были в корне приложения. и не справится с параметрами запроса, которые так важны при работе с коллекциями.
Теоретически может быть несколько URI для определенного класса ресурсов; но этот код должен предполагать отображение 1: 1, текущая реализация содержит простой алгоритм, который использует метамодель Джерси, чтобы попытаться разработать структуру, если это не сработает, вы можете просто предоставить другую реализацию из ResourceMappingContext .
Некоторые могут спросить, почему я должен использовать эти уродливые аннотации, когда может быть проще просто ввести сам URI? Ну, причина в том, чтобы предоставить метаданные, которые могут использовать другие инструменты. Одна из моих следующих работ — расширить эту работу для создания расширений гипермедиа, и для этого мне нужны вышеуказанные метаданные. (Ожидание одобрения запроса на извлечение , прежде чем я действительно смогу в него попасть).
Наконец, стоит отметить, что у модели подкачки есть свои проблемы, которые становятся очевидными, если вы рассматриваете коллекцию REST как некий массив, который можно безопасно перелистывать. Одновременные обновления вместе с отсутствием состояния означают, что клиент никогда не может быть уверен, что у него есть полная модель, и он должен ожидать, что некоторые элементы будут видны несколько раз при обновлении модели. Вместо этого следует рассмотреть схемы на основе курсора или связывания, что является еще одним хорошим напоминанием о том, почему вы всегда должны рассматривать URI как непрозрачный — серверу может понадобиться изменить его структуру в будущем. Но это совсем другой блог для другого дня …..