網頁

2020/5/29

Spring Boot 自訂Java Bean驗證失敗回應訊息 custom bean validation fail response

Spring Boot使用bean validation驗證失敗時,預設會返回HTTP Status: 400 Bad Request及訊息。

例如下面為@Size驗證傳入參數失敗的預設回應訊息。

{
    "timestamp": "2020-05-30T05:20:24.417+0000",
    "status": 400,
    "error": "Bad Request",
    "errors": [
        {
            "codes": [
                "Size.demoRequest.password",
                "Size.password",
                "Size.java.lang.String",
                "Size"
            ],
            "arguments": [
                {
                    "codes": [
                        "demoRequest.password",
                        "password"
                    ],
                    "arguments": null,
                    "defaultMessage": "password",
                    "code": "password"
                },
                10,
                5
            ],
            "defaultMessage": "size must be between 5 and 10",
            "objectName": "demoRequest",
            "field": "password",
            "rejectedValue": "1234",
            "bindingFailure": false,
            "code": "Size"
        }
    ],
    "message": "Validation failed for object='demoRequest'. Error count: 1",
    "path": "/demo/send"
}

若要自訂的返回的訊息格式或HTTP Status狀態碼,可利用@ControllerAdvice捕捉MethodArgumentNotValidException

例如下面為bean validation驗證失敗要返回的自訂訊息類別。

DemoResponse

package com.abc.demo.controller.response;

public class DemoResponse {

    private String code;
    private String message;

    // getters and setters
}

接著建立一個掛有@ControllerAdviceDemoExceptionHandler類別來自訂回應訊息。

package com.abc.demo.exception.handler;

import com.abc.demo.controller.response.DemoResponse;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;

@ControllerAdvice
public class DemoExceptionHandler {

    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ResponseBody
    public DemoResponse handleBeanValidationFail(MethodArgumentNotValidException e) {
        DemoResponse demoResponse = new DemoResponse();
        demoResponse.setCode("9999");
        demoResponse.setMessage("Invalid input");
        return demoResponse;
    }

}

在處理方法前加上@ExceptionHandler(MethodArgumentNotValidException.class)處理bean validation驗證失敗時拋出的例外。

利用@ResponseStatus定義返回時的HTTP狀態碼,例如HttpStatus.BAD_REQUEST(400)或HttpStatus.OK(200)。

由於DemoResponse為回應主體,所以方法前加上@ResponseBody才能將其轉為json,否則Spring Boot會以ViewResolver處理。(@ControllerAdvice改用@RestControllerAdvice即可,就不用自行撰寫ResponseEntity<T>的包裝邏輯。)


設定完以上後驗證失敗時的回應訊息如下,HTTP Statu:400,也就是在DemoExceptionHandler.handleBeanValidationFail()中自訂的訊息內容。

{
    "code": "9999",
    "message": "Invalid input"
}

沒有留言:

張貼留言