간단히 말해 클라이언트가 서버에서 받을 데이터타입에 맞게 보내는지 확인하는 절차
ex : 몸무게 입력칸에 한글 입력...etc
검증시 오류가 발생하면 errors 에 담아둔다. 이때 어떤 필드에서 오류가 발생했는지 구분하기 위해 오류가 발생한 필드명을 key 로 사용한다.
검증오류가 나면 Model에 담아서 뷰단으로 던진다.
- 해당 페이지 처음 들어갈떄 errors 에 null이 들어있을텐데 왜 익셉션이 안터졌을까???
- 바로 erros.? 문법때문. 익셉션 대신에 null반환
- 타임리프에서 null이면 해당 코드는 무시됌(아무일도f 안일어남)
스프링에서는 BindingResult 라는 것을 사용한다. 사용할때 주의해야 할점은 검증을 할 객체가 앞에 와야한다는점
해당 객체 필드에 에러가 나면 FieldError 객체를 생성해 BindingResult 에 넣어준다.
객체 에러시 ObjectError 에 담아 BindingReuslt에 넣어준다
filedError("객체이름","필드이름","디폴트 메시지")
ObjectError("객체이름","디폴트 메세지")
model에 안담아줘도 bindingResult는 알아서 뷰단에 넘어감
해당 필드에 오류가 있으면 출력 없으면 무시
컨트룰러 필드에러 객체에 price라는 필드이름으로 담아와서 저렇게만 사용해도 가능
#field , #fields 로 bindingResult에 제공하는 오류에 접근 가능
th:errors 는 해당 필드에 오류가 있으면 출력 아니면 x
th:errorclass 는 th:field 에서 지정한 오류가 있으면 class 정보 추가(여기서는 CSS)
BindgResult 는 Error인터페이스를 상속한 인터페이스이므로 Errors 를 사용해도 됀다.
하지만 BindingResult가 제공하는 기능이 더 많으며 관례상 BindingResult를 많이 사용함
세번째 메서드는 클라이언트가 검증실패를 유도하는 값, 네번째는 binding이 잘됐는지 안됐는지
th:field 에서 이 세번째값을 꺼내서 사용하는것. 즉 사용자가 잘못입력한 값
- th:field를 사용하면 정상적인 값이 올때는 객체에서 필드값을 꺼내 사용하고 타입이 잘못됐으면 스프링이 알아서 fieldError에 잘못 입력한 값을 넣어 bindingResult에 넣어서 보낸 값을 꺼내서 반환함.
fieldError 에 Codes, arguments 는 오류 발생시 오류 코드로 메시지를 찾기 위해 사용된다.
codes: 배열 형태로 여러값을 넣을수 있으며 처음 매칭되는 메시지 사용
arguments: 치환할 값 전달
위에 쓰던 예전 방법은 에러 메세지도 일일이 넣어주고 그러면 그럴수록 파라미터도 많아지며 복잡해진다. 이럴땐 간단하게 bindingResult에서 제공하는 reject() 메서드를 사용 하면 됀다.
bindingResult는 이미 target이 누군지 안다는 점을 이용한다. 그러므로 field값을 적고, errorcode만 입력해주면 됀다. fieldError 처럼 aaa.bbb.ccc 로 작성할 필요가 없이 aaa만 입력하면 됀다. 그럼 알아서 properties 메세지에서 알아서 찾아옴
reject() 와 rejectValue()는 기본적으로 좀더 디테일한 경로의 오류메세지가 있으면 그걸 우선적으로 반환한다.
그런데 어떻게 errorCode하나만 보냈는데 알아서 디테일한 경로 오류메세지가 있으면 그걸 우선해서 가져오는 것일까??
bindingResult의 reject() , rejectValue() 는 내부적으로 messagesCodesResolver 를 사용한다.
messageCodesResolver는 특정 규칙이 있다. 그 규칙대로 가져오는것
- messageCodesResolver은 저렇게 메세지를 만들고저 값들을 각각
new ObjectError(new Stirng[])/ new FieldError(new String[])
에 나온 값들을 순서대로 넣어주고 순서대로 찾는것.
=> 즉 변경 요청이와도 개발코드는 변경할 필요없고 error.properties만 수정하면 됌
주로 타입정보가 맞지 않을때 발생 , 스프링이 자동 생성
codes[typeMismatch.item.price,typeMismatch.price,typeMismatch.java.lang.Integer,typeMismatch
위에 예제처럼 4가지로 messageCodesResolver가 만들어서 보내준다. 만약 errors.properties 에 저 4가지 내용들이 없으면 스프링이만든 디폴트 메세지 출력
컨트룰러의 검증로직이 너무크고 복잡하다. 코드 독립성을위해 따로 분리해주자.
support() = 해당 검증기를 지원하는지 여부 확인용
@Validated 애노테이션을 사용하면 WebDataBinder에 등록된 검증기를 사용한다
이때 검증기가 여러개일수 있다. 이럴때는 만들어 놓았던 supports()가 사용됀다.