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에 들어가 바인딩 할 때 같이 사용되기도 한다.

Validator 인터페이스 (spring에 있는 Validation인지 확인, 다른 패키지 것을 사용하지 않도록 주의 필요함.)

  • boolean supports(Class clazz): 어떤 타입의 객체를 검증할 때 사용할 것인지 결정함
  • void validate(Object obj, Errors e): 실제 검증 로직을 이 안에서 구현
    • 구현할 때 ValidationUtils 사용하며 편리 함.

스프링 부트 2.0.5 이상 버전을 사용할 때

  • 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 표준 스펙 중 하나

스프링 부트 2.3 이상 버전을 사용할 때

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);
    }

참고:

⚠️ **GitHub.com Fallback** ⚠️