1. 概要

このクイックチュートリアルでは、Spring5で導入された新しいResponseStatusExceptionクラスについて説明します。 このクラスは、HTTP応答へのHTTPステータスコードの適用をサポートします。

RESTfulアプリケーションは、クライアントへの応答で正しいステータスコードを返すことにより、HTTPリクエストの成功または失敗を伝えることができます。 簡単に言えば、適切なステータスコードは、アプリケーションが要求を処理している間に発生した可能性のある問題をクライアントが特定するのに役立ちます。

2. ResponseStatus

ResponseStatusExceptionについて詳しく説明する前に、 @ResponseStatusアノテーションを簡単に見てみましょう。 このアノテーションは、HTTPステータスコードをHTTP応答に適用するためにSpring3で導入されました

@ResponseStatus アノテーションを使用して、HTTP応答のステータスと理由を設定できます。

@ResponseStatus(code = HttpStatus.NOT_FOUND, reason = "Actor Not Found")
public class ActorNotFoundException extends Exception {
    // ...
}

HTTPリクエストの処理中にこの例外がスローされた場合、レスポンスにはこのアノテーションで指定されたHTTPステータスが含まれます。

@ResponseStatus アプローチの欠点の1つは、例外との密結合が作成されることです。 この例では、タイプ ActorNotFoundException のすべての例外は、応答で同じエラーメッセージとステータスコードを生成します。

3. ResponseStatusException

ResponseStatusException は、 @ResponseStatus のプログラムによる代替であり、ステータスコードをHTTP応答に適用するために使用される例外の基本クラスです。 これはRuntimeExceptionであるため、メソッドシグネチャに明示的に追加する必要はありません。

Springは、 ResponseStatusException:を生成するための3つのコンストラクターを提供します

ResponseStatusException(HttpStatus status)
ResponseStatusException(HttpStatus status, java.lang.String reason)
ResponseStatusException(
  HttpStatus status, 
  java.lang.String reason, 
  java.lang.Throwable cause
)

ResponseStatusException、コンストラクター引数:

  • status –HTTP応答に設定されたHTTPステータス
  • 理由–HTTP応答に設定された例外を説明するメッセージ
  • 原因– ThrowableResponseStatusExceptionの原因

注:Springでは、 HandlerExceptionResolver は、コントローラーによって発生し、処理されない例外をインターセプトして処理します。

これらのハンドラーの1つ、 ResponseStatusExceptionResolver、 何かを探します ResponseStatusException またはによって注釈が付けられたキャッチされない例外 @ResponseStatus 次に、HTTPステータスコードと理由を抽出し、それらをHTTP応答に含めます。

3.1. ResponseStatusExceptionの利点

ResponseStatusException の使用には、いくつかの利点があります。

  • まず、同じタイプの例外を個別に処理し、応答に異なるステータスコードを設定して、密結合を減らすことができます。
  • 第二に、不要な追加の例外クラスの作成を回避します
  • 最後に、例外はプログラムで作成できるため、例外処理をより細かく制御できます。

4. 例

4.1. ResponseStatusExceptionを生成します

次に、ResponseStatusExceptionを生成する例を見てみましょう。

@GetMapping("/actor/{id}")
public String getActorName(@PathVariable("id") int id) {
    try {
        return actorService.getActor(id);
    } catch (ActorNotFoundException ex) {
        throw new ResponseStatusException(
          HttpStatus.NOT_FOUND, "Actor Not Found", ex);
    }
}

Spring Bootは、デフォルトの / error マッピングを提供し、HTTPステータスのJSON応答を返します。

応答は次のようになります。

$ curl -i -s -X GET http://localhost:8081/actor/8
HTTP/1.1 404
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Sat, 26 Dec 2020 19:38:09 GMT

{
    "timestamp": "2020-12-26T19:38:09.426+00:00",
    "status": 404,
    "error": "Not Found",
    "message": "",
    "path": "/actor/8"
}

2.3バージョン以降、Spring Bootのデフォルトのエラーページにエラーメッセージが含まれていません。 その理由は、クライアントに情報が漏洩するリスクを減らすためです。

デフォルトの動作を変更するには、server.error.include-messageプロパティを使用できます。

常にに設定して、何が起こるか見てみましょう。

$ curl -i -s -X GET http://localhost:8081/actor/8
HTTP/1.1 404
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Sat, 26 Dec 2020 19:39:11 GMT

{
    "timestamp": "2020-12-26T19:39:11.426+00:00",
    "status": 404,
    "error": "Not Found",
    "message": "Actor Not Found",
    "path": "/actor/8"
}

ご覧のとおり、今回の応答には、「ActorNotFound」エラーメッセージが含まれています。

4.2. 異なるステータスコード–同じ例外タイプ

次に、同じタイプの例外が発生したときに、異なるステータスコードがHTTP応答にどのように設定されるかを見てみましょう。

@PutMapping("/actor/{id}/{name}")
public String updateActorName(
  @PathVariable("id") int id, 
  @PathVariable("name") String name) {
 
    try {
        return actorService.updateActor(id, name);
    } catch (ActorNotFoundException ex) {
        throw new ResponseStatusException(
          HttpStatus.BAD_REQUEST, "Provide correct Actor Id", ex);
    }
}

応答は次のようになります。

$ curl -i -s -X PUT http://localhost:8081/actor/8/BradPitt
HTTP/1.1 400
...
{
    "timestamp": "2018-02-01T04:28:32.917+0000",
    "status": 400,
    "error": "Bad Request",
    "message": "Provide correct Actor Id",
    "path": "/actor/8/BradPitt"
}

5. 結論

このクイックチュートリアルでは、プログラムでResponseStatusExceptionを作成する方法について説明しました。

また、 @ResponseStatus アノテーションよりも、プログラムでHTTPResponseにHTTPステータスコードを設定する方が優れていることも強調しました。

いつものように、完全なソースコードはGitHubから入手できます。