Когда использовать @QueryParam vs @PathParam

Я не задаю вопрос, который уже задавал здесь: в чем разница между @PathParam и @QueryParam

это "наилучшая практика" или вопрос конвенции.

когда вы используете @PathParam vs @QueryParam.

что я могу думать о том, что решение может использовать эти два для дифференциации информационного шаблона. Позвольте мне проиллюстрировать ниже мое LTPO-менее совершенное наблюдение.

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

в то время как QueryParam может быть зарезервирован для указания атрибутов для поиска экземпляра класса.

например,

  • /Vehicle/Car?registration=123
  • /House/Colonial?region=newengland

/category?instance

@GET
@Path("/employee/{dept}")
Patient getEmployee(@PathParam("dept")Long dept, @QueryParam("id")Long id) ;

vs /category/instance

@GET
@Path("/employee/{dept}/{id}")
Patient getEmployee(@PathParam("dept")Long dept, @PathParam("id")Long id) ;

vs ?category+instance

@GET
@Path("/employee")
Patient getEmployee(@QueryParam("dept")Long dept, @QueryParam("id")Long id) ;

Я не думаю, что существует стандартная конвенция об этом. Есть? Однако я хотел бы услышать о том, как люди используют PathParam vs QueryParam для дифференциации своей информации, как я показал выше. Я также хотел бы услышать причину этой практики.

13 ответов


REST не может быть стандартом как таковым, но чтение общей документации REST и сообщений в блогах должно дать вам некоторые рекомендации для хорошего способа структурирования URL-адресов API. Большинство API rest, как правило, имеют только имена ресурсов и идентификаторы ресурсов в пути. Например:

/departments/{dept}/employees/{id}

некоторые API REST используют строки запросов для фильтрации, разбиения на страницы и сортировки, но поскольку REST не является строгим стандартом, я бы рекомендовал проверить некоторые API REST, такие как github и stackoverflow и посмотреть, что может хорошо работать для вашего случая.

Я бы рекомендовал поместить любые необходимые параметры в путь, и любые необязательные параметры, безусловно, должны быть параметрами строки запроса. Ввод дополнительных параметров в URL-адрес в конечном итоге становится очень грязным при попытке написать обработчики URL, которые соответствуют различным комбинациям.


это то, что я делаю.

Если есть сценарий для получения записи на основе id, например, вам нужно получить сведения о сотруднике, чей id равен 15, тогда у вас может быть ресурс с @PathParam.

GET /employee/{id}

Если есть сценарий, в котором вам нужно получить сведения обо всех сотрудниках, но только 10 за раз, вы можете использовать query param

GET /employee?start=1&size=10

Это говорит о том, что начиная сотрудник id 1 получить десять записей.

чтобы суммировать, используйте @PathParam для извлечение на основе ID. User @QueryParam для фильтра или если у вас есть фиксированный список параметров, которые пользователь может передать.


Я думаю, что если параметр идентифицирует конкретный объект, вы должны использовать переменную path. Например, чтобы получить все сообщения в моем блоге, я прошу

GET: myserver.com/myblog/posts

чтобы получить сообщение с id = 123, я бы попросил

GET: myserver.com/myblog/posts/123

но чтобы отфильтровать мой список сообщений и получить все сообщения с 1 января 2013 года, я бы попросил

GET: myserver.com/myblog/posts?since=2013-01-01

в первом примере "сообщения" определяет конкретный объект (всю коллекцию сообщений в блоге). Во втором примере "123" также представляет определенную сущность (одно сообщение в блоге). Но в последнем примере параметр "since=2013-01-01" - это запрос на фильтрацию коллекции posts не конкретной сущности. Разбиение на страницы и упорядочение были бы еще одним хорошим примером, т. е.

GET: myserver.com/myblog/posts?page=2&order=backward

надеюсь, что это поможет. :-)


вы можете использовать параметры запроса для фильтрации и параметры пути для группировки. Следующая ссылка имеет хорошую информацию об этом когда использовать pathParams или QueryParams


Я лично использовал подход "если для пользователя имеет смысл добавить URL-адрес, который включает эти параметры, то используйте PathParam".

например, если URL-адрес профиля пользователя включает какой-либо параметр идентификатора профиля, так как это может быть закладка пользователем и/или по электронной почте, я бы включил этот идентификатор профиля в качестве параметра пути. Кроме того, еще одно соображение заключается в том, что страница, обозначенная URL-адресом, который включает параметр path, не изменяется-пользователь настроит его / ее профиль, сохраните его, а затем вряд ли сильно изменится; это означает, что webcrawlers/поисковые системы/браузеры/etc могут кэшировать эту страницу на основе пути.

если параметр, переданный в URL, вероятно, изменит макет страницы / содержимое, я бы использовал это как queryparam. Например, если URL-адрес профиля поддерживает параметр, который указывает, показывать ли электронную почту пользователя или нет, я бы счел это параметром запроса. (Я знаю, возможно, вы могли бы сказать, что the &noemail=1 или какой-либо параметр может использоваться в качестве параметра пути и генерирует 2 отдельные страницы-одну с электронной почтой, другую без нее, но логически это не так: это все та же страница с определенными атрибутами или без них.

надеюсь, это поможет - я ценю, что объяснение может быть немного нечетким :)


Это очень интересный вопрос.

вы можете использовать оба из них, нет никакого строгого правила об этом предмете, но использование переменных пути URI имеет некоторые преимущества:

  • кэш: Большинство служб веб-кэша в Интернете не кэшируют запрос GET, если они содержат параметры запроса. Они делают это, потому что есть много систем RPC, использующих GET-запросы для изменения данных на сервере (fail!! Вам должен быть безопасным метод)

но если вы используете переменные пути, все эти службы могут кэшировать ваши запросы GET.

  • иерархия: Переменные пути могут представлять иерархию: / Город / Улица / Место

, Он дает пользователю больше информации о структуре данных.

но если ваши данные не имеют отношения иерархии, вы все равно можете использовать переменные пути, используя запятую или двоеточие:

/ город / долгота, широта

Как правило, используйте запятую, когда порядок параметров имеет значение, используйте двоеточие, когда порядок не имеет значения:

/IconGenerator/красный;синий;зеленый

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

  • когда вам нужно, чтобы браузер автоматически помещал переменные формы HTML в URI
  • когда вы имеете дело с алгоритм. Например, Google engine использует строки запроса:

http:// www.google.com/search?q=rest

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


Как отметил Теон, отдых не является стандартом. Однако, если вы хотите реализовать соглашение URI на основе стандартов, вы можете рассмотреть OData URI convention. Версия 4 была одобрено как стандарт оазиса и библиотеки существуют для oData для различных языков, включая Java через Apache Olingo. Не позволяйте тому факту, что это отродье от Microsoft, отталкивать вас, так как это получил поддержку от других игроков отрасли, а также, которые включают Red Hat, Citrix, IBM, Blackberry, Drupal, Netflix Facebook и SAP

больше усыновителей перечислены здесь


причина на самом деле очень просто. При использовании параметра запроса вы можете использовать такие символы, как"/", и вашему клиенту не нужно их кодировать html. Есть и другие причины, но это простой пример. Когда использовать переменную PATH. Я бы сказал, Когда вы имеете дело с идентификаторами или если переменная path является направлением для запроса.


Из Википедии: Единый Локатор Ресурсов

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

необязательный запрос, отделена от предыдущей части вопросительным знаком (?), содержащий строку запроса не-иерархические данные.

- согласно концептуальному дизайну URL, мы может реализовать PathParam для иерархических данных/директив / компонентов локатора или реализовать QueryParam, когда данные не являются иерархическими. Это имеет смысл, потому что пути естественно упорядочены, тогда как запросы содержат переменные, которые могут быть упорядочены произвольно (пары неупорядоченных переменных/значений).

предыдущий комментатор писал,

Я думаю, что если параметр идентифицирует конкретный объект, вы должны использовать переменную path.

другой написал:

используйте @PathParam для извлечения на основе id. User @QueryParam для фильтра или если у вас есть фиксированный список параметров, которые пользователь может передать.

другой,

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

- однако можно реализовать гибкую, неиерархическую систему для идентификации конкретных объектов! Один может иметь несколько уникальных индексов в таблице SQL и позволяет идентифицировать сущности с помощью любой комбинации полей, составляющих уникальный индекс! Различные комбинации (возможно, также упорядоченные по-разному) могут использоваться для ссылок из различных связанных объектов (рефереров). В этом случае мы можем иметь дело с неиерархическими данными, используемыми для идентификации отдельных сущностей , или в других случаях мы можем указать только определенные переменные / поля-определенные компоненты уникальных индексов - и получить список/набор записей. В таких случаях может быть проще, логичнее и разумнее реализовать URL-адреса как QueryParams!

может ли длинная шестнадцатеричная строка разбавить / уменьшить значение ключевых слов в остальной части пути? Это может стоить учитывая потенциальные последствия SEO размещения переменных / значений в пути или в запросе и последствия человеческого интерфейса для того, хотим ли мы, чтобы пользователи могли проходить / исследовать иерархию URL-адресов путем редактирования содержимое адресной строки. Моя страница 404 Not Found использует переменные SSI для автоматического перенаправления сломанных URL-адресов их родителю! Поисковые роботы также могут пересекать иерархию путей. С другой стороны, лично, когда я делюсь URL - адресами в социальных сетях, я вручную удаляю любые частные уникальные идентификаторы-обычно путем усечения запроса из URL-адреса, оставляя только путь: в этом случае есть некоторая полезность в размещении уникальных идентификаторов в пути, а не в запросе. Хотим ли мы облегчение использования компонентов path в качестве грубого пользовательского интерфейса, возможно, зависит от того, являются ли данные/компоненты удобочитаемыми или нет. Вопрос о удобочитаемости для человека несколько связан с вопросом иерархии: часто данные, которые могут быть выражены в виде удобочитаемых ключевых слов, также являются иерархическими; в то время как иерархические данные часто могут быть выражены в виде удобочитаемых ключевых слов. (Сами поисковые системы могут быть определены как расширение использования URL-адресов в качестве пользовательского интерфейса.) Иерархии ключевых слов или директивы могут быть не строго упорядочены, но они обычно достаточно близки, чтобы мы могли охватить альтернативные случаи в пути, и обозначьте один вариант как" канонический " случай.

есть принципиально несколько видов вопросов, которые мы могли бы ответить с URL для каждого запроса:

  1. какую запись / вещь мы запрашиваем / обслуживаем?
  2. какой из них нас интересует?
  3. как мы хотим представить информация / записи?

Q1 почти наверняка лучше всего покрывается путем или PathParams. Q3 (который, вероятно, управляется с помощью набора произвольно упорядоченных необязательных параметров и значений по умолчанию); почти наверняка лучше всего покрывается QueryParams. В2: это зависит...


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

когда вы хотите проанализировать параметры запроса из запроса GET, вы можете просто определить соответствующий параметр для метода, который будет обрабатывать запрос GET и аннотировать их аннотацией @QueryParam

  1. @PathParam извлекает значения URI и соответствует @Path. И, следовательно, получает входной параметр. 2.1 @PathParam может быть более одного и имеет значение аргументы методов

    @Path ("/rest")

    общественный класс Abc {

    @GET

    @Path ("/msg/{p0}/{p1}")

    @Produces ("text/plain")

    общественная строка добавить(@PathParam("Р0") целое число параметр1, @PathParam("Р1") целочисленный параметр param2 ) {

     return String.valueOf(param1+param2);
    

    } }

в выше пример,

http://localhost:8080/Restr/rest/msg/ {p0} / {p1},

P0 соответствует param1 и P1 соответствует param2. Так что для URI

http://localhost:8080/Restr/rest/msg/4/6,

мы получаем результат 10.

в Службе REST JAX-RS предоставляет @QueryParam и @FormParam для приема данных из HTTP-запроса. Форма HTTP может быть отправлена различными методами, такими как GET и ДОЛЖНОСТЬ.

@QueryParam: принимает запрос GET и считывает данные из строки запроса.

@FormParam: принимает запрос POST и извлекает данные из HTML-формы или любого запроса носителя


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

/departments/{id}/employees
/employees?dept=id

параметры запроса могут поддерживать иерархическое и неиерархическое подмножество; параметры пути являются только иерархическими.

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

/inventory?make=toyota&model=corolla
/inventory?year=2014

использовать параметры запроса для объединения ортогональных иерархий.

/inventory/makes/toyota/models/corolla?year=2014
/inventory/years/2014?make=toyota&model=corolla
/inventory?make=toyota&model=corolla&year=2014

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

/words/{id}/definitions
/definitions?word=id   // not useful

Я даю один exapmle в undersand, когда мы используем @Queryparam и @pathparam

например, я беру один resouce carResource класс

если вы хотите сделать входные данные вашего метода resouce manadatory, используйте тип param как @pathaparam, если входные данные вашего метода ресурсов должны быть необязательными, то сохраните этот тип param как @QueryParam параметр

@Path("/car")
class CarResource
{
    @Get
    @produces("text/plain")
    @Path("/search/{carmodel}")
    public String getCarSearch(@PathParam("carmodel")String model,@QueryParam("carcolor")String color) {
        //logic for getting cars based on carmodel and color
            -----
        return cars
    }
}

для этого resouce передайте запрос

req uri ://address:2020/carWeb/car/search/swift?carcolor=red

если вы даете req, как это в зависимости от Будет дает модель автомобиля и цвет

 req uri://address:2020/carWeb/car/search/swift

если вы даете req, как это resoce метод будет отображать только swift модель автомобиля на основе

req://address:2020/carWeb/car/search?carcolor=red

если вы дадите так, мы получим ResourceNotFound исключение, потому что в классе автомобиля resouce я объявил carmodel как @pathPram то есть вы должны и должны дать carmodel как reQ uri в противном случае он не будет передавать req resouce, но если вы не передадите цвет, он также передаст req ресурсу почему потому что цвет @quetyParam это необязательно в req.


в двух словах

@ Pathparam работает для значения, проходящего через ресурсы и строку запроса

  • / user / 1
  • /пользователей?id=1

@ Queryparam работает для передачи значения только строка запроса

  • /пользователей?id=1