web-dev-qa-db-ja.com

JAX RSで、返される応答とBeanまたはBeanのコレクション(DTO)の違い

私はREST api。呼び出しの成功に関連して、エラーや例外的な状況に対して適切な例外をスローしています。

以下に例を示します。

@Produces(MediaType.APPLICATION_JSON)
public Response search(FooBean foo){
    List<FooBean> results = bar.search(foo);
    return Response.ok(results).build();
}

vs.

@Produces(MediaType.APPLICATION_JSON)
public List<FooBean> search(FooBean foo){
    List<FooBean> results = bar.search(foo);
    return results;
}

両方の例を使用しましたが、サービスメソッドを簡単に認識できるようにするために、2番目のシナリオを好むでしょう。私はこれらの両方の方法に対する応答を調べましたが、それらは同じように見えます。

考え?

40
Half_Duplex

違いはJAX-RS仕様で説明されています。

.3.3戻り値のタイプ

リソースメソッドは、void、Response、GenericEntity、または別のJava typeを返す場合があります。これらの戻り値のタイプは、次のように応答エンティティ本体にマップされます。

void
結果は、204ステータスコードの空のエンティティボディになります。

応答
結果は、Responseのstatusプロパティで指定されたステータスコードを使用して、Responseのentityプロパティからマッピングされたエンティティ本体の結果です。 nullの戻り値は、204ステータスコードになります。応答のステータスプロパティが設定されていない場合:エンティティプロパティがnullの場合、200ステータスコードがnull以外のエンティティプロパティに使用され、204ステータスコードが使用されます。

GenericEntity
GenericEntityのEntityプロパティからマッピングされたエンティティ本体の結果。戻り値がnullでない場合、200ステータスコードが使用され、null戻り値は204ステータスコードになります。

その他
返されたインスタンスのクラスからマッピングされたエンティティ本体の結果。戻り値がnullでない場合、200ステータスコードが使用され、null戻り値は204ステータスコードになります。

応答で追加のメタデータを提供する必要があるメソッドは、Responseのインスタンスを返す必要があります、ResponseBuilderクラスは、ビルダーパターンを使用してResponseインスタンスを作成します。

「通常の」Beanは、Responseとほぼ同じ方法でマッピングされますが、Responseを使用すると追加のメタデータ(応答ヘッダー、特殊なステータス、特殊なコンテンツタイプ、等)。どちらを使用するかについては、あなた次第です-Responseを使用すると柔軟性が高まりますが、通常のBeanはより「自己文書化」されます。

36
Perception

常に応答200 - OKを返し、メソッドがインターセプトまたはWebApplicationExceptionで結果を返す前に発生する可能性のあるすべての例外をキャッチして操作する場合、違いはありません。したがって、これらのメソッドは両方とも同じ応答を返します。

唯一の違いは、次の例のように、nullオブジェクトを返す、またはオブジェクトを作成するなど、特定のシナリオです。

@POST
@Consumes("application/json")
public Response post(String content) {
    URI createdUri = ...
    Object createdContent = create(content);
    return Response.created(createdUri).entity(createdContent).build();
}

この場合、戻り値は201 - CREATEDになります(作成されたオブジェクトにアクセスするためのURIを使用)

したがって、次の方法:

@POST
@Consumes("application/json")
public Object post(String content) {
    URI createdUri = ...
    Object createdContent = create(content);
    return createdContent;
}

...応答200 - OKを返します

クライアントがどの応答ステータスを受け取るかを気にしない場合は、問題なく宣言を使用できます。

ソース: ジャージー

8

私の見解では、応答にDTO(Bean/Beanのコレクション)が含まれる場合、残りのサービスは常にDTOを返す必要がありますが、応答オブジェクトは返しません。

動機:早めに、または遅く、rest client api通常、restインターフェースを抽出し、restサービスでそれらを実装する必要があります。これらの休息インターフェースは、休息クライアントのクライアントによって使用されます。

そして、クライアントの観点からは、DTO処理とプレーンレスポンスの間には大きな違いがあります。レスポンスが使用される場合、クライアントは強制されます:

  1. 応答コードを明示的にチェックして、成功した応答を処理します
  2. コードを明示的にチェックしてエラーを処理する
  3. 応答の本文を自分でDTOに変換します。

つまり、Responseの処理は、メソッドでエラーコードを返すことに非常に似ており、非常に悪い習慣と見なされます。エラーを1か所で処理するために、例外が使用されます(私はFPエラーの処理方法について話しているわけではありませんが、これが最善です)。

だからあなたは何をすることができます:

  1. リクエストが正常に処理された場合、残りのサービスデータをDTO/Beanに変換して返します。
  2. 検証に失敗した場合、または何か問題が発生した場合は、restサービスで例外をスローします。おそらく、デフォルトのexception mapperは適切ではないため、独自の例外マッパーを実装する必要があります。

そのため、事前に考える場合は、DTOを返却する必要があります。

1つのユースケース、プレーンなレスポンスを返す必要がある場合-たとえば、ファイルをエクスポートする場合。 JAX RSはInputStreamオブジェクトを返すことを許可していないようです。よくわかりませんが、確認する必要があります。

もう1つのユースケースは@Perceptionによって示されましたが、ルールというよりも例外です。

追加のメタデータに応答を提供する必要があるメソッドは、Responseのインスタンスを返す必要があります。ResponseBuilderクラスは、ビルダーパターンを使用してResponseインスタンスを作成する便利な方法を提供します。

注:これはJAX RSの一般的な質問であり、ResteasyやJerseyのような正確な実装に依存しません

2
Alexandr