APIで入力の検証エラーを検知する方法
バージョン4.5.9以降、OpenLegacy契約(コントラクト)ベースのAPIは、すぐに契約(コントラクト)フィールドの制限を適用します。 Springのフィールド検証のデフォルトの例外処理は、空のエラーメッセージとともにHTTP BadRequestレスポンスコードを返えします。
以下で簡単な2つのSpringのデフォルトの振舞いを変更する方法を説明します。ユーザは有益なエラーメッセージを受け取ることができます。
カスタムContollerAdvice クラスの定義
ユーザに検証エラーメッセージを提供するためには、カスタム @RestControllerAdvice
クラスを定義し、 MethodArgumentNotValidException
を処理します。
コントローラパッケージ内部でカスタムクラスを作成します。
クラスに以下のコードを追加します。
@ControllerAdvice public class CustomExceptionHandler { @ExceptionHandler(value = { MethodArgumentNotValidException.class }) public ResponseEntity<Map<String, Object>> handleConflict(MethodArgumentNotValidException ex, WebRequest request) { Map<String, Object> m = new LinkedHashMap<>(); m.put("timestamp", new Date()); m.put("status", HttpStatus.BAD_REQUEST.value()); m.put("error",HttpStatus.BAD_REQUEST.getReasonPhrase()); m.put("message",ex.getLocalizedMessage()); m.put("path",request.getContextPath()); return new ResponseEntity<>(m, HttpStatus.BAD_REQUEST); } }
これで、違反したフィールドが発生する度に、ユーザにエラーメッセージが表示され、エラーは次のようになります:
{ "timestamp": 1595511289924, "status": 400, "error": "Bad Request", "message": "org.springframework.web.bind.MethodArgumentNotValidException: Validation failed for argument [0] in public com.cics_api.openlegacy.PostPetsPet com.cics_api.openlegacy.services.controllers.PostPetsController.postPets(com.cics_api.openlegacy.PostPetsNewPet) throws java.lang.Exception: [Field error in object 'postPetsNewPet' on field 'id': rejected value [0]; codes [Min.postPetsNewPet.id,Min.id,Min.java.lang.Integer,Min]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [postPetsNewPet.id,id]; arguments []; default message [id],1]; default message [must be greater than or equal to 1]] ", "path": "uri=/api/api/pets" }
返信されるメッセージ形式は、必要に応じてコントローラアドバイスで簡単にカスタマイズできます。
application.yml
へプロパティの追加
Spring-Bootバージョン2.3.0以降に適応できます。 もう1つのオプションは、エラーレスポンスに例外メッセージを含むプロパティを追加することです。
application.yml
を開き、以下のプロパティを追加しますserver: error: include-message: always include-binding-errors: always
server.error.include-message = always
を追加することで、エラーは次のようになります:{ "timestamp": "2020-07-22T12:01:38.606+00:00", "status": 400, "error": "Bad Request", "message": "Validation failed for object='customerModel'. Error count: 1", "path": "/api/service/Customer" }
server.error.include-binding-errors=always
を追加することで、エラーは次のようになります:{ "timestamp": "2020-07-22T12:07:15.570+00:00", "status": 400, "error": "Bad Request", "message": "", "errors": [ { "codes": [ "NotNull.customerModel.firstName", "NotNull.firstName", "NotNull.java.lang.String", "NotNull" ], "arguments": [ { "codes": [ "customerModel.firstName", "firstName" ], "arguments": null, "defaultMessage": "firstName", "code": "firstName" } ], "defaultMessage": "must not be null", "objectName": "customerModel", "field": "firstName", "rejectedValue": null, "bindingFailure": false, "code": "NotNull" } ], "path": "/api/service/Customer" }
関連情報:
https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-error-handling
https://www.baeldung.com/exception-handling-for-rest-with-spring#controlleradvice