222

Jersey を使用して JAX-RS (別名、JSR-311) を学習しています。ルート リソースの作成に成功し、パラメーターをいじっています。

@Path("/hello")
public class HelloWorldResource {

    @GET
    @Produces("text/html")
    public String get(
        @QueryParam("name") String name,
        @QueryParam("birthDate") Date birthDate) {

         // Return a greeting with the name and age
    }
}

これはうまく機能し、Date(String) コンストラクターによって理解される現在のロケールの任意の形式 (YYYY/mm/dd や mm/dd/YYYY など) を処理します。しかし、無効または理解できない値を指定すると、404 応答が返されます。

例えば:

GET /hello?name=Mark&birthDate=X

404 Not Found

この動作をカスタマイズするにはどうすればよいですか? おそらく別の応答コード (おそらく「400 Bad Request」) ですか? エラーをログに記録するのはどうですか?トラブルシューティングを支援するために、カスタム ヘッダーに問題の説明 (「不正な日付形式」) を追加することはできますか? または、5xx ステータス コードと共に、詳細を含むエラー レスポンス全体を返しますか?

4

11 に答える 11

277

JAX-RS でエラー処理動作をカスタマイズするには、いくつかの方法があります。ここでは、より簡単な方法を 3 つ紹介します。

最初のアプローチは、WebApplicationException を拡張する Exception クラスを作成することです。

例:

public class NotAuthorizedException extends WebApplicationException {
     public NotAuthorizedException(String message) {
         super(Response.status(Response.Status.UNAUTHORIZED)
             .entity(message).type(MediaType.TEXT_PLAIN).build());
     }
}

そして、この新しく作成された例外をスローするには、次のようにします。

@Path("accounts/{accountId}/")
    public Item getItem(@PathParam("accountId") String accountId) {
       // An unauthorized user tries to enter
       throw new NotAuthorizedException("You Don't Have Permission");
}

WebApplicationException はランタイム例外であるため、throws 句で例外を宣言する必要はありません。これにより、クライアントに 401 応答が返されます。

2 番目の簡単な方法は WebApplicationException、コード内で のインスタンスを直接構築することです。このアプローチは、独自のアプリケーション例外を実装する必要がない限り機能します。

例:

@Path("accounts/{accountId}/")
public Item getItem(@PathParam("accountId") String accountId) {
   // An unauthorized user tries to enter
   throw new WebApplicationException(Response.Status.UNAUTHORIZED);
}

このコードもクライアントに 401 を返します。

もちろん、これは単純な例です。必要に応じて例外をより複雑にすることができ、必要な HTTP 応答コードを生成することができます。

もう 1 つの方法は、既存の Exception をラップすることです。おそらく、アノテーションで注釈が付けられたインターフェイスObjectNotFoundExceptionを実装する小さなラッパー クラスを使用します。これは JAX-RS ランタイムに、ラップされた Exception が発生した場合に. ExceptionMapper@ProviderExceptionMapper

于 2009-03-01T02:40:38.847 に答える
39

Jersey は、パラメーターの非整列化に失敗すると com.sun.jersey.api.ParamException をスローするため、1 つの解決策は、これらのタイプの例外を処理する ExceptionMapper を作成することです。

@Provider
public class ParamExceptionMapper implements ExceptionMapper<ParamException> {
    @Override
    public Response toResponse(ParamException exception) {
        return Response.status(Status.BAD_REQUEST).entity(exception.getParameterName() + " incorrect type").build();
    }
}
于 2011-11-28T12:25:57.563 に答える
27

QueryParam で注釈が付けられた変数の再利用可能なクラスを作成することもできます

public class DateParam {
  private SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");

  private Calendar date;

  public DateParam(String in) throws WebApplicationException {
    try {
      date = Calendar.getInstance();
      date.setTime(format.parse(in));
    }
    catch (ParseException exception) {
      throw new WebApplicationException(400);
    }
  }
  public Calendar getDate() {
    return date;
  }
  public String format() {
    return format.format(value.getTime());
  }
}

次に、次のように使用します。

private @QueryParam("from") DateParam startDateParam;
private @QueryParam("to") DateParam endDateParam;
// ...
startDateParam.getDate();

この場合、エラー処理は簡単ですが (400 応答をスローします)、このクラスを使用すると、ロギングなどを含む一般的なパラメーター処理を除外できます。

于 2009-08-26T05:26:58.777 に答える
11

明らかな解決策の1つは、文字列を取り込んで、自分で日付に変換することです。これにより、必要な形式を定義し、例外をキャッチして、送信されるエラーを再スローまたはカスタマイズできます。解析の場合、SimpleDateFormatは正常に機能するはずです。

データ型のハンドラーをフックする方法もあると思いますが、この場合に必要なのは、おそらく少しの単純なコードだけです。

于 2009-02-28T01:01:49.297 に答える
1

これは実際には正しい動作です。Jersey は、入力のハンドラーを見つけようとし、提供された入力からオブジェクトを構築しようとします。この場合、コンストラクターに提供された値 X で新しい Date オブジェクトを作成しようとします。これは無効な日付であるため、慣例により、Jersey は 404 を返します。

あなたができることは、生年月日を文字列として書き換えて配置し、解析を試みることです。必要なものが得られない場合は、例外マッピングメカニズムのいずれかによって必要な例外を自由にスローできます (いくつかあります) )。

于 2015-10-20T20:08:27.040 に答える