코딩성장스토리

스프링 vaildation 본문

백 엔드/spring

스프링 vaildation

까르르꿍꿍 2022. 5. 9. 01:11

김영한 선생님의 MVC2편 정리

 

검증

HTTP 요청이 정상인지 우리의 요구랑 다른 값들이 들어오는지 검증하는 단계이고 스프링에서 도와주는 기능들이 있다.

 

오류 처리 방법을 도와주는  BindingResult

BindingResult bindingResult 파라미터의 위치는 @ModelAttribute Item item 다음에 와야 한다 이렇게 하면 BIndingResult는 객체 item을 알고 있고 사용이 가능하다

 

필드오류(fielderror)

 

if (!StringUtils.hasText(item.getItemName())) {
 bindingResult.addError(new FieldError("item", "itemName", "상품 이름은
필수입니다."));
}

파라미터 목록

objectName : 오류가 발생한 객체 이름

field : 오류 필드

rejectedValue : 사용자가 입력한 값(거절된 값)

bindingFailure : 타입 오류 같은 바인딩 실패인지, 검증 실패인지 구분 값

codes : 메시지 코드               -메시지 코드는 전에 했던 메시지,국제화 사용하듯이 errors.properties에 넣어서 사용함

arguments : 메시지에서 사용하는 인자

defaultMessage : 기본 오류 메시지

글로벌 오류 - ObjectError

bindingResult.addError(new ObjectError("item", "가격 * 수량의 합은 10,000원 이상이어야
합니다. 현재 값 = " + resultPrice));

특정 필드를 넘어서는 오류가 있으면 ObjectError 객체를 생성해서 bindingResult 에 담아두면 된다.

파라미터는 필드오류 랑 유사하다

 

타임리프 스프링 검증 오류 통합 기능

타임리프는 스프링의 BindingResult 를 활용해서 편리하게 검증 오류를 표현하는 기능을 제공한다.

  • #fields : #fields 로 BindingResult 가 제공하는 검증 오류에 접근할 수 있다.
  • th:errors : 해당 필드에 오류가 있는 경우에 태그를 출력한다. th:if 의 편의 버전이다.
  • th:errorclass : th:field 에서 지정한 필드에 오류가 있으면 class 정보를 추가한다

 

BindingResult에 검증 오류를 적용하는 3가지 방법

  • @ModelAttribute 의 객체에 타입 오류 등으로 바인딩이 실패하는 경우 스프링이 FieldError 생성해서 BindingResult 에 넣어준다.
  • 개발자가 직접 넣어준다.
  • Validator 사용

 

오류 발생시 사용자 입력 값 유지

new FieldError("item", "price", item.getPrice(), false, null, null, "가격은 1,000 ~ 1,000,000 까지 허용합니다."

 

하지만 이럴 경우 타입이 안 맞으면 객체에 저장이 불가능 하다.

하지만 th:field="*{price}" 타임리프의 th:field 는 매우 똑똑하게 동작하는데, 정상 상황에는 모델 객체의 값을 사용하지만, 오류가 발생하면 FieldError 에서 보관한 값을 사용해서 값을 출력한다

 

 

 

하지만 위와 같은 필드 오류와 글로벌 오류를 다루기는 인자가 많기도 하고 중복이 많다 이를 편히 만든게

rejectValue() 

BindingResult 가 제공하는 rejectValue()를 사용하면 FieldError , ObjectError 를 직접 생성하지 않고, 깔끔하게 검증 오류를 다룰 수 있다.

void rejectValue(@Nullable String field, String errorCode,
@Nullable Object[] errorArgs, @Nullable String defaultMessage);

field : 오류 필드명

errorCode : 오류 코드(이 오류 코드는 메시지에 등록된 코드가 아니다. 

errorArgs : 오류 메시지에서 {0} 을 치환하기 위한 값

defaultMessage : 오류 메시지를 찾을 수 없을 때 사용하는 기본 메시지

 

위에가 가능한 이유는 BindingResult가 이미 바인딩할 객체를 알고 있고 위의 오류코드를 단순하게

FieldError rejectValue("itemName", "required") 적용이 가능하다 .이유는

다음 4가지 오류 코드를 자동으로 생성하고 위에서 부터 우선순위가 적용이 된다.

required.item.itemName

required.itemName

required.java.lang.String

required

ObjectError reject("totalPriceMin")

다음 2가지 오류 코드를 자동으로 생성

totalPriceMin.item

totalPriceMin

 

하지만 위의 기능들은 타입이 다른것들을 오류처리할 수 없다

스프링은 타입 오류가 발생하면 typeMismatch 라는 오류 코드를 사용한다

typeMismatch.item.price

typeMismatch.price

typeMismatch.java.lang.Integer

typeMismatch

위의 메시지 코드를 정리하면 타입이 다른 것들도 오류처리가 가능하다.

 

 

 

검증 부분 분리하기

이떄 쓰이는 인터페이스

public interface Validator {
boolean supports(Class<?> clazz);
void validate(Object target, Errors errors);
}

supports() {} : 해당 검증기를 지원하는 여부 확인(뒤에서 설명)

validate(Object target, Errors errors) : 검증 대상 객체와 BindingResult   (errors가 binding Result 상위클래스)

 

 

WebDataBinder 는 스프링의 파라미터 바인딩의 역할을 해주고 검증 기능도 내부에 포함한다.

컨트롤러에 포함하면 검증기 전부 사용가능

@InitBinder
public void init(WebDataBinder dataBinder) {
 log.info("init binder {}", dataBinder);
 dataBinder.addValidators(itemValidator);
}

@Validated 는 검증기를 실행하라는 애노테이션이다.

이 애노테이션이 붙으면 앞서 WebDataBinder 에 등록한 검증기를 찾아서 실행한다.

그런데 여러 검증기를 등록한다면 그 중에 어떤 검증기가 실행되어야 할지 구분이 필요하다.

이때 supports() 가 사용된다. 여기서는 supports(Item.class) 호출되고, 결과가 true 이므로 ItemValidator 의 validate() 가 호출된다

 

@PostMapping("/add")
public String addItem(@Validated @ModelAttribute("item") ItemSaveForm form,
BindingResult bindingResult, RedirectAttributes redirectAttributes) {
 //...
}

위 코드처럼 검증할 객체앞에 @vaildated 붙이기

 

 

 

 

'백 엔드 > spring' 카테고리의 다른 글

스프링 -쿠키,세션  (0) 2022.05.13
스프링 Bean Validation  (0) 2022.05.09
스프링 메시지,국제화  (0) 2022.05.06
스프링 타임리프 스프링 통합기능  (0) 2022.05.06
spring 타임리프 기본기능  (0) 2022.05.05