Spring/Spring MVC

Spring MVC - HTTP API 메시지(JSON)의 Bean Validation

jddng 2022. 2. 7. 16:58
728x90
반응형

 

 

 

HTTP API 메시지(JSON)의 Bean Validation

  • @ModelAttribute : HTTP 요청 파라미터(URL 쿼리 파라미터, POST Form)를 타룰 때 사용
  • @RequestBody : HTTP Body의 데이터를 객체로 변환할 때 사용(JSON)

 

 Bean Validation는 HttpMessageConverter를 사용하는 @RequestBody에도 적용할 수 있다.

 

 API Bean Validation

 

  • 데이터 바인딩 시 타입 검증 오류가 발생하면 JSON을 객체로 생성하는 것 자체를 실패한다.
    (객체 생성에 실패하면 컨트롤러 자체가 호출되지 않고 예외가 발생)
  • 타입 검증을 통과하면 JSON을 객체로 생성하여 Bean Validation을 수행한다.

 

@Slf4j
@RestController
@RequestMapping("/validation/api/items")
public class ValidationItemApiController {

    @PostMapping("/add")
    public Object addItem(@Validated @RequestBody ItemSaveForm form, BindingResult bindingResult) {

        log.info("API 컨트롤러 호출");

        if (bindingResult.hasErrors()) {
            log.info("검증 오류 발생 errors={}", bindingResult);
            return bindingResult.getAllErrors();
        }

        log.info("성공 로직 실행");
        return form;
    }
}

 

 

Postman으로 JSON 형식으로 상황에 따른 요청 메시지를 보내보자.

 

  1. 타입 검증 오류가 발생하여 컨트롤러를 호출하지 못하고 예외가 발생
    {"itemName":"hello", "price":B, "quantity": 100}​
    응답 메시지 바디
    {
        "timestamp""2022-02-07T07:37:53.706+00:00",
        "status"400,
        "error""Bad Request",
        "message""",
        "path""/validation/api/items/add"
    }


  2. 타입 검증을 통과했지만 필드 바인딩 과정에서 검증 오류 발생
    {"itemName":"hello", "price":1000, "quantity": 10000}
    응답 메시지 바디
    [
        {
            "codes": [
                "Max.itemSaveForm.quantity",
                "Max.quantity",
                "Max.java.lang.Integer",
                "Max"
            ],
            "arguments": [
                {
                    "codes": [
                        "itemSaveForm.quantity",
                        "quantity"
                    ],
                    "arguments"null,
                    "defaultMessage""quantity",
                    "code""quantity"
                },
                9999
            ],
            "defaultMessage""9999 이하여야 합니다",
            "objectName""itemSaveForm",
            "field""quantity",
            "rejectedValue"10000,
            "bindingFailure"false,
            "code""Max"
        }
    ]


    3. 검증에 성공

    {"itemName":"hello", "price":1000, "quantity": 1000}​

    응답 메시지 바디

    {
        "itemName""hello",
        "price"1000,
        "quantity"1000
    }

 

@ModelAttribute와 @RequestBody의 차이

 

  • @ModelAttribute
         - 각각의 필드 단위로 정교하게 바인딩이 적용
         - 필드에 타입이 맞지 않는 오류가 발생해도 나머지 필드는 정상 처리 가능
         - 즉, 특정 필드가 바인딩되지 않아도 나머지 필드는 정상적으로 바인딩, 검증 처리가 가능

  • @RequestBody
         - 필드 단위로 적용되는 것이 아닌 객체 단위로 적용
         - HttpMessageConverter 단계에서 JSON 데이터를 객체로 변경하지 못하면
           컨트롤러를 호출하지 못하므로 예외가 발생

 

@Valid를 이용하여 @RequestBody 객체 검증 참고 사이트

SpringBoot API 요청 값 검증하고 Validation Exception Handing하기 (tistory.com)

@Valid 를 이용해 @RequestBody 객체 검증하기 (tistory.com)

 

 

 

 

 

 

 

 

728x90
반응형