실무에서는 유효성 검사를 실시할때 자바 또는 스프링의 유효성 검사 어노테이션에서 제공하지 않는 기능을 써야 할 때가 있다
-> 이 경우 ConstraintValidator
와 커스텀 어노테이션
을 조합해서 별도의 유효성 검사 어노테이션을 생성
전화번호 형식이 일치하는지 확인하는 유효성 어노테이션을 생성해보자!
우선 ConstraintValidator 인터페이스를 구현하는 클래스 생성
public class TelephoneValidator implements ConstraintValidator<Telephone, String> {
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
if(value == null){
return false;
}
return value.matches("01(?:0|1|[6-9])[.-]?(\\d{3}|\\d{4})[.-]?(\\d{4})$");
}
}
Telephonevalidator 클래스를 ConstraintValidator 인터페이스의 구현체로 정의
인터페이스 선언 시 어떤 어노테이션 인터페이스인지 타입을 지정해야 함
isValid()를 통해 직접 유효성 검사 로직을 작성 해야 함
이 로직에서 false가 리턴되면 MethodArgumentNotValidException 예외 발생
Telephone 어노테이션 인터페이스 생성
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = TelephoneValidator.class)
public @interface Telephone {
String message() default "전화번호 형식이 일치하지 않습니다";
Class[] groups() default {};
Class[] payload() default {};
}
Target
어노테이션은 이 어노테이션을 어디서 선언할 수 있는지 정의 하는 데 사용
Retention
은 이 어노테이션이 실제로 적용되고 유지되는 범위를 의미
Constraint
어노테이션을 통해 앞에서 작성한 TelephoneValidator와 매칭하는 작업 수행
위와 같이 코드 작성 시
@Telephone이 Bean Validation에 추가된것을 볼 수 있음
DTO에 만든 어노테이션 지정
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
@Builder
public class ValidatedRequestDto {
@NotBlank
String name;
@Email
String email;
// @Pattern(regexp = "01(?:0|1|[6-9])[.-]?(\\d{3}|\\d{4})[.-]?(\\d{4})$")
@Telephone
String phoneNumber;
@Min(value = 20)
@Max(value = 40)
int age;
@Size(min = 0, max = 40)
String description;
@Positive
int count;
@AssertTrue
boolean booleanCheck;
}
이후 유효성 검사에서 형식 오류를 감지하는 것을 볼 수 있다