Validation 추상화
객체를 검증할 때 사용하는 인터페이스이다.
주로 Spring mvc에서 많이 활용되나 일반적인 인터페이스이기 때문에 모든 계층에서 사용할 수 있다.
JSR-303 (Bean Validation), JSR-349 (Bean Validation 1.1)을 지원한다.
현재는 2.0 이상의 버전이 출시되어 있다.
직접 구현하기
현재는 더 쉽게 구현할 수 있는 방법이 있어 잘 쓰이지 않는 방법이다.
하지만 비즈니스 로직이 복잡하다면 직접 구현하는 것도 고려해볼 수 있다.
Spring boot 프로젝트를 하나 만들고 검증할 객체와 Validator를 생성한다.
마지막으로 실행 결과를 볼 AppRunner 클래스까지 정의한다.
User
- 검증 대상인 POJO
public class User {
private String id;
private String name;
private int age;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
UserValidator
- User 객체를 검증
Validator
를 상속받고 두 가지 메소드를 구현한다.- 검증 기준으로 사용할 메소드는
ValidationUtils
에 static으로 정의된rejectIfEmptyOrWhitespace
이다. 이 메소드는 empty이거나 white space(“”)인 경우 에러 코드를 던진다.
public class UserValidator implements Validator {
@Override
public boolean supports(Class<?> aClass) {
return User.class.equals(aClass);
}
@Override
public void validate(Object o, Errors errors) {
ValidationUtils.rejectIfEmptyOrWhitespace(errors, “id”, “notEmpty”, “id cannot be empty.”);
}
}
AppRunner
@Component
public class AppRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
User user = new User();
UserValidator userValidator = new UserValidator();
Errors errors = new BeanPropertyBindingResult(user, “user”);
userValidator.validate(user, errors);
System.out.println(errors);
for (ObjectError error : errors.getAllErrors()) {
System.out.println("==== ERROR CODE ====");
if (error.getCodes() == null) {
continue;
}
for (String errorCode : error.getCodes()) {
System.out.println(errorCode);
}
System.out.println(error.getDefaultMessage());
}
}
}
결과
org.springframework.validation.BeanPropertyBindingResult: 1 errors
Field error in object 'user' on field 'id': rejected value [null]; codes [notEmpty.user.id,notEmpty.id,notEmpty.java.lang.String,notEmpty]; arguments []; default message [id cannot be empty.]
==== ERROR CODE ====
notEmpty.user.id
notEmpty.id
notEmpty.java.lang.String
notEmpty
id cannot be empty.
에러 코드를 전부 찍혀나왔다.
여기서 notEmpty, id cannot be empty. 는 UserValidator
에 직접 정의해 준 결과이다.
validate()
메소드에서 에러를 다르게 던질 수도 있다.
아래와 같이 수정하고 결과를 확인하면 에러 코드가 조금 다르게 나타날 것이다.
@Override
public void validate(Object o, Errors errors) {
// ValidationUtils.rejectIfEmptyOrWhitespace(errors, “id”, “notEmpty”, “id cannot be empty.”);
if (((User) o).getId() == null) {
errors.reject(“Oh my god!”);
}
}
간편하게 사용하기
Spring boot 기준으로 2.0.5 이상이라면 hibernate-validator
가 Bean Validation 2.0.1의 기본 구현체로 설정되어 있다.
낮은 버전이어도 maven / gradle에서 hibernate-validator
의 dependency를 불러와서 사용할 수도 있다.
Spring boot 기준이므로 아래의 의존성을 추가한다.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
라이브러리를 불러오는 작업이 완료되었다면, 소스 코드를 수정한다.
- User
- 검증을 원하는 필드에 적절한 annotation을 붙여준다.
- 검증용 annotaion은 인터넷에 정보가 많으니 찾아보자.
public class User {
@NotEmpty
private String id;
private String name;
@Min(1)
private int age;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
- AppRunner
- Validator의 의존성을 추가했기 때문에 Autowired로 bean을 주입할 수 있다.
- UserValidator 관련 코드를 전부 주석처리한다.
@Component
public class AppRunner implements ApplicationRunner {
@Autowired
Validator validator;
@Override
public void run(ApplicationArguments args) throws Exception {
User user = new User();
// UserValidator userValidator = new UserValidator();
Errors errors = new BeanPropertyBindingResult(user, “user”);
// userValidator.validate(user, errors);
validator.validate(user, errors);
System.out.println(errors);
for (ObjectError error : errors.getAllErrors()) {
System.out.println("==== ERROR CODE ====");
if (error.getCodes() == null) {
continue;
}
for (String errorCode : error.getCodes()) {
System.out.println(errorCode);
}
System.out.println(error.getDefaultMessage());
}
}
}
결과
org.springframework.validation.BeanPropertyBindingResult: 2 errors
Field error in object 'user' on field 'age': rejected value [0]; codes [Min.user.age,Min.age,Min.int,Min]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [user.age,age]; arguments []; default message [age],1]; default message [반드시 1보다 같거나 커야 합니다.]
Field error in object 'user' on field 'id': rejected value [null]; codes [NotEmpty.user.id,NotEmpty.id,NotEmpty.java.lang.String,NotEmpty]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [user.id,id]; arguments []; default message [id]]; default message [반드시 값이 존재하고 길이 혹은 크기가 0보다 커야 합니다.]
==== ERROR CODE ====
Min.user.age
Min.age
Min.int
Min
반드시 1보다 같거나 커야 합니다.
==== ERROR CODE ====
NotEmpty.user.id
NotEmpty.id
NotEmpty.java.lang.String
NotEmpty
반드시 값이 존재하고 길이 혹은 크기가 0보다 커야 합니다.
id 필드에 @NotEmpty
, age 필드에 @Min(1)
을 붙여주었기 때문에 이런 결과가 나타났다.
본인의 상황에 적절한 방법을 선택하여 값을 검증하면 된다.
작성한 전체 소스 코드는 아래 링크에서 확인할 수 있다.
https://github.com/dhmin5693/Spring-core-study/tree/master/Validation
'Java > Spring framework' 카테고리의 다른 글
Spring framework core (11) - SpEL (0) | 2020.01.24 |
---|---|
Spring framework core (10) - Data binding (0) | 2020.01.17 |
Spring framework core (8) - Resource (0) | 2020.01.15 |
Spring framework core (7) - ResourceLoader (0) | 2020.01.14 |
Spring framework core (6) - ApplicationEventPublisher (0) | 2020.01.14 |