본 게시물은 스스로의 공부를 위한 글입니다.
틀린 내용이 있을 수 있습니다.
public String addItem(@ModelAttribute Item item, BindingResult bindingResult) {
if (!StringUtils.hasText(item.getItemName())) {
bindingResult.addError(new FieldError("item", "itemName", "상품 이름은 필수입니다."));
}
BindingResult bindingResult
파라미터의 위치는 반드시 @ModelAttribute Item item
다음에 바로 와야 한다.FieldError(String objectName, String field, String defaultMessage)
FieldError(검증 객체 이름, 오류가 발생한 필드 이름, 오류 기본 메시지)
bindingResult.addError(new ObjectError("item", "가격 * 수량의 합은 10,000원 이상이어야 합니다. 현재 값 = " + resultPrice));
ObjectError(String objectName, String defaultMessage)
ObjectError(@ModelAttribute 이름, 오류 기본 메시지)
<input type="text" th:field="${price}" th:errorclass="field-error" class="form-control" placeholder="가격을 입력하세요">
<div class="field-error" th:errors="*{price}"> 가격 오류 </div>
th:errorclass
th:field
에서 지정한 필드에 오류가 있으면 class정보 추가th:errors
th:if
의 편의버전이다.<div th:if="${#fields.hasGlobalErrors()}">
<p class="field-error" th:each="err : ${#fields.globalErrors()}" th:text="${err}">글로벌 오류 메시지</p>
</div>
#fields
로 BindingResult
가 제공하는 검증 오류에 접근할 수 있다.BindingResult
가 인자로 없으면BindingResult
가 인자로 있으면fieldError
를 만들고 BindingResult
에 담아서 컨트롤러를 정상 호출한다.BindingResult
에 검증 오류를 적용하는 3가지 방법
@ModelAttribute
의 객체에 타입 오류 등으로 바인딩이 실패하는 경우 스프링이 FieldError
생성해서 BindingResult
에 넣어준다.
개발자가 직접 넣어준다.
Validator 사용
BindingResult
에 들어간다. FieldError
의 또다른 생성자.
FieldError(String objectName, String field, @Nullable Object rejectedValue, boolean bindingFailure, @Nullable String[] codes, @Nullable Object[] arguments, @Nullable String defaultMessage)
FieldError(오류 발생 객체 이름, 오류 필드, 사용자가 입력한 값(거절된 값), 바인딩실패?, 메시지 코드, 메시지에 이용하는 인자, 기본 메시지)
ObjectError
도 field
부분만 빼고 동일하다.
이를 통해 사용자가 입력한 오류값이 그대로 남아있게 할 수 있다.(rejectedValue
를 통해서 가능.)
바인딩 오류시에는 스프링이 알아서 사용자 입력 값을 담은 FieldError을 생성해 BindingResult에 넣어주니, 크게 신경쓰지 않아도 알아서 해준다.
th:field
는 정상 상황에서는 모델 객체 값을 사용하지만, 해당 필드의 오류 발생시 FieldError에 담긴 필드값을 사용한다. 즉, 사용자가 입력한 오류 값을 사용하므로 사용자에게 그대로 보여줄 수 있다.FieldError, ObjectError의 생성자는 errorCode
,arguments
를 제공한다. 이것은 오류 발생시 오류 코드로 메시지를 찾기 위해 사용된다.
스프링 부트는 기본 설정으로 src/main/resources/messages.properties
에서 메시지를, src/main/resources/ValidationMessages.properties
에서 유효성 검사에 대응하는 (에러)메시지를 가져온다.
application.properties
에 spring.messages.basename=messages,errors
추가
## `src/main/resources/errors.properties`에
required.item.itemName=상품 이름은 필수입니다.
range.item.price=가격은 {0} ~ {1} 까지 허용합니다.
max.item.quantity=수량은 최대 {0} 까지 허용합니다.
totalPriceMin=가격 * 수량의 합은 {0}원 이상이어야 합니다. 현재 값 = {1}
bindingResult.addError(new FieldError("item", "price", item.getPrice(), false, new String[]{"range.item.price"}, new Object[]{1000, 1000000}, null))
bindingResult.addError(new ObjectError("item", new String[] {"totalPriceMin"}, new Object[]{10000, resultPrice}, null))
errorCode
와 errorArgs
가 있다.errors.properties
에 오류 메시지를 만들어두면, 스프링에 이에 맞는 오류 메시지를 찾는다.오류 메시지는 MessageCodesResolver
이 맡는데, 오류 메시지를 찾는 메커니즘을 알아보자
객체 오류
필드 오류
cf 바인딩에 실패하면 BindingReuslt
는 typeMismatch
라는 errorCode
를 자동으로 넣는다.
BindingResult
는 Object
가 뭔지 알고있기 때문에(인자에서 오브젝트 바로 뒤에 쓰기 때문이다) 생략 가능하다.Object
를 생략한 rejectValue
, rejcet
를 사용해보자.rejectValue(@Nullable String field, String errorCode, @Nullable Object[] errorArgs, @Nullable String defaultMessage);
bindingResult.rejectValue("price", "range", new Object[]{1000, 1000000}, null)
reject(String errorCode, @Nullable Object[] errorArgs, @Nullable String defaultMessage);
사실 스프링에서 검증할땐 거의 대부분
Bean Validation
을 사용한다. 다음 게시물에서 자세히 알아보자.
인프런의 '스프링 MVC 2편(김영한)'을 스스로 정리한 글입니다.
자세한 내용은 해당 강의를 참고해주세요