REST WebサービスでHTTPステータスコードを設定するにはいくつかのユースケースがあり、少なくとも1つは既存の回答で十分に文書化されていません(つまり、JAXBを使用して自動魔法のJSON / XMLシリアル化を使用していて、シリアル化されるオブジェクトですが、デフォルトの200とは異なるステータスコードも含まれます。
そこで、さまざまなユースケースとそれぞれのソリューションを列挙してみましょう。
1.エラーコード(500、404など)
200 OK
エラーが発生したときとは異なるステータスコードを返したい場合の最も一般的な使用例。
例えば:
- エンティティが要求されたが存在しない(404)
- リクエストが意味的に正しくない(400)
- ユーザーは承認されていません(401)
- データベース接続に問題があります(500)
- 等..
a)例外をスローする
その場合、問題を処理する最もクリーンな方法は例外をスローすることだと思います。この例外はExceptionMapper
、例外を適切なエラーコードを含む応答に変換するによって処理されます。
ExceptionMapper
Jerseyで事前構成されているデフォルトを使用でき(他の実装でも同じだと思います)、の既存のサブクラスをスローできjavax.ws.rs.WebApplicationException
ます。これらは、さまざまなエラーコードに事前にマップされている事前定義の例外タイプです。次に例を示します。
- BadRequestException(400)
- InternalServerErrorException(500)
- NotFoundException(404)
リストはここにあります:API
または、独自のカスタム例外とExceptionMapper
クラスを定義し、これらのマッパーを@Provider
アノテーション(この例のソース)を使用してジャージーに追加できます。
public class MyApplicationException extends Exception implements Serializable
{
private static final long serialVersionUID = 1L;
public MyApplicationException() {
super();
}
public MyApplicationException(String msg) {
super(msg);
}
public MyApplicationException(String msg, Exception e) {
super(msg, e);
}
}
プロバイダー:
@Provider
public class MyApplicationExceptionHandler implements ExceptionMapper<MyApplicationException>
{
@Override
public Response toResponse(MyApplicationException exception)
{
return Response.status(Status.BAD_REQUEST).entity(exception.getMessage()).build();
}
}
注:使用する既存の例外タイプに対してExceptionMappersを作成することもできます。
b)Response Builderを使用する
ステータスコードを設定するもう1つの方法は、Response
ビルダーを使用して、目的のコードで応答を作成することです。
その場合、メソッドの戻り値の型はでなければなりませんjavax.ws.rs.core.Response
。これは、hisdrewnessが受け入れた回答など、他のさまざまな応答で説明されており、次のようになります。
@GET
@Path("myresource({id}")
public Response retrieveSomething(@PathParam("id") String id) {
...
Entity entity = service.getById(uuid);
if(entity == null) {
return Response.status(Response.Status.NOT_FOUND).entity("Resource not found for ID: " + uuid).build();
}
...
}
2.成功、ただし200
戻りステータスを設定したい場合のもう1つのケースは、操作は成功したが、200以外の成功コードと本文で返すコンテンツを返す場合です。
よくある使用例は、新しいエンティティ(POST
リクエスト)を作成し、この新しいエンティティまたはエンティティ自体に関する情報を201 Created
ステータスコードとともに返したい場合です。
1つのアプローチは、上記のように応答オブジェクトを使用し、リクエストの本文を自分で設定することです。ただし、これを行うと、JAXBによって提供されるXMLまたはJSONへの自動シリアル化を使用する機能が失われます。
これは、JAXBによってJSONにシリアル化されるエンティティオブジェクトを返す元のメソッドです。
@Path("/")
@POST
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public User addUser(User user){
User newuser = ... do something like DB insert ...
return newuser;
}
これにより、新しく作成されたユーザーのJSON表現が返されますが、戻りステータスは201ではなく200になります。
問題は、Response
ビルダーを使用して戻りコードを設定するResponse
場合、メソッドでオブジェクトを返さなければならないことです。User
シリアル化するオブジェクトを返すにはどうすればよいですか?
a)サーブレット応答にコードを設定します
これを解決する1つの方法は、サーブレットリクエストオブジェクトを取得して、手動で応答コードを設定することです。
@Path("/")
@POST
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public User addUser(User user, @Context final HttpServletResponse response){
User newUser = ...
//set HTTP code to "201 Created"
response.setStatus(HttpServletResponse.SC_CREATED);
try {
response.flushBuffer();
}catch(Exception e){}
return newUser;
}
メソッドは引き続きエンティティオブジェクトを返し、ステータスコードは201になります。
これを機能させるには、応答をフラッシュする必要があったことに注意してください。これは、優れたJAX_RSリソースでの低レベルのサーブレットAPIコードの不快な復活であり、さらに悪いことに、ヘッダーがすでにネットワーク上に送信されているため、ヘッダーが変更できなくなります。
b)エンティティで応答オブジェクトを使用する
その場合の最善の解決策は、Responseオブジェクトを使用して、この応答オブジェクトでシリアル化するエンティティを設定することです。その場合、ペイロードエンティティのタイプを示すためにResponseオブジェクトをジェネリックにするのは良いことですが、現在はそうではありません。
@Path("/")
@POST
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public Response addUser(User user){
User newUser = ...
return Response.created(hateoas.buildLinkUri(newUser, "entity")).entity(restResponse).build();
}
その場合、ステータスコードを201に設定するために、Responseビルダークラスの作成されたメソッドを使用します。entity()メソッドを介してエンティティオブジェクト(ユーザー)を応答に渡します。
その結果、HTTPコードは必要な401になり、応答の本文は、前にUserオブジェクトを返したときとまったく同じJSONになります。また、ロケーションヘッダーも追加します。
Responseクラスには、次のようなさまざまなステータス(stati?)用のいくつかのビルダーメソッドがあります。
Response.accepted()Response.ok()Response.noContent()Response.notAcceptable()
注意:hateoasオブジェクトは、リソースURIの生成を支援するために開発したヘルパークラスです。ここで独自のメカニズムを考え出す必要があります;)
それだけです。
この長い応答が誰かを助けることを願っています:)