[Spring MVC] 검증 - Validator
Validator 분리1
컨트롤러에서 검증 로직이 차지하는 부분이 매우 크기 때문에 별도의 클래스로 역할을 분리하는 것이 좋다.
ItemValidator.class
@Component
public class ItemValidator implements Validator {
@Override
public boolean supports(Class<?> clazz) {
return Item.class.isAssignableFrom(clazz);
}
@Override
public void validate(Object target, Errors errors) {
Item item = (Item) target;
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "itemName", "required");
// 컨트롤러에 있던 검증 로직을 모두 이곳에 넣는다.
// bindingResult대신 errors 파라미터를 사용한다.
}
}
public interface Validator {
boolean supports(Class<?> clazz);
void validate(Object target, Errors errors);
}
supports() {}
: 해당 검증기를 지원하는 여부 확인validate()
: 검증 대상 객체와BindingResult
addItemV5
private final ItemValidator itemValidator;
// ...
itemValidator.validate(item, bindingResult);
if (bindingResult.hasErrors()) {
log.info("errors={}", bindingResult);
return "validation/v2/addForm";
}
Validator 분리2
스프링이 Validator
인터페이스를 별도로 제공하는 이유는 체계적으로 검증 기능을 도입하기 위해서다. 앞에서는 검증기를 직접 불러서 사용했지만, Validator
인터페이스를 사용해서 검증기를 만들면 스프링의 추가적인 도움을 받을 수 있다.
WebDataBinder
WebDataBinder
는 스프링의 파라미터 바인딩의 역할을 해주고 검증 기능도 내부에 포함한다.
Controller에 다음 코드 추가
@InitBinder
public void init(WebDataBinder dataBinder) {
log.info("init binder {}", dataBinder);
dataBinder.addValidators(itemValidator);
}
WebDataBinder
에 검증기를 추가하면 해당 컨트롤러에서는 검증기를 자동으로 적용.@InitBinder
-> 해당 컨트롤러에만 영향을 준다.
@Validated 적용
Controller
@PostMapping("/add")
public String addItemV6(@Validated @ModelAttribute Item item, BindingResult bindingResult, RedirectAttributes redirectAttributes) {
if (bindingResult.hasErrors()) {
log.info("errors={}", bindingResult);
return "validation/v2/addForm";
}
}
validator를 직접 호출하는 부분이 사라지고, 검증 대상 앞에 @Validated
가 붙었다.
동작 방식
@Validated
는 검증기를 실행하라는 애노테이션이다.
이 애노테이션이 붙으면 앞서 WebDataBinder
에 등록한 검증기를 찾아서 실행한다.
이때 여러 검증기를 등록한다면 그 중에 어떤 검증기가 실행되어야 할지 구분이 필요한데 이때 supports()
가 사용된다.
여기서는 supports(Item.class)
가 호출되고, 결과가 true
이므로 ItemValidator
의 validate()
가 호출된다.
<출처 : 인프런 스프링 MVC 2편 - 백엔드 웹 개발 활용 기술(김영한)>
댓글남기기