何についての説明か?
- 独自のエラーレスポンスを作成する場合のやり方
- 主に、API 開発で使うことができると思います。
やりたいこと
- 以下のようなエラーレスポンスを返したい(独自エラーレスポンスを行いたい)
{
"status": 400,
"message": "リクエストの値が異なります"
}
使用するコード
今回は、タスクの作成時を想定します。
タスクを作成する時は以下のような値を入力する
- summary
- タスクの説明
- deadline
- タスクの期限日
// タスクを作成する
@PostMapping
fun createParent(
@RequestBody task: Task
) {
taskService.create(
summary = task.summary,
deadline = task.deadline
)
}
data class Task(
// タスクの説明
val summary: String,
// タスクの期限日
val deadline: Date
)
正常に動作する
$ curl -X POST -H "Content-Type: application/json" -d '{"summary":"サンプル", "deadline":"2022-04-30"}' http://localhost:8080/api/task/parent
{
"summary":"サンプル",
"deadline":"2022-04-30"
}
例外処理の作成
@RestControllerAdvice
class ApiControllerHandler : ResponseEntityExceptionHandler() {
// リクエストに入る値の型が異なる場合、エラーとなる
override fun handleHttpMessageNotReadable(
ex: HttpMessageNotReadableException,
headers: HttpHeaders,
status: HttpStatus,
request: WebRequest
): ResponseEntity<Any> {
headers.contentType = MediaType(MediaType.APPLICATION_JSON)
val res = ResponseError(
status = HttpStatus.BAD_REQUEST.value(),
message = "リクエストの値が異なります"
)
return handleExceptionInternal(ex, res, headers, status, request)
}
}
// エラーレスポンス用のクラス
class ResponseError(
val status: Int,
val message: String?
)
説明
-
@RestControllerAdvice
を宣言している- API開発の場合は、これは必須
- 「例外が発生した場合、このクラスでキャッチをして、処理をする」 ということを宣言している(例外の共通化)
-
ResponseEntityExceptionHandler()
を継承している- 例外処理を作成する際に必要なクラスであり、大部分の例外をキャッチし、処理してくれる
- このクラスを継承することで、特定の例外時のレスポンスを作成することができる(ない場合は、↓のような Spring 標準の例外が返される)
{
"timestamp": "2022-.....",
"status": 400,
.
.
}
-
HttpMessageNotReadableException
が使用されている- リクエストされた
body
の値変換が失敗した場合に出てくる例外クラス(@RequestBody
をつけると発生する) - 今回の場合、
summary
,deadline
の型が正しいかどうかを検証してくれる
- リクエストされた
-
headers.contentType = MediaType(MediaType.APPLICATION_JSON)
- JSON形式で返すことができる
-
return handleExceptionInternal(ex, res, headers, status, request)
- JSON 形式の
body
にすることができる
- JSON 形式の
エラーとなる リクエスト
$ curl -X POST -H "Content-Type: application/json" -d '{"summary":"サンプル", "deadline":"2022-04-30AAAAA"}' http://localhost:8080/api/task/parent
{
"summary":"サンプル",
"deadline":"2022-04-30AAAAA"
}
エラー集(実装している最中に出たエラーなど)
Content type 'application/x www form-urlencoded;charset=UTF-8' not supported
- レスポンスで返す際に、JSON形式にならないため、エラーになっていた
-
headers: HttpHeaders
で-
headers.contentType = MediaType(MediaType.APPLICATION_JSON)
でJSON形式にすることができる
-
Ambiguous @ExceptionHandler method mapped for [class org.springframework.web ~~~~
- クラス内に、
ResponseEntityExceptionHandler
側で既に例外処理を行ってくれている部分を、自分で作成しようとしている。(同じ名前が存在しているため、エラーとなる) -
override fun ~~
で作成しようとしていた例外処理のクラスを使うことで解決できる