Goal
- 스프링의 추상화 중 하나인 Validation 추상화에 대해 알아본다
- validator를 구현해보며 이해한다
Validation 추상화란 ?
애플리케이션에서 사용하는 객체 검증용 인터페이스 이며, org.springframework.validation.Validator를 제공한다
특징
- 어떠한 계층과도 관계가 없다
- 모든 계층(웹,서비스,데이터)에서 사용해도 좋다
- 주로 스프링 mvc에서 사용하기는 하지만 웹 계층에서만 사용하는 웹 전용 validator가 아니다
- 구현체 중 하나로 JSR-303(Bean Validation 1.0)과 JSR-349(Bean Validation 1.1)을 지원한다
- LocalValidatorFactoryBean
- bean validation이 제공하는 여러 애노테이션을 사용하여 객체의 데이터를 검증 가능
Bean Validation
java ee 표준 스펙 중 하나로 @NotNull, @NotEmpty, @Email 등 bean 데이터를 검증할 수 있다
인터페이스
- boolean supports(Class clazz)
- 내가 검증해야하는 인스턴스의 클래스가 해당 validator가 검증을 할 수 있는 클래스인지 확인하는 메서드
- 어떤 타입의 객체를 검증할 때 사용할 것인지 결정함
- void validate(Object obj)
- 실질적으로 검증 작업이 일어나는 곳
- 구현시 ValidationUtils 사용하면 편리함
Validator 만들기
원시적인 방법의 validator
Event
public class Event {
Integer id;
String title;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
- title이 notEmpty라고 가정해보자
EventValidator
public class EventValidator implements Validator {
@Override
public boolean supports(Class<?> clazz) {
return Event.class.equals(clazz);
}
@Override
public void validate(Object target, Errors errors) {
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "title", "notempty","empty title is not allowed");
}
}
- Validator를 구현한다
- org.springframework.validation;
- supports(), validate()
- validate()에서는 타겟에 에러(key, value)형태를 넘긴다
AppRunner
@Component
public class AppRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
Event event = new Event();
EventValidator eventValidator = new EventValidator();
Errors errors = new BeanPropertyBindingResult(event, "event");
eventValidator.validate(event,errors);
System.out.println(errors.hasErrors());
errors.getAllErrors().forEach(e ->{
System.out.println("=======error code ======");
Arrays.stream(e.getCodes()).forEach(System.out::println);
System.out.println(e.getDefaultMessage());
});
}
}
- new BeanPropertyBindingResult(event, "event");
- 스프링 mvc에서는 이런 값들이 자동으로 넘어가기 때문에 실제 우리가 사용할 일은 거의 없다
결과
true
=======error code ======
notempty.event.title
notempty.title
notempty.java.lang.String
notempty
empty title is not allowed
=> 위의 3가지를 validator에서 자동으로 추가해 줌.
스프링 2.0.5 이상의 validator
Event
public class Event {
Integer id;
@NotEmpty
String title;
@Min(0)
Integer limit;
@Email
String email;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public Integer getLimit() {
return limit;
}
public void setLimit(Integer limit) {
this.limit = limit;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
- @NotEmtpy, @Min, @Max, @Email 등
AppRunner
@Component
public class AppRunner implements ApplicationRunner {
@Autowired
Validator validator;
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println(validator.getClass());
Event event = new Event();
event.setLimit(-1);
event.setEmail("ggg");
Errors errors = new BeanPropertyBindingResult(event, "event");
validator.validate(event,errors);
System.out.println(errors.hasErrors());
errors.getAllErrors().forEach(e ->{
System.out.println("=======error code ======");
Arrays.stream(e.getCodes()).forEach(System.out::println);
System.out.println(e.getDefaultMessage());
});
}
}
- LocalValidationFactoryBean 빈으로 자동 등록
- Validator를 @Autowired로 의존성 주입을 해주면 됨
- JSR-380(Bean Validation2.0.1) 구현체로 hibernate-validate 사용
결과
class org.springframework.validation.beanvalidation.LocalValidatorFactoryBean
true
=======error code ======
Email.event.email
Email.email
Email.java.lang.String
Email
올바른 형식의 이메일 주소여야 합니다
=======error code ======
NotEmpty.event.title
NotEmpty.title
NotEmpty.java.lang.String
NotEmpty
비어 있을 수 없습니다
=======error code ======
Min.event.limit
Min.limit
Min.java.lang.Integer
Min
0 이상이어야 합니다
참고
@NotEmpty를 인지하지 못해서, 구글링 했더니 spring boot 2.3 version 이상부터는 spring-boot-starter-web 의존성 내부에 있던 validation이 사라졌다고 한다. 그래서 사용하는 spring boot version이 2.3 이상이라면 validation 의존성을 따로 추가해야 한다고 해서 아래와 같이 했다. 그런데 .. 더보기
spring boot 3.1.2 + maven 기준
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
또는
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
</dependency>
의존성을 추가하고 빌드를 해도 찾지 못해서, 어노테이션 클래스 임포트 하니까 되따.. 쩝
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotEmpty;
'Spring > about spring' 카테고리의 다른 글
@Repository vs @Interface 그리고 Mybatis (1) | 2023.09.18 |
---|---|
[데이터 바인딩 추상화] PropertyEditor (0) | 2023.07.28 |
[Resource / Validation] Resource 추상화 (0) | 2023.07.25 |
[IoC 컨테이너와 빈] ResourceLoader (0) | 2023.07.24 |
[IoC 컨테이너와 빈] ApplicationEvent Publisher (0) | 2023.07.24 |