오봉이와 함께하는 개발 블로그
스프링 MVC 2 - Bean Validator 스프링 적용 본문
Bean Validation - 스프링 적용
ValidationItemControllerV3 코드 수정
@Controller
@RequestMapping("/validation/v3/items")
@RequiredArgsConstructor
@Slf4j
public class ValidationItemControllerV3 {
private final ItemRepository itemRepository;
@GetMapping
public String items(Model model) {
List<Item> items = itemRepository.findAll();
model.addAttribute("items", items);
return "validation/v3/items";
}
@GetMapping("/{itemId}")
public String item(@PathVariable long itemId, Model model) {
Item item = itemRepository.findById(itemId);
model.addAttribute("item", item);
return "validation/v3/item";
}
@GetMapping("/add")
public String addForm(Model model) {
model.addAttribute("item", new Item());
return "validation/v3/addForm";
}
@PostMapping("/add")
public String addItem(@Validated @ModelAttribute Item item, BindingResult bindingResult, RedirectAttributes redirectAttributes, Model model) {
// 검증에 실패하면 다시 입력 폼으로
if (bindingResult.hasErrors()) {
log.info("errors = {}", bindingResult);
return "validation/v3/addForm";
}
// 검증 성공했을 때
Item savedItem = itemRepository.save(item);
redirectAttributes.addAttribute("itemId", savedItem.getId());
redirectAttributes.addAttribute("status", true);
return "redirect:/validation/v3/items/{itemId}";
}
@GetMapping("/{itemId}/edit")
public String editForm(@PathVariable Long itemId, Model model) {
Item item = itemRepository.findById(itemId);
model.addAttribute("item", item);
return "validation/v3/editForm";
}
@PostMapping("/{itemId}/edit")
public String edit(@PathVariable Long itemId, @ModelAttribute Item item) {
itemRepository.update(itemId, item);
return "redirect:/validation/v3/items/{itemId}";
}
}
코드를 변경하고 실행하면 정상적으로 동작하는 것을 확인할 수 있다.
스프링 MVC는 어떻게 Bean Validator를 사용할까
스프링 부트가 spring-boot-starter-validation
라이브러리를 넣으면 자동으로 Bean Validator를 인지하고 스프링에 통합한다.
스프링 부트는 자동으로 글로벌 Validator로 등록한다.
LocalValidatorFactoryBean
을 글로벌 Validator로 등록한다.
이 Validator는 @NotNull
같은 어노테이션을 보고 검증을 수행한다.
글로벌 Validator가 적용되어 있기 때문에, @Valid
, @Validated
만 적용하면 된다.
검증 오류가 발생하면 FieldError
, ObjectError
를 생성해서 BindingResult
에 담아준다.
주의
글로벌 Validator를 직접 등록하면 스프링 부트는 Bean Validator를 글로벌 Validator로 등록하지 않기 때문에 어노테이션 기반의 빈 검증기가 동작하지 않는다.
참고
검증시 @Validated
@Valid
둘다 사용가능하다.javax.validation.@Valid
를 사용하기 위해서 build.gradle
의존관계 추가가 필요하다.
(implementation 'org.springframework.boot:spring-boot-starter-validation')
@Validated
는 스프링 전용 검증 애노테이션이고, @Valid
는 자바 표준 검증 애노테이션이다. 둘중 아무거나 사용해도 동일하게 작동하지만, @Validated
는 내부에 groups라는 기능을 포함하고 있다.
검증 순서
- @ModelAttribute 각각의 필드에 타입 변환 시도
- 성공하면 다음
- 실패하면 typeMismatch로 FieldError추가
- Validator 적용
바인딩에 성공한 필드만 Bean Validation 적용
BeanValidator는 바인딩(타입 변환)에 실패한 필드는 BeanValidator를 적용하지 않는다.
모델 객체에 바인딩 받는 값이 정상으로 들어와야 검증도 의미가 있기 때문이다.
예시
- 성공
- itemName에 문자 "A"입력
- 타입 변환 성공
- BeanValidation 적용
- 실패
- price에 문자 "A"입력
- 문자를 숫자 타입 변환 시도 실패
- typeMismatch FieldError 추가
- price 필드는 BeanValidation 적용 X
출처 : 인프런 김영한 지식공유자님 강의 스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
'BE > Spring' 카테고리의 다른 글
스프링 MVC 2 - BeanValidation 한계, groups (0) | 2022.08.24 |
---|---|
스프링 MVC 2 - Bean Validation 에러 코드, 오브젝트 오류 (0) | 2022.08.24 |
스프링 MVC 2 - Bean Validation 소개, 시작 (0) | 2022.08.24 |
스프링 MVC 2 - Validator 분리 (0) | 2022.08.23 |
스프링 MVC 2 - 오류 코드와 메시지 처리 part.3 (0) | 2022.08.23 |