티스토리 뷰
Validator란?
애플리케이션에서 사용하는 객체 검증용 인터페이스이다. 주로 스프링 MVC에서 사용하긴 하지만 웹 계층에서만 사용하라고 만든 웹 계층 전용이 아니라 어떤 계층(웹, 서비스, 데이터)이라도 사용할 수 있는 일반적인 인터페이스이다. 그리고 BeanValidation 전용 여러 어노테이션들을 사용해서 객체의 데이터를 검증할 수 있다.
Validator 내부 메소드
public interface Validator {
boolean supports(Class<?> clazz);
void validate(Object target, Errors errors);
}
Validator 인터페이스를 implements 하기 위해서는 두개의 메소드를 오버라이딩 해야한다.
- supports 메소드는 인자로 넘어온 검증해야 할 클래스가 Validator로 검증할 수 있는 클래스인지 확인하는 메소드이다.
- validate 메소드는 실질적으로 검증이 일어나는 메소드이다.
public class Event {
Integer id;
String title;
public void setId(Integer id) {
this.id = id;
}
public void setTitle(String title) {
this.title = title;
}
public Integer getId() {
return id;
}
public String getTitle() {
return title;
}
}
import org.springframework.validation.Errors;
import org.springframework.validation.ValidationUtils;
import org.springframework.validation.Validator;
public class EventValidator implements Validator {
@Override
public boolean supports(Class<?> clazz) {
return Event.class.equals(clazz);
}
@Override
public void validate(Object target, Errors errors) {
// default 에러코드로 메세지를 찾지 못했을 때 사용함
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "title", "notempty", "Empty title is now allow");
}
}
EventValidator 클래스는 Validator 인터페이스를 implements 했기 때문에 supprots, validate 메소드를 오버라이딩 했다. supports 메소드는 매개변수로 넘어온 클래스가 Event 클래스인지를 확인하고, validate 메소드는 ValidationUtils의 rejectIfEmptyOrWhitespace 메소드를 이용하여 title 필드가 공백이거나 존재하지 않을 때 errors에 에러 정보를 담는 역할이다. notempty는 에러코드이며 마지막 인자는 디폴트 메세지이다.
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
import org.springframework.validation.BeanPropertyBindingResult;
import org.springframework.validation.Errors;
import java.util.Arrays;
@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());
});
}
}
Errors 타입의 구현체인 BeanPropertyBindingResult는 현재 테스트 중이기 때문에 직접 사용하지만 실질적으로 사용할 일이 거의 없다. 왜냐하면 스프링 MVC에서는 자동으로 넘어가기 때문이다.
eventValidator.validate(event, errors);
이 부분이 검증하는 부분이고 첫 번째 인자값에다 검증할 event를 넣어주고 두 번째 인자에다가 검증 에러를 담아준다.
true
==== error code ====
notempty.event.title
notempty.title
notempty.java.lang.String
notempty
Empty title is now allow
결과는 title이 값이 없기 때문에 에러가 발생하여 true가 출력되고 위의 validate 메소드 안에 있는 errors에 에러가 담기게 된다. 그리고 에러코드를 notempty만 입력했는데 위의 3개의 에러메세지를 자동으로 생성해준 것도 알 수 있다.
그리고 스프링 부트 2.0.5 이상 버전을 사용한다면 Validator 인터페이스를 LocalValidatorFactoryBean 빈으로 자동 등록해준다. LocalValidatorFactoryBean는 Bean Validation 어노테이션을 지원하는 Validator이다.
public class Event {
Integer id;
@NotEmpty
String title;
@NotNull @Min(0)
Integer limit;
@Email
String email;
}
getter, setter는 모두 있다고 가정하고 Event 클래스에 Bean Validation 어노테이션을 이용해서 검증을 해보려 한다.
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
import org.springframework.validation.BeanPropertyBindingResult;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;
import java.util.Arrays;
@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("aaa");
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());
});
}
}
여기서 limit, Email에 setter를 통해서 값을 넣고 검증을 해보기 위해 실행을 해보면 결과는 아래와 같다.
class org.springframework.validation.beanvalidation.LocalValidatorFactoryBean
true
==== error code ====
Min.event.limit
Min.limit
Min.java.lang.Integer
Min
반드시 0보다 같거나 커야 합니다.
==== error code ====
NotEmpty.event.title
NotEmpty.title
NotEmpty.java.lang.String
NotEmpty
반드시 값이 존재하고 길이 혹은 크기가 0보다 커야 합니다.
==== error code ====
Email.event.email
Email.email
Email.java.lang.String
Email
이메일 주소가 유효하지 않습니다.
Bean도 위에서 말한 클래스가 주입이 된 것을 알 수 있고 email 형식이 다르고 limit이 0보다 작은 값을 넣었을 때 에러메세지를 자동으로 만들어주는 등등을 알 수 있다.
# 인프런 강의 (백기선 / 스프링 프레임워크 핵심 기술)
Resource 추상화 https://joinwithyou.tistory.com/34
Validation 추상화 https://joinwithyou.tistory.com/35
데이터 바인딩 추상화: PropertyEditor https://joinwithyou.tistory.com/36
데이터 바인딩 추상화: Converter와 Formatter https://joinwithyou.tistory.com/37
SpEL (스프링 Expression Language) https://joinwithyou.tistory.com/38
스프링 AOP: 개념 소개 https://joinwithyou.tistory.com/39
스프링 AOP: 프록시 기반 AOP https://joinwithyou.tistory.com/39
스프링 AOP: @AOP https://joinwithyou.tistory.com/39
Null-safety https://joinwithyou.tistory.com/39
# Reference
https://devlog-wjdrbs96.tistory.com/165?category=882236 (블로그)
https://www.inflearn.com/course/spring-framework_core (백기선 강의)
'Spring' 카테고리의 다른 글
데이터 바인딩 추상화: Converter와 Formatter (0) | 2021.06.07 |
---|---|
데이터 바인딩 추상화: PropertyEditor (0) | 2021.06.07 |
[Spring] Resource 추상화 (0) | 2021.06.07 |
IoC 컨테이너 9부: ResourceLoader (0) | 2021.06.06 |
IoC 컨테이너 8부: ApplicationEventPublisher (0) | 2021.06.06 |