검증-Validation
- 컨트롤러의 역할: HTTP 요청이 정상인지 검증
- 정상: PRG
직접 개발
//Map
Map<String, String> errors = new HashMap<>(); //<필드명, 에러메시지>
errors.put("itemName", "상품 이름은 필수입니다.");
!errors.isEmpty()-> 모델에 담고 다시 입력 폼으로
th:if="${errors?.containsKey('globalError')}"
th:text="${errors['globalError']}"
th:classappend="${errors?.containsKey('itemName')} ? 'field-error' : _"
th:if="${errors?.containsKey('itemName')}" th:text="${errors['itemName']}"
- errors?. : null일 때 null반환
BindingResult
//Map->BindingResult
bindingResult.addError(new FieldError("item", "itemName", "상품 이름은
필수입니다."));//@ModelAttribute명, 필드명, 오류메시지
bindingResult.addError(new ObjectError("item", "가격 * 수량의 합은 10,000원") //글로벌 오류
bindingResult.hasErrors()->다시 입력 폼으로
th:if="${#fields.hasGlobalErrors()}"
th:each="err : ${#fields.globalErrors()}" th:text="${err}"
th:errorclass="field-error"
th:errors="*{itemName}"
- 순서지키기 @ModelAttribute Item item, BindingResult bindingResult
- 오류가 있는 경우에 태그 출력
- BindingResult: 데이터 바인딩 오류->BindingResult에 담아 컨트롤러
정상 호출
FieldError, ObjectError
public FieldError(String objectName, String field, @Nullable Object
rejectedValue, boolean bindingFailure, @Nullable String[] codes,
@Nullable Object[] arguments, @Nullable String defaultMessage)
- th:field="*{price}"는 FieldError에서 보관한 값 출력
오류 코드와 메시지 처리
- errors.properties
- application.properties: spring.messages.basename=messages,errors
max.item.quantity=수량은 최대 {0} 까지 허용합니다. new FieldError("item", "quantity",item.getQuantity(), false, new String[]{"max.item.quantity"}, new Object[]{9999}, null)
- FieldError , ObjectError -> rejectValue() , reject()
bindingResult.rejectValue("quantity", "max", new Object[]{9999}, null); bindingResult.reject("totalPriceMin", new Object[]{10000, resultPrice}, null);
- MessageCodesResolver: 검증 오류 코드로 메시지 코드 생성
- resolveMessageCodes("range","item", "price", Integer.class);
- codes [range.item.price, range.price, range.java.lang.Integer, range]
- ValidationUtils: Empty , 공백
ValidationUtils.rejectIfEmptyOrWhitespace(bindingResult, "itemName", "required");
스프링이 직접 만든 오류 메시지
- 타입 오류: codes [typeMismatch.item.price, typeMismatch.price, typeMismatch.java.lang.Integer, typeMismatch]
- typeMismatch.java.lang.Integer=숫자를 입력해주세요.
Validator 분리
Validator
Validator supports(Class<?> clazz) validate(Object target, Errors errors) //컨트롤러 주입 private final ItemValidator itemValidator; itemValidator.validate(item, bindingResult);
- WebDataBinder: 검증기 자동 적용
컨트롤러에 추가 @InitBinder public void init(WebDataBinder dataBinder) { dataBinder.addValidators(itemValidator); }
검증-Bean Validation
- 검증 애노테이션과 여러 인터페이스의 모음
- @NotBlank: 빈값 + 공백체크
- @NotNull
- @Range(min = 1000, max = 1000000)
- @Max(9999)
@Validated(스프링 전용)
addItem(@Validated @ModelAttribute Item item, BindingResult bindingResult, RedirectAttributes redirectAttributes)
spring-boot-starter-validation 라이브러리: Bean Validator자동 인지
@ModelAttribute 타입변환시도->실패(typeMismatch) FieldError추가
@ModelAttribute 타입변환시도->성공 Validator 적용
에러 코드
- NotBlank.item.itemName, NotBlank.itemName, NotBlank.java.lang.String, NotBlank
- NotBlank={0} 공백X //{0}은 필드명
- @NotBlank(message = "공백! {0}")
오브젝트 오류
- @ScriptAssert(lang = "javascript", script = "_this.price * _this.quantity >= 10000")
- 자바 코드 작성 권장
bindingResult.reject("totalPriceMin", new Object[]{10000, resultPrice}, null);
한계
등록, 수정 요구사항 다름
BeanValidation의 groups(@Validated만 가능, @Valid 안됨)
public interface SaveCheck public interface UpdateCheck //아이템에 적용 @NotNull(groups = UpdateCheck.class) @NotBlank(groups = {SaveCheck.class, UpdateCheck.class}) //컨트롤러에 적용 @Validated(SaveCheck.class)//저장로직 @Validated(UpdateCheck.class)//수정로직
등록시 폼 데이터 도메인 객체와 맞지않음->폼 전송을 위한 별도의 모델 객체
public class ItemSaveForm public class ItemUpdateForm @Validated @ModelAttribute("item") ItemSaveForm form Item item = new Item(); item.setItemName(form.getItemName()); itemRepository.save(item); @Validated @ModelAttribute("item") ItemUpdateForm form Item itemParam = new Item(); itemParam.setItemName(form.getItemName()); itemRepository.update(itemId, itemParam);
@ModelAttribute("item")안적어주면 ItemSaveForm -> itemSaveForm
HTTP 메시지 컨버터
- HttpMessageConverter(@RequestBody)에도 적용
- @RequestBody @Validated ItemSaveForm form
- 성공 < 검증 오류(Validator) < 객체 생성 실패(HttpMessageConverter->ItemSaveForm)
- @ModelAttribute(필드 단위), @RequestBody(객체를 만들어야 @Valid , @Validate 적용)
링크
https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-mvc-2
'스프링' 카테고리의 다른 글
예외 처리 (0) | 2022.06.19 |
---|---|
로그인 (0) | 2022.06.18 |
타임리프 (0) | 2022.06.16 |
[스프링] 스프링 MVC (0) | 2022.06.09 |
[스프링] MVC 프레임워크 (0) | 2022.06.09 |