앞에서의 기본 사용법과 이어지는 내용으로 다음과 같은 내용을 알아보겠습니다. 예제의 전체 소스는 글의 끝에 첨부해 두었습니다.
- 빈 객체가 멤버로 객체를 가지거나 컬렉션을 가질 경우 모두 검증하기
- 객체의 멤버들을 그룹을 지정하여 특정상황에 특정 멤버만 검증하기
- 커스텀 검증 아노테이션 만들기
1. 테스트용 폼 만들기(personForm.jsp)
<c:url var="insertUrl" value="/personInsert.do" />
<form:form commandName="personVO" action="${insertUrl}" name="personVO" method="post">
...
<tr>
<th>주민번호</th>
<td>
<form:input path="jumin" size="20" maxlength="14" />
<form:errors path="jumin" />
</td>
</tr>
<tr>
<th>비밀번호</th>
<td>
<form:password path="password" size="20" maxlength="20" />
<form:errors path="password" />
</td>
</tr>
...
</tr>
<td>
<form:input path="relations[0].relation" size="20" maxlength="20" /><br />
<form:errors path="relations[0].relation" />
</td>
<td>
<form:input path="relations[0].name" size="20" maxlength="20" /><br />
<form:errors path="relations[0].name" />
</td>
<td>
<form:input path="relations[0].email" size="20" maxlength="20" /><br />
<form:errors path="relations[0].email" />
</td>
</tr>
...
<tr>
<td>
<form:input path="recommender.relation" size="20" maxlength="20" /><br />
<form:errors path="recommender.relation" />
</td>
<td>
<form:input path="recommender.name" size="20" maxlength="20" /><br />
<form:errors path="recommender.name" />
</td>
<td>
<form:input path="recommender.email" size="20" maxlength="20" /><br />
<form:errors path="recommender.email" />
</td>
</tr>
...
</form:form>
- 주민번호는 검증을 위한 커스텀 아노테이션을 만들어 봅니다.
- 비밀번호는 그룹을 사용하여 특정 상황에서만 검증하도록 하여 봅니다.
- relations[0] 으로 된 부분은 멤버로 객체 리스트를 가지는 부분으로 리스트 전체를 검증 합니다.
- recommender 부분은 멤버로 가지는 하나의 객체의 멤버를 검증하도록 합니다.
2. VO에 제약사항 지정하기
- 그룹 지정은 이름만 가지는 인터페이스로 처리 합니다.(PersonGroupA.java)
package com.tistory.pentode.vo;
public interface PersonGroupA { }
- 검정할 그룹을 지정합니다.(PersonVO.java)
@JuminNo
private String jumin; // 주민번호
@Size(min=8, max=20, groups=PersonGroupA.class)
private String password; // 비밀번호
@NotEmpty
@Valid
List<RelationVO> relations; // 가족
@NotNull
@Valid
private RelationVO recommender; // 추천인
- @JuminNo 아노테이션은 뒤에 만들게 될 커스텀 아노테이션 입니다.
- password에는 group=PersonGroupA.class 를 지정하여 Validator 에 PersonGroupA.class 를 검증하도록 표시되었을 때만 검증합니다.
- relations와 recommender는 @Valid 를 사용하여 내부의 멤버들도 검증하도록 지정합니다. 순환 참조일 경우 한번만 검증 됩니다.
3. 검증하기 (HomeController.java)
@Autowired
Validator validator;
...
@RequestMapping(value = "/personInsert.do", method = RequestMethod.POST)
public String personInsert(PersonVO personVO, Errors errors, Model model) throws Exception {
SpringValidatorAdapter validatorAdapter = new SpringValidatorAdapter(validator);
validatorAdapter.validate(personVO, errors, Default.class, PersonGroupA.class);
if(errors.hasErrors()) {
return "personForm";
}
return "redirect:/personForm.do";
}
- SpringValidatorAdapter를 생성하여 validate 메소드로 검증합니다.
- validate 메소드의 세번째 인자는 가변 파라미터로 그룹을 지정하는 인터페이스를 여러개 지정할 수 있습니다.
- 그룹이 지정되지 않은 멤버의 검증은 Default.class 를 지정하여 수행합니다.
- 아래와 같이 @Validated 아노테이션을 사용하여 검증할 수도 있습니다.
@RequestMapping(value = "/personInsert.do", method = RequestMethod.POST)
public String personInsert(@Validated({Default.class,PersonGroupA.class}) PersonVO personVO, Errors errors, Model model) throws Exception {
if(errors.hasErrors()) {
return "personForm";
}
return "redirect:/personForm.do";
}
- SpringValidatorAdapter를 사용할 경우 특정 입력값에 따라 검증 그룹을 동적으로 변경할 수 있을 것입니다.
4. 커스텀 검증 아노테이션 만들기
- @JuminNo 아노테이션을 만듭니다.(JuminNo.java)
- 아래 코드는 거의 대부분의 검증용 아노테이션에서 공통의로 사용되어 집니다. 인터페이스 이름만 바꿔 쓰면 되겠습니다.
- JuminNoValidator.class 가 실제 검증 로직을 가집니다.
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Constraint(validatedBy = {JuminNoValidator.class})
@ReportAsSingleViolation
public @interface JuminNo {
String message() default "주민번호 형식이 틀립니다.";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
static @interface List {
JuminNo[] value();
}
}
- @Target : 아노테이션을 붙일수 있는 곳을 지정합니다.
- @Retention(RetentionPolicy.RUNTIME) : 아노테이션이 실행시에도 사용할 수 있도록 합니다.
- @Constraint : 검증용 클래스를 지정합니다.
- @ReportAsSingleViolation : 다른 아노테이션을 상속해서 기능을 만들때 여러개의 아노테이션을 상속 받아서 검증한다면 각 검증 메세지를 모두 가지고 있습니다. 이때 자신의 메세지만을 사용할 경우 필요합니다.(이 예제에서는 없어도 됩니다.)
- JuminNoValidator.java 만들기
public class JuminNoValidator implements ConstraintValidator<JuminNo, CharSequence> {
@Override
public boolean isValid(CharSequence value, ConstraintValidatorContext context) {
if(value instanceof String) {
return isJuminNo((String)value);
}
return isJuminNo(value.toString());
}
private boolean isJuminNo(String value) {
...
}
}
- isValid() 메소드가 true 를 반환하면 성공, false를 반환하면 실패입니다. 자세한 내용을 첨부된 소스를 참고 하세요.
5. 실행결과
※ 전체소스
'프로그래밍 > 스프링프레임워크' 카테고리의 다른 글
spring-test - 테스트 프로젝트 및 테스트 케이스 기본구조 (0) | 2018.05.01 |
---|---|
전자정부표준프레임워크 3.7 설치하기 (0) | 2018.04.27 |
Hibernate Bean Validator 사용하기(1) - 기본 사용법 (0) | 2018.04.21 |
스프링프레임워크 에러페이지 만들기 (4) | 2018.04.21 |
도메인 이전시 기존 도메인의 모든 URL을 새 도메인으로 리다이렉트하기 (0) | 2018.04.21 |