검증 애노테이션과 인터페이스의 모음으로 구현체가 아닌 Bean Validation2.0(JSR-380)이라는 기술 표준이다. 구현체로는 하이버네이트 Validator가 있고, ORM 하이버네이트와는 관련이 없다.
implementation 'org.springframework.boot:spring-boot-starter-validation'
import lombok.Data;
import org.hibernate.validator.constraints.Range;
import javax.validation.constraints.Max;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
@Data
public class Item {
private Long id;
@NotBlank //(message = "공백X")
private String itemName;
@NotNull
@Range(min = 1000, max = 1000000)
private Integer price;
@NotNull
@Max(9999)
private Integer quantity;
public Item() {
}
public Item(String itemName, Integer price, Integer quantity) {
this.itemName = itemName;
this.price = price;
this.quantity = quantity;
}
}
@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}";
}
#Bean Validation 추가
NotBlank.item.itemName=상품명을 입력해주세요
NotBlank={0} 공백X
Range={0}, {2} ~ {1} 허용
Max={0}, 최대 {1}
@Data
@ScriptAssert(lang = "javascript", script = "_this.price * _this.quantity >= 10000", message = "총합이 10000이상이 되도록 입력해주세요")
public class Item {
@PostMapping("/add")
public String addItem(@Validated @ModelAttribute Item item, BindingResult bindingResult, RedirectAttributes redirectAttributes, Model model) {
// 오브젝트 에러
if (item.getPrice() != null && item.getQuantity() != null) {
int resultPrice = item.getPrice() * item.getQuantity();
if (resultPrice < 10000) {
bindingResult.reject("totalPriceMin", new Object[]{10000, resultPrice}, null);
}
}
// 검증에 실패하면 다시 입력 폼으로
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}";
}
같은 도메인에 대해 기능에 따라 요구사항이 차이가 있을 때
예를 들어, 상품(Item)을 등록할 때는 수량(quantity)이 1~9999개 사이로만 설정이 가능한 반면에, 상품을 수정할 때는 수량에 대한 제한이 없을 때를 생각해보자.
현재 상품에는 아래 코드와 같이 설정이 되어 있기 때문에 수정을 할 때 요구사항을 충족할 수 없다.
@NotNull
@Max(9999)
private Integer quantity;
출처: 김영한의 스프링MVC2편