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

277

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

Это вопрос «передового опыта» или соглашения.

Когда бы вы использовали @PathParamпротив @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) ;

против /category/instance

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

против ?category+instance

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

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

Благословенный Компьютерщик
источник
4
возможный дубликат Когда использовать pathParams или QueryParams
Йоахим Зауэр

Ответы:

245

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

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

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

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

Теон
источник
73
« Я бы порекомендовал поместить в путь все обязательные параметры, а любые необязательные параметры должны быть параметрами строки запроса. » - недурно +1 да def
smeeb
1
если это соглашение будет использоваться и для запроса Put, допустим, мы хотим обновить конкретную версию сущности db, если URI PUT /depatments/{dept}/employees/{id}/{version}и версия являются необязательными или версия должна быть PUT /depatments/{dept}/employees/{id}?version=12необязательной
наилучшие пожелания
В этом случае я бы порекомендовал: - PUT /depatments/{dept}/employees/{id}/versions/{version}создать сотрудника с выбранной версией - POST /depatments/{dept}/employees/{id}/versionsсоздать сотрудника с версией, определенной бэкэндом
Гийом Вовер,
90

Вот что я делаю.

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

GET /employee/{id}

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

GET /employee?start=1&size=10

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

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

Арун Б Чандрасекаран
источник
оба «@PathParam» и «@QueryParam» обеспечивают одинаковую функциональность? «@QueryParam» - это просто еще один способ написать то же самое?
Ришабх Агарвал
1
@RishabhAgarwal, хотя оба предоставляют одинаковую функциональность, практика чистого кода такова, что рекомендуется указывать обязательный параметр в качестве переменной пути и любой необязательный параметр в качестве параметра запроса.
Ахил Гатики
@RishabhAgarwal Для получения дополнительной информации, вы можете обратиться к моей статье Лучшие практики Rest API
Арун Б Chandrasekaran
43

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

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» представляет собой запрос на фильтрацию коллекции сообщений, а не конкретной сущности. Нумерация страниц и упорядочивание были бы другим хорошим примером, то есть

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

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

10GritSandpaper
источник
8

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

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

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

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

Liv
источник
Я думаю, что этот ответ смешивает ресурсы с маршрутами. Речь идет о ресурсах REST API, обычно возвращающих JSON или XML, а не о маршрутах веб-приложения, которые помогают вам ориентироваться в приложении.
Хампус
5

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

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

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

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

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

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

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

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

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

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

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

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

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

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

jfcorugedo
источник
2

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

Другие усыновители перечислены здесь

MikeM
источник
2

Из Википедии: унифицированный указатель ресурса

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

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

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

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

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

Другой написал,

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

Другой,

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

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

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

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

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

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

Мэтью Слиман
источник
2

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

/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
Стив Митчелл
источник
1

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

Тони
источник
1

Я даю один пример, чтобы понять, когда мы используем @Queryparamи@pathparam

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

Если вы хотите, чтобы входные данные вашего метода ресурсов были обязательными, используйте тип параметра как @pathaparam, если входные данные вашего метода ресурса должны быть необязательными, сохраните этот тип параметра как @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
    }
}

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

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

Если вы дадите запрос, как это, то ресурс даст основанную модель автомобиля и цвет

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

Если вы зададите req как этот, метод resoce покажет только автомобиль на основе быстрой модели

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

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

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

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

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

    @Path("/rest")
    public class Abc {
    
        @GET
        @Path("/msg/{p0}/{p1}")
        @Produces("text/plain")
        public String add(@PathParam("p0") Integer param1, @PathParam("p1")  Integer 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 и POST.

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

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

Амлеш Кумар
источник
0

В двух словах,

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

  • /user/1
  • /user?id=1

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

  • /user?id=1
ArulRajP
источник