Коли використовувати @QueryParam vs @PathParam


276

Я не задаю питання, яке тут вже задають: Яка різниця між @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 для розмежування своєї інформації, як я пояснював вище. Я також хотів би почути причину такої практики.


Відповіді:


245

REST може не бути стандартом як таким, але читання загальної документації REST та публікацій блогу повинно дати вам певні рекомендації щодо гарного способу структури URL-адрес API. У більшості інших API-інтерфейсів на шляху є лише імена ресурсів та ідентифікатори ресурсів. Як от:

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

Деякі API-файли REST використовують рядки запитів для фільтрації, сторінки та сортування, але оскільки REST не є строгим стандартом, я рекомендую перевірити деякі API REST там, наприклад, github та stackoverflow, і побачити, що може добре працювати у вашому випадку використання.

Я рекомендую ввести будь-які необхідні параметри в шлях, і будь-які необов’язкові параметри, безумовно, повинні бути параметрами рядка запиту. Якщо встановити необов'язкові параметри в шлях, в результаті вийде справді безладним при спробі написати обробники URL-адрес, які відповідають різним комбінаціям.


73
" Я рекомендую ввести будь-які необхідні параметри в шлях, і будь-які необов'язкові параметри, безумовно, повинні бути рядковими параметрами запиту. " - великі пальці вгору +1, щоб
визначити

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

Це я і роблю.

Якщо є сценарій для отримання запису на основі id, наприклад, вам потрібно отримати реквізити працівника, ідентифікатор якого становить 15, то ви можете мати ресурс за допомогою @PathParam.

GET /employee/{id}

Якщо є сценарій, коли вам потрібно отримати реквізити всіх співробітників, але лише 10 за один раз, ви можете скористатись параметром запиту

GET /employee?start=1&size=10

Це говорить про те, що починаючи службовець id 1 отримує десять записів.

Для підведення підсумків використовуйте @PathParam для пошуку на основі id. Користувач @QueryParam для фільтра або якщо у вас є фіксований список параметрів, які користувач може пройти.


чи "@PathParam" і "@QueryParam" забезпечують однакові функції? Це "@QueryParam" лише інший спосіб написання того ж самого?
Рішабх Агарвал

1
@RishabhAgarwal, незважаючи на те, що обидва забезпечують однакову функціональність, практика чистого коду полягає в тому, що рекомендується вводити необхідний параметр як змінну шляху та будь-який необов'язковий параметр як параметр запиту.
Ахіл Ґатікі

@RishabhAgarwal Для отримання додаткової інформації, ви можете посилатися на мою статтю Найкращі практики відпочинку API
Arun B 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

Сподіваюся, що це допомагає. :-)


8

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

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

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

Сподіваюся, це допомагає - я вдячний, що пояснення може бути трохи нечітким :)


Я думаю, що ця відповідь плутає ресурси з маршрутами. Питання стосується ресурсів API REST, як правило, повертає JSON або XML, а не про маршрути веб-програми, що допомагає орієнтуватися в програмі.
Гампус


5

Це дуже цікаве питання.

Ви можете використовувати обидва, не існує жодного суворого правила щодо цієї теми, але використання змінних шляху URI має деякі переваги:

  • Кеш : Більшість сервісів веб-кеша в Інтернеті не кешують GET-запит, коли вони містять параметри запиту. Вони роблять це тому, що існує багато RPC-систем, які використовують GET-запити для зміни даних на сервері (помилка !! Отримати потрібно безпечним методом)

Але якщо ви використовуєте змінні шляху, всі ці служби можуть кешувати ваші GET-запити.

  • Ієрархія : змінні шляху можуть представляти ієрархію: / Місто / вулиця / місце

Це дає користувачеві більше інформації про структуру даних.

Але якщо ваші дані не мають жодного ієрархічного відношення, ви все одно можете використовувати змінні Path, використовуючи коску або крапку з двокрапкою:

/ Місто / довгота, широта

Як правило, використовуйте кома, коли впорядкування параметрів має значення, використовуйте крапку з двокрапкою, коли впорядкування не має значення:

/ IconGenerator / червоний; синій; зелений

Окрім цих причин, є деякі випадки, коли дуже часто використовувати змінні рядка запиту:

  • Коли вам потрібен браузер, автоматично вводите змінні форми HTML в URI
  • Коли ви маєте справу з алгоритмом. Наприклад, двигун google використовує рядки запитів:

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

Підсумовуючи це, немає жодної вагомої причини використовувати один із цих методів, але коли можна, використовуйте змінні URI.


2

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

Тут перелічено більше усиновителів


2

З Вікіпедії: Уніфікований локатор ресурсів

Шлях , який містить дані, зазвичай організований в ієрархічній формі , що відображається як послідовність сегментів, розділених косою рисою.

Необов’язковий запит , відокремлений від попередньої частини знаком питання (?), Що містить рядок запиту неієрархічних даних .

- Відповідно до концептуальної конструкції URL-адреси, ми можемо реалізувати PathParam для ієрархічних компонентів даних / директив / локатора або застосувати QueryParam, коли дані не є ієрархічними. Це має сенс, оскільки шляхи природно впорядковані, тоді як запити містять змінні, які можуть бути упорядковані довільно (не упорядковані пари змінних / значень).

Попередній коментатор написав:

Я думаю, що якщо параметр ідентифікує конкретну сутність, ви повинні використовувати змінну шляху.

Інший написав:

Використовуйте @PathParam для пошуку на основі id. Користувач @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, метод резонансу відображатиме лише швидку модель на базі автомобіля

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

Якщо ви надаєте подібне, ми отримаємо виняток ResourceNotFound, тому що в класі ресуспіювання автомобілів я оголосив carmodel як @pathPramтакий, який ви повинні і повинні дати carmodel як reQ uri, інакше вона не передасть req для відновлення, але якщо ви не передасте колір також він передасть файл req ресурсу, чому в кольорі @quetyParamвін необов'язковий.


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 працює для передачі значення лише рядок запиту

  • /user?id=1
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.