입력값 검증
ModelAttribute나 RequestBody로 입력값을 검증할때 모든 입력값들을 if문으로 하나하나 검증하게 된다면 컨트롤러단의 코드가 굉장히 복잡해진다. 따라서 재사용가능하고 비즈니스 로직과 분리가 필요하다.
Bean Validation
java SE, java EE 에서 사용되는 java beans 검증용 java API spec
재사용가능하고 비즈니스 로직과 분리
public String modifyUser(@Valid @ModelAttribute UserModifyRequest userRequest,
BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
throw new ValidationFailedException(bindingResult);
}
}
BindingResult가 있다면 hasErrors로 에러를 던지지 않으면 BindingResult에서 에러를 잡아서 에러가 나오지 않는다. 따라서 Error를 던질시에 hasErrors를 통해서 에러를 던지거나 @Valid만 넣어서 MethodArgumentValidException을 잡으면된다.
참고로 ExceptionHandlerResolver가 ControllerAdvice에 있는 Exception이 나면 찾아서 DispatcherServlet에게 보내주는데, 이걸 이용해서 AOP를 사용해 Controller에 있는 검증 코드들도 없앨수 있을 것 같은데 이건 나중에 ControllerAdvice에 대해서 설명하면서 다루겠습니다.
스프링 Validation
WebDataBinder
- 스프링에서는 사용자의 요청과 자바 빈 객체를 바인딩할 수 있는 WebDataBinder객체를 제공합니다.
- addValidators를 이용해서 validator 를 추가합니다.
@InitBinder
- 특정 컨트롤러 또는 전체 애플리케이션에 대해 데이터 바인딩과 유효성 검사를 커스터마이징하는 데 사용
- WebDataBinder를 설정하여 사용자 요청에 대한 데이터 바인딩을 설정
- 전역적으로 사용하고 싶다면 @ControllerAdvice 가 정의된 클래스에서 사용
- 특정 객체에 매핑가능
사용예제
@Component
public class PostRegisterRequestValidator implements Validator {
@Override
public boolean supports(Class<?> clazz) {
return PostRegisterRequest.class.equals(clazz);
}
@Override
public void validate(Object target, Errors errors) {
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "title", "", "title is empty");
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "content", "", "content is empty");
PostRegisterRequest request = (PostRegisterRequest) target;
String content = request.getContent();
if (content.length() > 100) {
errors.rejectValue("content", "", "content max length is 100");
}
}
}
@Controller
@RequestMapping("/post/register")
@RequiredArgsConstructor
public class PostRegisterController {
private final PostRepository postRepository;
// TODO #3: `Validator` 추가
private final PostRegisterRequestValidator validator;
// TODO #2: `@Valid` 또는 `@Validated` annotation 적용
@PostMapping
public ModelAndView registerPost(@Validated @ModelAttribute PostRegisterRequest postRequest,
BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
throw new ValidationFailedException(bindingResult);
}
//.....
return mav;
}
// TODO #3: `@InitBinder`를 통해 Validator 지정
@InitBinder("postRegisterRequest")
protected void initBinder(WebDataBinder binder) {
binder.addValidators(validator);
}
}
ControllerAdvice를 사용해 전역으로 사용할 수 있다.
'Spring > Spring Boot MVC' 카테고리의 다른 글
Spring MVC Components(구성 요소) (0) | 2024.08.18 |
---|---|
Spring MVC에서의 Exception Handling, Exception 종류 (0) | 2024.08.04 |
Controller Method에 사용가능한 것 (0) | 2024.08.03 |
Spring Web Mvc 자동설정 코드 따라가기 (0) | 2024.08.03 |
Spring Boot MVC 소개 (0) | 2024.07.30 |