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
Jakarta Bean Validation - Home
Jakarta Bean Validation is a Java specification which lets you express constraints on object models via annotations lets you write custom constraints in an extensible way provides the APIs to validate objects and object graphs provides the APIs to validate
beanvalidation.org
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 |
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
Jakarta Bean Validation - Home
Jakarta Bean Validation is a Java specification which lets you express constraints on object models via annotations lets you write custom constraints in an extensible way provides the APIs to validate objects and object graphs provides the APIs to validate
beanvalidation.org
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 |