1. 직접 Validator 인터페이스를 상속받아서 객체 검증하기
Validator 인터페이스는 두가지 메서드를 정의하는데, supports메서드와 validate메서드이다.
supports메서드는 검증하고자 하는 객체가 validator에서 지원하는지 아닌지 확인하는 메서드이고, validate메서드는 실제 로직을 구현하는 메서드이다.
아무튼 코드로 Validator 인터페이스를 상속받아서 구현하자면,
public class EventValidator implements Validator {
@Override
public boolean supports(Class<?> aClass) {
//해당 객체가 validator가 지원하는 객체인지 판단하기 위해서 override하는 메서드
return Event.class.equals(aClass);
}
@Override
public void validate(Object target, Errors errors) {
//ValidationUtils를 사용하여 validate을 구현하거나
//rejectIfEmptyOrWhitespace 함수의 경우 해당 필드가 비어있거나 공백일 경우 발생시킴
//1번인자 Error객체, 2번인자 필드이름, 3번인자 에러코드, 4번인자 디폴트 메세지
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "title", "NOT_EMPTY", "DEFALT_MESSAGE");
//또는 직접 Error 객체에 접근해서 validate을 구현할 수도 있음
Event event = (Event) target;
if(event.getClass()==null){
//객체 전반의 에러라면 reject 메서드
errors.reject("Error Message");
//특정 필드의 에어라면 rejectValue 메서드
//첫번째 인자가 필드 이름, 두번째 인가자 에러코드드
errors.rejectValue("fieldName", "ErrorMessage");
}
}
}
그리고 검증받을 객체는,,,
public class Event {
private Integer id;
private 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;
}
}
Validator를 상속받은 클래스를 생성하고 validate매서드를 실행시키는 것임.
validate메서드는 검증할 객체와 Errors객체를 받아서 검증처리를 하고 Errors객체의 메서드를 통해서 e.g. errors.hasErrors() 또는 errors.getAllErrors()등의 메서드를 활용해서 검증 내용을 확인함.
직관적을 코드로 보자면,,
@Component
public class AppRunner implements ApplicationRunner {
@Autowired
Validator validator;
@Override
public void run(ApplicationArguments args) throws Exception {
Event event = new Event();
EventValidator eventValidator = new EventValidator();
//Errors는 인터페이스이고 이를 구현한 구현체는 BeanPropertyBindingResult
// 파라미터로 검증할 객체와 객체의 이름을 String으로 넘김
Errors errors = new BeanPropertyBindingResult(event, "event");
eventValidator.validate(event, errors);
System.out.println(errors.hasErrors());
errors.getAllErrors().forEach(error->{
System.out.println("----error code------");
Arrays.stream(error.getCodes()).forEach(System.out::println);
System.out.println(error.getDefaultMessage());
});
}
2. Validator 인터페이스의 구현체 빈 사용하기
Validator인터페이스를 상속받아 직접 validator를 구현해도 되지만, 갓갓 스프링은 이미 validator인터페이스를 구현해 놓은 LocalValidatorFactoryBean 클래스를 빈으로 등록해 놓았기 때문에
@Component
public class AppRunner implements ApplicationRunner {
@Autowired
Validator validator;
@Override
public void run(ApplicationArguments args) throws Exception {
Event event = new Event();
//Errors는 인터페이스이고 이를 구현한 구현체는 BeanPropertyBindingResult
// 파라미터로 검증할 객체와 객체의 이름을 String으로 넘김
Errors errors = new BeanPropertyBindingResult(event, "event");
eventValidator.validate(event, errors);
}
}
이렇게 빈으로 주입받아서 사용할 수 있도록 되어 있다.
Validator 인터페이스를 직접 구현해서 사용할 때처럼 validate.validate()메서드에 검증할 객체와 Errors객체를 넣고 errro.hasErorr()등의 메서드로 확인함.
그런데 말입니다? 그럼 무엇을 어떻게 검증할건지 어떻게 아나요?
정답은 검증받을 객체의 필드에 여러가지 어노테이션을 필드에 붙여서 확인하게 된다.
예를들면...
public class Event {
@Min(1) //최소값이 1이라는거, 즉, 0이나 음수를 가질 수 없음
private Integer id;
@NotEmpty //Null이나 ""빈 물자열을 가질 수 없음
private 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;
}
}
3. 어노테이션 정리
이제 검증할 객체의 필드에 붙이는 어노테이션들을 하나하나 아라보자!
- Anotation 제약조건
- @NotNull - Null 불가
- @Null - Null만 입력 가능
- @NotEmpty - Null, 빈 문자열 불가
- @NotBlank - Null, 빈 문자열, 스페이스만 있는 문자열 불가
- @Size(min=,max=) - 문자열, 배열등의 크기가 만족하는가?
- @Pattern(regex=) - 정규식을 만족하는가?
- @Max(숫자) - 지정 값 이하인가?
- @Min(숫자) - 지정 값 이상인가
- @Future - 현재 보다 미래인가?
- @Past - 현재 보다 과거인가?
- @Positive - 양수만 가능
- @PositiveOrZero - 양수와 0만 가능
- @Negative - 음수만 가능
- @NegativeOrZero - 음수와 0만 가능
- @Email - 이메일 형식만 가능
- @Digits(integer=, fraction = ) - 대상 수가 지정된 정수와 소수 자리 수 보다 작은가?
- @DecimalMax(value=) - 지정된 값(실수) 이하인가?
- @DecimalMin(value=) - 지정된 값(실수) 이상인가?
- @AssertFalse - false 인가?
- @AssertTrue - true 인가?
'Spring' 카테고리의 다른 글
AA (0) | 2024.03.23 |
---|---|
@RequiredAgrsConsturcor (0) | 2024.01.10 |
[Spring] 컴포넌트 스캔(Component Scan)이란 무엇일까. (0) | 2023.08.29 |
의존성 주입(Dependency Injection) 방법 3가지 (0) | 2023.08.29 |
스프링 빈을 등록하는 2가지 방법 (0) | 2023.08.29 |