@QueryParamと@PathParamを使用する場合


276

私はすでにここで質問されている質問をしていません: @PathParamと@QueryParamの違いは何ですか

これは「ベストプラクティス」または規則の質問です。

するときは、使用する@PathParam@QueryParam

その決定は、情報パターンを区別するために2つを使用することであると考えることができます。私の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ドキュメントとブログの投稿を読むと、API URLを構造化するための適切な方法に関するいくつかのガイドラインが得られるはずです。ほとんどのREST APIは、パスにリソース名とリソースIDのみを含める傾向があります。といった:

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

一部のREST APIはクエリ文字列を使用してフィルタリング、ページ分割、並べ替えを行っていますが、RESTは厳密な標準ではないため、githubstackoverflowなどのREST APIを調べて、ユースケースで何がうまく機能するかを確認することをお勧めします。

パスに必要なパラメーターを含めることをお勧めします。オプションのパラメーターは、必ずクエリ文字列パラメーターにする必要があります。オプションのパラメーターをパスに入れると、さまざまな組み合わせに一致するURLハンドラーを記述しようとすると、非常に面倒になります。


73
パスに必須パラメーターを含めることをお勧めします。オプションのパラメーターは、必ずクエリ文字列パラメーターにする必要があります。」-いいね+1はいdef
smeeb

1
この規則は、同様のPut要求を使用する必要があり、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したバージョンで従業員を作成する
Guillaume Vauvert

90

これが私がすることです。

IDに基づいてレコードを取得するシナリオがある場合、たとえば、IDが15である従業員の詳細を取得する必要がある場合は、@ PathParamを使用してリソースを持つことができます。

GET /employee/{id}

すべての従業員の詳細を一度に10人だけ取得する必要があるシナリオがある場合は、クエリパラメータを使用できます。

GET /employee?start=1&size=10

これは、最初の従業員ID 1が10レコードを取得することを示しています。

要約すると、@ PathParamを使用して、IDに基づく取得を行います。フィルターまたはユーザーが渡すことができるオプションの固定リストがある場合は、ユーザー@QueryParam。


「@PathParam」と「@QueryParam」はどちらも同じ機能を提供しますか?「@QueryParam」は同じことを書くための別の方法ですか?
Rishabh Agarwal

1
@RishabhAgarwalはどちらも同じ機能を提供しますが、クリーンなコードプラクティスは、必須パラメーターをパス変数として、任意のパラメーターをクエリパラメーターとして配置することをお勧めします。
Akhil Ghatiki 2018

@RishabhAgarwal詳細については、私の記事Rest APIのベストプラクティス
Arun B Chandrasekaran

43

パラメータが特定のエンティティを識別する場合は、パス変数を使用する必要があると思います。たとえば、私のブログのすべての投稿を取得するには、

GET: myserver.com/myblog/posts

id = 123の投稿を取得するには、リクエストします

GET: myserver.com/myblog/posts/123

しかし、私の投稿のリストをフィルタリングして、2013年1月1日以降のすべての投稿を取得するには、

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

最初の例では、「投稿」は特定のエンティティ(ブログ投稿のコレクション全体)を識別します。2番目の例では、「123」は特定のエンティティ(単一のブログ投稿)も表します。しかし、最後の例では、パラメーター「since = 2013-01-01」は、特定のエンティティーではなく投稿コレクションをフィルターする要求です。ページネーションと順序付けは、もう1つの良い例です。

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

お役に立てば幸いです。:-)


8

私は「ユーザーがこれらのパラメーターを含むURLをブックマークして、それからPathParamを使用することが理にかなっている」というアプローチを個人的に使用しました。

たとえば、ユーザープロファイルのURLにプロファイルIDパラメータが含まれている場合、これはユーザーがブックマークしたり、メールで送信したりできるため、そのプロファイルIDをパスパラメータとして含めます。また、これに関するもう1つの考慮事項は、パスparamを含むURLで示されるページは変更されないことです。ユーザーは自分のプロファイルを設定して保存し、それ以降はそれほど変更しない可能性があります。これは、webcrawlers / search engines / browsers / etcがパスに基づいてこのページを適切にキャッシュできることを意味します。

URLで渡されたパラメーターがページレイアウト/コンテンツを変更する可能性がある場合は、それをqueryparamとして使用します。たとえば、プロファイルURLがユーザーのメールを表示するかどうかを指定するパラメーターをサポートしている場合、それをクエリパラメーターと見なします。(間違いなく、その&noemail=1パラメータはパスパラメータとして使用でき、2つの個別のページを生成します-1つはメールがあり、もう1つはありません-とは言え、論理的にはそうではありません:特定の属性が表示されているかどうかにかかわらず、同じページです。

これがお役に立てば幸いです-説明が少しあいまいかもしれないことを感謝します:)


これはリソースとルートを混同していると思います。問題は、REST APIのリソースについてであり、通常はJSONまたはXMLを返します。Webアプリケーションのルートではなく、アプリケーション内の移動に役立ちます。
ハンパス


5

とても興味深い質問です。

両方を使用できますが、この件について厳密な規則はありませんが、URIパス変数を使用するといくつかの利点があります。

  • キャッシュ:インターネット上のほとんどのWebキャッシュサービスは、クエリパラメーターが含まれている場合、GETリクエストをキャッシュしません。サーバーでデータを変更するためにGETリクエストを使用するRPCシステムがたくさんあるので、彼らはそれをします(失敗!! Getは安全な方法でなければなりません)

ただし、パス変数を使用する場合、このサービスはすべてGETリクエストをキャッシュできます。

  • 階層:パス変数は階層を表すことができます:/ City / Street / Place

データの構造に関する詳細情報をユーザーに提供します。

しかし、データに階層関係がない場合でも、コンマまたはセミコロンを使用してPath変数を使用できます。

/ City / longitude、latitude

原則として、パラメータの順序が重要な場合はカンマを使用し、順序が重要でない場合はセミコロンを使用します。

/ IconGenerator / red; blue; green

これらの理由とは別に、クエリ文字列変数を使用することが非常に一般的である場合があります。

  • ブラウザがHTMLフォーム変数をURIに自動的に配置する必要がある場合
  • アルゴリズムを扱っているとき。たとえば、googleエンジンはクエリ文字列を使用します。

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

要約すると、このメソッドのいずれかを使用する強い理由はありませんが、可能な場合は常にURI変数を使用します。


2

前述のとおり、RESTは標準ではありません。ただし、標準ベースのURI規則を実装する場合は、oData URI規則を検討してください。Ver 4はOASIS標準として承認されておりApache Olingoを介してJavaを含むさまざまな言語のoData用のライブラリが存在します。これは、Red Hat、Citrix、IBM、Blackberry、Drupal、Netflix Facebook、SAPを含む他の業界のプレーヤーからもサポートを得ているため、Microsoftからのスポーンであるという事実を認めないでください。

より多くのアダプターがここにリストされています


2

ウィキペディアから:Uniform Resource Locator

スラッシュで区切られた一連のセグメントとして表示される通常は階層形式編成されたデータを含むパス

前の部分から疑問符(?)で区切られたオプションのクエリ非階層データのクエリ文字列が含まれます

— URLの概念設計に従って、階層データ/ディレクティブ/ロケーターコンポーネントにPathParamを実装するか、データが階層的でない場合はQueryParamを実装します。パスは自然に順序付けられますが、クエリには任意に順序付けできる変数(順序付けされていない変数/値のペア)が含まれているため、これは意味があります。

以前のコメント者が書いた、

パラメータが特定のエンティティを識別する場合は、パス変数を使用する必要があると思います。

別の人が書いた、

IDに基づく取得には@PathParamを使用します。フィルターまたはユーザーが渡すことができるオプションの固定リストがある場合は、ユーザー@QueryParam。

別の

パスに必要なパラメーターを含めることをお勧めします。オプションのパラメーターは、必ずクエリ文字列パラメーターにする必要があります。

—ただし、特定のエンティティを識別するための柔軟な非階層システムを実装することもできます。SQLテーブルに複数の一意のインデックスがあり、一意のインデックスを構成するフィールドの任意の組み合わせを使用してエンティティを識別できる場合があります。さまざまな組み合わせ(おそらく、順序も異なる)は、さまざまな関連エンティティ(参照元)からのリンクに使用できます。この場合、個々のエンティティを識別するために使用される非階層データを扱う場合があります。または、特定の変数/フィールド(一意のインデックスの特定のコンポーネント)のみを指定して、レコードのリスト/セットを取得する場合もあります。そのような場合、URLをQueryParamsとして実装する方が簡単で、より論理的で合理的です。

長い16進文字列は、パスの残りの部分のキーワードの値を薄めたり減らしたりできますか?パスまたはクエリに変数/値を配置することの潜在的なSEOの影響を考慮することは価値があるかもしれません、およびユーザーがアドレスバーのコンテンツを編集してURLの階層を走査/探索できるようにするかどうかのヒューマンインターフェイスの影響。私の404 Not FoundページはSSI変数を使用して、壊れたURLを親に自動的にリダイレクトします!検索ロボットは、パス階層をトラバースする場合もあります。一方、個人的には、ソーシャルメディアでURLを共有する場合、プライベートな一意の識別子を手動で取り除きます。通常、URLからクエリを切り捨て、パスのみを残します。この場合、一意の識別子を配置するのにいくつかのユーティリティがあります。クエリ内ではなくパス内。粗雑なユーザーインターフェイスとしてパスコンポーネントの使用を促進するかどうかは、おそらくデータ/コンポーネントが人間が読めるかどうかによって異なります。人間の可読性の問題は、階層の問題にある程度関連しています。多くの場合、人間が読めるキーワードとして表現できるデータも階層的です。階層データは、人間が読めるキーワードとして表現されることがよくあります。(検索エンジン自体は、ユーザーインターフェースとしてのURLの使用を強化するものとして定義される場合があります。)キーワードまたはディレクティブの階層は厳密に順序付けられていない場合がありますが、通常、パス内の別のケースをカバーできるほど十分に近く、1つのオプションに「正規の」ケースとしてラベルを付けます

基本的に、各リクエストの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エンコードする必要はありません。他の理由もありますが、それは簡単な例です。パス変数をいつ使用するかについては。idを処理するとき、またはパス変数がクエリの方向である場合はいつでも言います。


1

私たちが使用しないとき、私はundersandに1 exapmleを与えている@Queryparam@pathparam

たとえば、私は1つのリソースを取っていますcarResourceクラスです

@pathaparamリソースメソッドの入力を必須にする場合は、param型をasとして使用します。リソースメソッドの入力をオプションにする必要がある場合は、param型を@QueryParamparamのままにします。

@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を指定すると、リソースはベースとなる車のモデルと色を提供します

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

このようにreqを指定した場合、resoceメソッドは迅速なモデルベースの車のみを表示します

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

このように指定すると、ResourceNotFound例外が発生します。これは、車のリソースクラスでcarmodelを宣言したため@pathPramです。そうでなければ、車のモデルをreQ uriとして指定する必要があります。また、色は@quetyParamreqではオプションであるため、なぜreqをリソースに渡します。


0
  1. @QueryParam デフォルト値アノテーションと一緒に使用すると、クエリパラメータが渡されない場合のnullポインタ例外を回避できます。

GETリクエストからクエリパラメータを解析する場合は、GETリクエストを処理するメソッドにそれぞれのパラメータを定義し、それらに@QueryParamアノテーションを付けることができます。

  1. @PathParamURI値を抽出し、に一致し@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、、param1p1一致し、と一致しparam2ます。したがって、URIの
http://localhost:8080/Restr/rest/msg/4/6場合
、結果が得られ10ます。

RESTサービスでは、JAX-RSはHTTPリクエストからデータを受け入れるために@QueryParam、および@FormParamその両方を提供します。HTTPフォームは、GETやPOSTなどのさまざまなメソッドで送信できます。

@QueryParam :GETリクエストを受け入れ、クエリ文字列からデータを読み取ります。

@FormParam:POSTリクエストを受け入れ、HTMLフォームまたはメディアのリクエストからデータをフェッチします


0

一言で言えば、

@Pathparam リソースとクエリ文字列の両方を通過する値に対して機能します

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

@Queryparam クエリ文字列のみを渡す値に対して機能します

  • /user?id=1
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.