상세 컨텐츠

본문 제목

BindingResult

spring

by finite라이프 2024. 4. 20. 02:43

본문

BindingResult에 대해 적어보겠다.

사용자가 input form에 이상한 값(숫자를 넣어야 하는데 문자를 넣는다는 둥..)이나 공백을 넣거나 터무니없는 값(999999....)등을 넣는 등 개발자가 원하는 제대로 된 값을 넣지 않을 때, 에러가 나서 문제가 생기는 것을 방지하기 위해 쓰이는 것이 BindingResult이다.

예를 들어

@PostMapping
public String register(@ModelAttribute User user) {

이런 메서드가 있다고 해보자. 이 메서드에는 User type 객체가 들어가는데, User class안에는 String type의 userName이라는 필드가 있다. 그런데 사용자가 input form에 123이라는 int값을 넣었다고 할때, 이 메서드는 실행되지 않고, typeMismatch오류가 난다. 

 

이때 BindingResult가 있으면 @ModelAttribute에 데이터 바인딩 시 오류가 발생해도 컨트롤러가 호출된다. 이는 스프링이 FieldError를 생성해서 BindingResult에 넣어주기 때문이다. (@RequestBody로 데이터를 받아올 시 컨트롤러가 호출되지 않고 에러가 난다. 이는 HttpMessageConverter가 @ModelAttribute와 다르게 각각의 필드 단위로 적용되는 것이 아닌 전체 객체 단위로 적용되기 때문이다. @RequestBody는 HttpMessageConverter 단계에서 JSON데이터를 객체로 변경하지 못하면 이후 단계 자체가 진행되지 않고 예외가 발생한다. 컨트롤러도 호출되지 않고 Validator도 적용할 수 없다.)따라서 타입 오류같은 바인딩 실패시에도 사용자의 오류메시지를 정상출력 할 수 있다.

BindingResult는 검증할 대상 바로 다음에 와야한다. 순서가 중요한데 @ModelAttribute 파라미터 바로 다음에 와야한다.

@PostMapping("login")
public String doLogin( @ModelAttribute("userLogin") UserLogin userLogin, BindingResult bindingResult) {

이렇게 와야한다.

 

BindingResult는 인터페이스이고 Errors인터페이스를 상속받고 있다. Errors는 단순한 오류 저장과 조회 기능을 제공한다. BindingResult는 여기에 추가 기능이 더해진다.(addError등) BindingResult의 구현체는 BeanPropertyBindingResult이다.

바인딩리절트에 에러를 추가하는 예시:

bindingResult.addError(new FieldError("객체이름","객체필드이름",rejectedValue,false,null,null,"default message"));

bindingResult.addError(new ObjectError("item",null,null,"default message"));

객체의 필드에서 에러가 나면 FieldError를 만들어 addError메서드의 인자로 넣어준다.

객체의 특정 필드 예외가 아닌 필드들의 조합으로 생긴 에러(가격*상품수가 허용치보다 높을때)가 나면 ObjectError를 만들어 addError메서드의 인자로 넣어준다.

fieldError의 생성자

ObjectError의 생성자

타임리프의 th:field는 정상 상활일때는 모델 객체의 필드값을 사용하지만, 오류가 발생하면 FieldError에서 보관한 값을 사용해서 값을 출력한다.

 

BindingResult가 제공하는 rejectValue(),reject()를 사용하면 bindingResult.addError(new FieldError 또는 ObjectError)를 쓰지않고 검증오류를 다룰 수 있다.

예시:

bindingResult.rejectValue("itemName","required") <-필드에러

bindingResult.reject("totalPriceMin",new Object[]{10000,resultPrice},null) <- Object에러

 

rejectValue의 파라미터

3개가 오버로딩 돼있다.

reject의 파라미터

마찬가지로 3개가 오버로딩 돼있다.

 

관련글 더보기

댓글 영역