Validation 추상화 - KwangtaekJung/inflearn-spring-framework-essential GitHub Wiki
- Bean Validation 명세
- Bean Validation 1.0 (JSR-303)
- Bean Validation 1.1 (JSR-349)
- Bean Validation 2.0 (JSR-380) -> 구현체(hibernate-validator:6.2.5.Final)
org.springframework.validation.Validator
애플리케이션에서 사용하는 객체 검증용 인터페이스.
- 어떤한 계층과도 관계가 없다. => 모든 계층(웹, 서비스, 데이터)에서 사용해도 좋다.
- 구현체 중 하나로, JSR-303(Bean Validation 1.0)과 JSR-349(Bean Validation 1.1)을 지원한다. ( LocalValidatorFactoryBean )
- DataBinder에 들어가 바인딩 할 때 같이 사용되기도 한다.
- boolean supports(Class clazz): 어떤 타입의 객체를 검증할 때 사용할 것인지 결정함
- void validate(Object obj, Errors e): 실제 검증 로직을 이 안에서 구현
- 구현할 때 ValidationUtils 사용하며 편리 함.
- LocalValidatorFactoryBean 빈으로 자동 등록 <= 이거 자체는 Spring에서 제공
Spring이 제공하는 Validator을 그냥 가져다 쓰면 됨. (@Autowired) 검증 로직을 직접 작성하지 않고 @NotEmpty 등의 constraints annotation을 붙여주면 검증이 이루어진다.
<dependency> <groupId>jakarta.validation</groupId> <artifactId>jakarta.validation-api</artifactId> <version>2.0.2</version> </dependency>
- JSR-380(Bean Validation 2.0.1) 구현체로 hibernate-validator 사용.
-
https://beanvalidation.org/
Jave EE 표준 스펙 중 하나
starter-validation을 의존성에 추가해주어야 한다.
jakarta.validation도 포함되어 있으므로 별도로 의존성 설정해주지 않아도 됨.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
==> 하지만 이렇게 validator를 직접 작성하지 않는다. 특히나 스프링 부트를 사용하고 있다면.... ^^
==> 하지만 복잡한 비지니스 로직이 들어가야 한다면 validator를 직접 만들어서 사용할 수도 있겠지...
-
참고로, validator를 직접 만들지 않고 제공되는 것을 사용하여, JSR 380 제약 사항을 이용해 검증하고자 할 때....
- spring이 제공하는 validator(org.springframework.validation.Validator)를 사용해도 되고
- javax.validation.Validator 에서 제공하는 Validator을 주입받아 사용해도 된다.
- 어차피 구현체는 LocalValidatorFactoryBean로 동일하다. 이 녀석이 2가지 인터페이스를 다 상속받아 처리한다.
- 단, 사용방법은 조금 다르니 주의할것, 그냥 스프링에서 제공하는 validator를 사용하자!!!
-
스프링은 직접 validate()를 명시하지 않아도 검증하는 몇 가지 방법을 제공한다.
- @Controller에서 인자로 넘어오는 모델 속성에 @Valid 를 붙이면 WebDataBinder가 데이터 바인딩과 함께 검증도 수행하고 결과를 BindingResult에 넣어준다.
- @Service 및 @Repository 등 @Component로 등록한 Java Bean에 @Validated를 붙이고 매소드에서 검증할 파라미터에 @Valid를 붙이면 해당 메서드를 호출할 때 검증이 수행된다. 매서드에 @Valid를 붙이면 리턴 타입을 검증을 해준다.
@Service
@Validated
public class CategoryService {
public void createCategory(@Valid Category category) {
System.out.println("Create Category");
}
}
@Component
public class AppRunner implements ApplicationRunner {
@Autowired
Validator validator; //org.springframework.validation.Validator;
@Autowired
CategoryService categoryService;
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println("validator: " + validator.getClass());
Item item = new Item();
item.setName("spring");
Category category = new Category();
category.setId(1234l);
category.setItem(item);
// BeanPropertyBindingResult bindingResult =
// new BeanPropertyBindingResult(category, "Errors");
// validator.validate(category, bindingResult);
//
// System.out.println(bindingResult.hasErrors());
//
// bindingResult.getAllErrors().forEach( e -> {
// System.out.println("=====================");
// Arrays.stream(e.getCodes()).forEach(System.out::println);
// System.out.println("-----");
// System.out.println(e.getDefaultMessage());
// });
categoryService.createCategory(category);
}
- https://beanvalidation.org/2.0/spec/#validationapi-validatorapi-methodlevelvalidationmethods
- https://medium.com/@gaemi/java-%EC%99%80-spring-%EC%9D%98-validation-b5191a113f5c
- https://jongmin92.github.io/2019/11/18/Spring/bean-validation-1/
- https://jongmin92.github.io/2019/11/21/Spring/bean-validation-2/