하이버네이트 Validator
공식 메뉴얼 https://docs.jboss.org/hibernate/validator/6.2/reference/en-US/html_single/
검증 애노테이션 모음 https://docs.jboss.org/hibernate/validator/6.2/reference/en-US/html_single/#validator-defineconstraints-spec
implementation 'org.springframework.boot:spring-boot-starter-validation'
@NotBlank : 빈값 + 공백만 있는 경우를 허용하지 않음
@NotNull : null 을 허용하지 않음
@Range(min = 1000, max = 1000000) : 범위 안의 값이어야 함
@Max(9999) : 최대 9999까지만 허용
💡 참고
javax.validation.constraints.NotNull org.hibernate.validator.constraints.Range
javax.validation ~
: 특정 구현에 관계없이 제공되는 표준 인터페이스
org.hibernate.validator ~
: 하이버네이트 validator 구현체를 사용할 때만 제공되는 검증 기능.
실무에서 대부분 하이버네이트 validator를 사용하므로 자유롭게 사용해도 된다.
//생성
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();
//검증 실행
Set<ConstraintViolation<Item>> violations = validator.validate(item);
=> 검증 대상( item )을 직접 검증기에 넣고 그 결과를 받는다
Set 에는 ConstraintViolation 이라는 검증 오류가 담긴다
결과가 비어있으면 검증 오류가 없는 것
@ModelAttribute 각각의 필드에 타입 변환 시도
1-1. 성공하면 다음으로
1-2. 실패하면 typeMismatch 로 FieldError 추가
Validator 적용
👉 바인딩에 성공한 필드만 Bean Validation 적용
@NotBlank
NotBlank.item.itemName
NotBlank.itemName
NotBlank.java.lang.String
NotBlank
@Range
Range.item.price
Range.price
Range.java.lang.Integer
Range
@Data
@ScriptAssert(lang = "javascript", script = "_this.price * this.quantity >= 10000")
public class Item {
//...
}
ScriptAssert.item
ScriptAssert
but
따라서 오브젝트 오류(글로벌 오류)의 경우
오브젝트 관련 부분만 직접 자바 코드로 작성하는 것을 권장
데이터를 등록할 때와 수정할 때의 요구사항이 다를 수 있다
해결 방법
HTML Form -> Item -> Controller -> Item -> Repository
👉 등록시 폼에서 전달하는 데이터가 도메인 객체와 딱 맞지 않아 잘 사용 안 함
HTML Form -> ItemSaveForm -> Controller -> Item 생성 -> Repository
@Valid, @Validated 는 HttpMessageConverter (@RequestBody)에도 적용할 수 있다
💡 참고
@ModelAttribute : HTTP 요청 파라미터(URL 쿼리 스트링, POST Form)를 다룰 때 사용
@RequestBody : HTTP Body의 데이터를 객체로 변환할 때 사용 (주로 API JSON 요청)
@Slf4j
@RestController
@RequestMapping("/validation/api/items")
public class ValidationItemApiController {
@PostMapping("/add")
public Object addItem(@RequestBody @Validated ItemSaveForm form, BindingResult bindingResult) {
log.info("API 컨트롤러 호출");
if (bindingResult.hasErrors()) {
log.info("검증 오류 발생 errors={}", bindingResult);
return bindingResult.getAllErrors();
}
log.info("성공 로직 실행");
return form;
}
}
API의 경우 3가지 경우가 있다
@ModelAttribute
@RequestBody