web-dev-qa-db-ja.com

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

私はすでにここで尋ねられている質問をしていません: @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) ;

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とQueryParamを使って情報を区別するのかを聞きたいです。私はまた練習の後ろの理由を聞きたいと思います。

233
Blessed Geek

RESTはそれ自体標準ではないかもしれませんが、一般的なRESTドキュメントとブログ投稿を読むことで、API URLを構造化するための良い方法についてのいくつかのガイドラインが得られるはずです。ほとんどの残りのAPIは、パスにリソース名とリソースIDしか持たない傾向があります。といった:

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

REST AP​​Iの中には、フィルタリング、ページ区切り、ソートにクエリ文字列を使用するものがありますが、RESTは厳密な標準ではないので、いくつかのREST AP​​Iをチェックすることをお勧めします githubstackoverflow のようにして、あなたのユースケースに何がうまくいくかを見てください。

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

215
theon

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

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

GET /employee/{id}

すべての従業員の詳細を一度に10人ずつ取得する必要があるシナリオがある場合は、query paramを使用します。

GET /employee?start=1&size=10

これは、開始従業員ID 1が10レコードを取得することを意味します。

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

79

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

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

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

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

それが役立つことを願っています。 :-)

39
10GritSandpaper

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

たとえば、ユーザープロファイルのURLにプロファイルIDパラメータが含まれている場合、これはユーザーによってブックマークされたり電子メールで送信されたりする可能性があるため、そのプロファイルIDをパスパラメータとして含めます。また、pathパラメータを含むURLで示されるページは変更されません。ユーザーは自分のプロファイルを設定して保存し、それ以降はそれほど変更することはほとんどありません。これは、Webクローラー/検索エンジン/ブラウザ/ etcがパスに基づいてこのページをうまくキャッシュできることを意味します。

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

これが助けになることを願っています - 私は説明が少しあいまいかもしれないことを理解する:)

6
Liv

フィルタ処理にクエリパラメータを使用し、グループ化にパスパラメータを使用できます。次のリンクはこれについて良い情報を持っています pathParamsやQueryParamsを使うとき

6
Chandra

非常に興味深い質問です。

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

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

しかし、パス変数を使用すると、このサービスはすべてGET要求をキャッシュすることができます。

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

それはデータの構造に関するより多くの情報をユーザに与えます。

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

/市/経度、緯度

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

/ IconGenerator /赤、青、緑

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

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

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

まとめると、このメソッドの1つを使用する強力な理由はありませんが、できる限りURI変数を使用してください。

4
jfcorugedo

Wikipedia:Uniform Resource Locatorから

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

オプションのクエリ、前の部分と疑問符(?)で区切られ、非階層のクエリ文字列を含むデータ

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

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

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

別の書き込み、

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

もう一つ、

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

—ただし、特定のエンティティを識別するための柔軟で非階層的なシステムを実装する場合があります。 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
Matthew Slyman

前述のとおり、RESTは標準ではありません。ただし、標準ベースのURI規約を実装する場合は、 oData URI規約 を検討してください。 Ver 4は OASIS標準として承認された であり、 Apache Olingo を介してJavaを含む様々な言語のoData用のライブラリが存在します。 Red Hat、Citrix、IBM、Blackberry、Drupal、Netflix、Facebook、SAPなど、{ 他の業界企業からも支持を得ています _であるため、Microsoftからのスポーンであることを先延ばしにしないでください。

他の採用企業はここにリストされています

2
MikeM

たとえば、リソースの集合体の場合、サブリソースの集合がそれ自体で意味をなす場合、クエリパラメータとパスパラメータの両方をサポートできます。

/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
Steve Mitchell
  1. @QueryParamはDefault Valueアノテーションと一緒に使うと便利です。クエリパラメータが渡されない場合はnullポインタ例外を避けることができます。

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}
p0param1に一致し、p1param2に一致します。 URIについて
http://localhost:8080/Restr/rest/msg/4/6
結果は10になります。

REST Serviceでは、JAX-RSはHTTPリクエストからデータを受け取るために@QueryParam@FormParamを提供します。 HTTPフォームは、GETやPOSTなどのさまざまな方法で送信できます。

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

@FormParam:POSTリクエストを受け取り、HTMLフォームまたはメディアのリクエストからデータを取得します

1
Amlesh Kumar

その理由は実際には非常に単純です。クエリパラメータを使用するときは、 "/"などの文字を取り込むことができ、クライアントはそれらをHTMLエンコードする必要はありません。他にも理由がありますが、それは簡単な例です。パス変数を使用する場合は。私はあなたがIDを扱っているときはいつでも、またはパス変数がクエリの方向であるかどうかを言うでしょう。

1
Tony

私たちは@Queryparam@pathparamを使うとき、アンダーサンドに一つの例を与えています

例えば、私はひとつのリソースをcarResourceクラスとしています

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

@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メソッドはSwiftモデルベースの自動車のみを表示します。

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

Carresouceクラスでcarmodelを@pathPramとして宣言したため、ResourceNotFound例外が発生します。そうしないと、carmodelをreQ uriとして指定する必要があります。 colorはなぜその色が@quetyParamなのでreqにはオプションなのかという理由でresourceにreqを渡します。

0
user4374220

一言で言えば、

@Pathparamは、ResourcesとQuery Stringの両方を通過する値に対して機能します。

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

@Queryparamは、クエリ文字列のみを渡すために機能します。

  • / user?id = 1
0
ArulRajP