✔️ 객체를 검증하기 위한 인터페이스. 객체 검증기 구현에 사용
public interface Validator {
// 이 검증기로 검증가능한 객체인지 알려주는 메서드
boolean supports(Class<?> clazz);
// 객체를 검증하는 메서드 - target: 검증할 객체, errors: 검증 시 발생 한 에러저장소
void vaildate(@Nullable Object target, Errors errors);
}
BindingResult
인터페이스는 Errors
의 자손이다.BindingResult
에 저장했듯이, Validator
도 검증한 데이터를 Errors
에 저장한다.supports()
는 User타입과 그의 자손객체만 들어오게 되어있다.
: false로 반환될 시, 검증하지 못한다.
: isAssignable
대신 equals
써도 된다.
validate()
는 실제 검증하는 메서드
: User로 형변환 하기 전에, instanceof로 먼저 확인을 해야 하는데 이미 supports()
에서 걸러주고 있기 때문에 굳이 사용하지 않았다.
id가 null이거나 id에 공백이 있으면 id필드에서 required라는 에러 코드를 저장한다.
: if문 쓰면 너무 길어지니까, ValidationUtils.rejectIfEmptyOfWhitespace()
를 사용한다.
✔️ ValidationUtils.rejectIfEmptyOfWhitespace(errors, iv, 에러코드)
: 해당 iv가 null이거나 공백일 시 errors에 저장
// 1. 유효성 검사
// 수동 검증 - Validator를 직접 생성하고, validator()를 직접 호출
UserValidator userValidator = new UserValidator();
userValidator.validate(user, result);
// User객체를 검증한 결과 에러가 있으면, registerForm을 이용해서 에러를 보여줘야 함.
if(result.hasErrors()) {
return "registerForm";
}
Validator를 배우기 전에는 Controller에다가 직접 검증을 했다.
: 지저분 해 보이니까, Validator를 활용함으로써 관심사를 분리하였다.
➡️ 분리하고 나니까 훨씬 코드가 깔끔해지고 간단해졌다.
Validator를 생성하고 메서드를 호출해서 검증한다.
➡️ 검증하고 나면 result에 에러가 있는지 확인한다.
➡️ 에러가 있으면 registerForm
View를 반환
@InitBinder
를 이용해서 Validator 등록
: binder.setValidator()
로 등록
검증할 대상에 @Valid
를 붙여주면 된다.
✔️ Spring에 없어서 maven.api에 직접 받아와야 함
✏️ pom.xml에다가 validation api 등록
<!-- https://mvnrepository.com/artifact/javax.validation/validation-api -->
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>
⚙️ Maven update 해주기
두개의 BindingResult가 에러난 것을 확인할 수 있다.
: 111(5 이상의 값을 안넣어서 에러)의 값을 넣었는데 검증에 실패해서 거절됨.
required 라고 에러코드를 저장 ➡️ 여러개의 에러코드를 만들어내서 해당하는 메세지를 찾음
arguments: 에러메시지를 사용 할 값
defalut message는 안적어서 null
📌 @InitBinder 가 붙은 메서드안에다가 setValidator를 써서 로컬 validator로 등록
➡️ 검증 할 객체 앞에 @Valid 달아줌
✔️ 모든 Controller에서 검증기가 필요할 때 사용
✔️ 하나의 Validator로 여러 객체를 검증할 때 사용
<annotation-driven validator="globalValidator"/>
<beans:bean id="globalValidator" class="kr.ac.jipark09.GlobalValidator"/>
Servlet-context.xml에 자바 빈 등록
annotation-driven 태그에 글로벌 Validator 등록
모든 Controller에서 @Valid
로 검증 가능
@InitBinder
가 붙은 메서드를 만들고 addvalidators()를 붙여서 로컬 Validator를 만든다.
set이 아닌 add 를 써야 한다.
: 글로벌 Validator에다가 등록하는 방법이기 때문
✔️ 유효성 검증 결과를 저장할 때 사용
public interface Errors {
// 객체 전체에 대한 에러를 저장
void reject(String errorCode);
// 어떤 필드의 에러를 저장 (id / pw -> iv를 의미)
void rejectValue(String field, String errorCode);
...
}
String 디폴트 메시지를 줄 수도 있다. (거의 잘 안씀)
아이디와 패스워드 둘다 틀렸을 경우 reject()
를 써서 "아이디 또는 패스워드가 틀렸습니다." 라는 문구를 많이 씀
rejectValue
가 많이 쓰임
reject()
메소드를 이용해서 추가된 글로벌 에러가 존재할 경우 true 리턴reject()
메소드를 이용해서 추가된 글로벌 에러 갯수를 리턴rejectValue()
메소드를 이용해서 추가된 에러가 존재할 경우 true 리턴rejectValue()
메소드를 이용해서 추가된 에러 갯수를 리턴rejectValue()
메소드를 이용해서 추가한 특정핑드의 에러가 존재할 경우 true 리턴rejectValue()
메소드를 이용해서 추가한 특정필드의 에러 갯수 리턴✔️ 다양한 리소스에서 메시지를 읽기 위한 인터페이스
MessageSource
이용✔️ 프로퍼티 파일을 메세지 소스로 하는 ResourceBundleMessageSource를 등록
Servlet-context.xml
에 자바 빈으로 등록
주석처리 된 것은 메시지 경로(아래 사진)를 의미
: 확장자는 properties여야 함
✔️ 에러코드가 있는 파일을 만들어야 함
📌 required.user.id ➡️ required.id ➡️ required.java.lang.String ➡️ required
Errors 인터페이스의 errorCode는 메시지 코드의 에러코드와 일치하는지 찾는다.
User객체의 아이디 필드를 검증하면 required.user.id를 찾는다. 그게 없으면 required.id 찾고 required.java.lang.String을 찾고 마지막으로 required를 찾는다.
➡️ 필드이름, 객체이름, 타입까지 조합을해서 메시지 코드에 일치하는 지 찾는다.
required는 일반적이여서 메세지 프로퍼티에 첫 번째로 등록해 놓는다.
✔️ 스프링이 제공하는 커스텀 태그 라이브러리를 사용
✔️ <form> 대신 <form:form> 사용
<form:form modelAttribute="user>
✔️ <form:erros>로 에러를 출력. path에 에러 발생 필드를 지정(*은 모든 필드의 에러)
<form:errors path="id" cssClass="msg">
/src/main/resources/
에다가 에러메시지 properties 만들기
incoding: UTF-8 설정
<beans:bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<beans:property name="basenames">
<beans:list>
<beans:value>error_message</beans:value> <!-- /src/main/resources/error_message.properties -->
</beans:list>
</beans:property>
<beans:property name="defaultEncoding" value="UTF-8"/>
</beans:bean>
Servlet-context.xml
에 등록Reference
: https://fastcampus.co.kr/dev_academy_nks