Upload
wontae-jo
View
1.273
Download
0
Embed Size (px)
Citation preview
효율적인 데이터 검증
Bean Validation 1.1
KSUG Spring-camp ( 2016 )
( JSR-349 )
조원태: Yello Travel Labs - 우리펜션 개발팀
“Bean Validation”
목차
Bean Validation 소개
일반적인 데이터 검증
Bean Validation을 사용한 데이터 검증
기본적으로 제공하는 Annotation 종류
구현체에서 제공하는 Annotation 종류
Pattren Annotation 을 사용한 전화번호 검증
사용자 정의 Annotation – Custom Contstraint
Annotation 속성 – groups
Annotation 속성 – messages
Annotation 속성 – payload
Annotation 사용 시 유의사항
Bean Validation 요약
추가적으로 다루고싶은 내용
참고자료
Bean Validation 소개
Bean Validation : 소개
Bean Validation 이란?
데이터를 검증하기 위한 Java 표준 기술
검증규칙은 Annotation 으로 사용
데이터의 검증은 Runtime 시에 이루어짐
ClientPresentation
LayerBusiness
LayerData Access
LayerDatabase
Java
DomainModel
Bean Validation : 소개
Bean Validation Release
Bean Validation 1.0JSR-303
2009. XX. XX.
Bean Validation 1.1JSR-349
2013. XX. XX.
Bean Validation : 소개
Bean Validation 구현체
Bean Validation 1.1Specification
HibernateValidator
ApacheBean Validation
Application
Java EE 6 and 7
Version 5.0 이상 Version 1.1 이상
구현체
API
우리가 흔히 사용하는 일반적인데이터 검증
Bean Validation : 일반적인 데이터 검증
public class User {
private String name;
private Int age;
... (getter / setter)
... (toString)
}
일반적인 User Model
Bean Validation : 일반적인 데이터 검증
public void validate(User user) throws Exception {if(user.getName() == null) {
throw new IllegalArgumentException("이름은 필수 정보입니다.");}
if(user.getAge() <= 19) {throw new IllegalArgumentException("나이는 19살 이상이어야 합니다.");
}}
일반적인 Validate
Bean Validation 을 사용한 데이터 검증
Bean Validation : Bean Validation을 사용한 데이터 검증
public class User {
@NotNullprivate String name;
@Min(value = 19)private Int age;
... (getter / setter)
... (toString) }
Annotation 선언된 User Model
Annotation 으로 해당
필드에 검증규칙을 선언
Bean Validation : Bean Validation을 사용한 데이터 검증
public class Main {public static void main(String[] arg) throws Exception {
ValidatorFactory validatorfactory = Validation.buildDefaultValidatorFactory();Validator validator = validatorfactory.getValidator();
User user = new User();
Set<ConstraintViolation<User>> constraintviolation = validator.validate(user);
if(constraintviolation.size() == 0) {System.out.println(“검증 성공”);
} else {System.out.println(“검증 실패”);for(ConstraintViolation<User> cv : constraintviolation) {
System.out.println(cv.getPropertyPath() + ” : “ + cv.getMessage());}
}}
}
Bean Validaiton Validate
Bean Validation : Bean Validation을 사용한 데이터 검증
public class Main {public static void main(String[] arg) throws Exception {
ValidatorFactory validatorfactory = Validation.buildDefaultValidatorFactory();Validator validator = validatorfactory.getValidator();
User user = new User();
Set<ConstraintViolation<User>> constraintviolation = validator.validate(user);
if(constraintviolation.size() == 0) {System.out.println(“검증 성공”);
} else {System.out.println(“검증 실패”);for(ConstraintViolation<User> cv : constraintviolation) {
System.out.println(cv.getPropertyPath() + ” : “ + cv.getMessage());}
}}
}
Bean Validaiton Validate
Bean Validation : Bean Validation을 사용한 데이터 검증
public class Main {public static void main(String[] arg) throws Exception {
ValidatorFactory validatorfactory = Validation.buildDefaultValidatorFactory();Validator validator = validatorfactory.getValidator();
User user = new User();
Set<ConstraintViolation<User>> constraintviolation = validator.validate(user);
if(constraintviolation.size() == 0) {System.out.println(“검증 성공”);
} else {System.out.println(“검증 실패”);for(ConstraintViolation<User> cv : constraintviolation) {
System.out.println(cv.getPropertyPath() + ” : “ + cv.getMessage());}
}}
}
Bean Validaiton Validate
Bean Validation : Bean Validation을 사용한 데이터 검증
public class Main {public static void main(String[] arg) throws Exception {
ValidatorFactory validatorfactory = Validation.buildDefaultValidatorFactory();Validator validator = validatorfactory.getValidator();
User user = new User();
Set<ConstraintViolation<User>> constraintviolation = validator.validate(user);
if(constraintviolation.size() == 0) {System.out.println(“검증 성공”);
} else {System.out.println(“검증 실패”);for(ConstraintViolation<User> cv : constraintviolation) {
System.out.println(cv.getPropertyPath() + ” : “ + cv.getMessage());}
}}
}
Bean Validaiton Validate
Bean Validation : Bean Validation을 사용한 데이터 검증
public class Main {public static void main(String[] arg) throws Exception {
ValidatorFactory validatorfactory = Validation.buildDefaultValidatorFactory();Validator validator = validatorfactory.getValidator();
User user = new User();
Set<ConstraintViolation<User>> constraintviolation = validator.validate(user);
if(constraintviolation.size() == 0) {System.out.println(“검증 성공”);
} else {System.out.println(“검증 실패”);for(ConstraintViolation<User> cv : constraintviolation) {
System.out.println(cv.getPropertyPath() + ” : “ + cv.getMessage());}
}}
}
Bean Validaiton Validate
Bean Validation : Bean Validation을 사용한 데이터 검증
public class Main {public static void main(String[] arg) throws Exception {
ValidatorFactory validatorfactory = Validation.buildDefaultValidatorFactory();Validator validator = validatorfactory.getValidator();
User user = new User();
Set<ConstraintViolation<User>> constraintviolation = validator.validate(user);
if(constraintviolation.size() == 0) {System.out.println(“검증 성공”);
} else {System.out.println(“검증 실패”);for(ConstraintViolation<User> cv : constraintviolation) {
System.out.println(cv.getPropertyPath() + ” : “ + cv.getMessage());}
}}
}
Bean Validaiton Validate
Bean Validation : Bean Validation을 사용한 데이터 검증
public class Main {public static void main(String[] arg) throws Exception {
ValidatorFactory validatorfactory = Validation.buildDefaultValidatorFactory();Validator validator = validatorfactory.getValidator();
User user = new User();
Set<ConstraintViolation<User>> constraintviolation = validator.validate(user);
if(constraintviolation.size() == 0) {System.out.println(“검증 성공”);
} else {System.out.println(“검증 실패”);for(ConstraintViolation<User> cv : constraintviolation) {
System.out.println(cv.getPropertyPath() + ” : “ + cv.getMessage());}
}}
}
Bean Validaiton Validate
Bean Validation : Bean Validation을 사용한 데이터 검증
public class Main {public static void main(String[] arg) throws Exception {
ValidatorFactory validatorfactory = Validation.buildDefaultValidatorFactory();Validator validator = validatorfactory.getValidator();
User user = new User();
Set<ConstraintViolation<User>> constraintviolation = validator.validate(user);
if(constraintviolation.size() == 0) {System.out.println(“검증 성공”);
} else {System.out.println(“검증 실패”);for(ConstraintViolation<User> cv : constraintviolation) {
System.out.println(cv.getPropertyPath() + ” : “ + cv.getMessage());}
}}
}
Bean Validaiton Validate
Bean Validation : Bean Validation을 사용한 데이터 검증
public class Main {public static void main(String[] arg) throws Exception {
ValidatorFactory validatorfactory = Validation.buildDefaultValidatorFactory();Validator validator = validatorfactory.getValidator();
User user = new User();
Set<ConstraintViolation<User>> constraintviolation = validator.validate(user);
if(constraintviolation.size() == 0) {System.out.println(“검증 성공”);
} else {System.out.println(“검증 실패”);for(ConstraintViolation<User> cv : constraintviolation) {
System.out.println(cv.getPropertyPath() + ” : “ + cv.getMessage());}
}}
}
Bean Validaiton Validate
검증 실패name : 반드시 값이 있어야 합니다.age : 반드시 19보다 같거나 커야 합니다.
Bean Validtaion 에서기본적으로 제공하는 Annotaion
Annotation 통과 조건 Annotation 통과 조건
@AssertFalse 거짓인가? @AssertTrue 참인가?
@Max 지정 값 이하인가? @Min 지정 값 이상인가?
@DecimalMax 지정 값 이하 실수인가? @DecimalMin 지정 값 이상 실수인가?
@NotNull Null이 아닌가? @Null Null인가?
@Digits 정수, 소수자리 수 이내인가? @Pattern 정규식을 만족하는가?
@Future 미래 날짜인가? @Size 지정 크기를 만족하는가?
@Past 과거 날짜인가? @Valid 객체의 확인 조건을 만족하는가?
Bean Validation : 기본적으로 제공하는 Annotaion 종류
Constraint Annotation
Annotation 통과 조건 Annotation 통과 조건
@AssertFalse 거짓인가? @AssertTrue 참인가?
@Max 지정 값 이하인가? @Min 지정 값 이상인가?
@DecimalMax 지정 값 이하 실수인가? @DecimalMin 지정 값 이상 실수인가?
@NotNull Null이 아닌가? @Null Null인가?
@Digits 정수, 소수자리 수 이내인가? @Pattern 정규식을 만족하는가?
@Future 미래 날짜인가? @Size 지정 크기를 만족하는가?
@Past 과거 날짜인가? @Valid 객체의 확인 조건을 만족하는가?
Bean Validation : 기본적으로 제공하는 Anntation 종류
Constraint Annotation
필드의 값이 Null이 아님을 확인하는 검증규칙
필드의 최소값을 지정할 수 있는 검증규칙
Hibernate 에서확장하여 제공하는 Annotaion
Annotation 통과 조건 Annotation 통과 조건
@NotEmpty Empty값이 아닌가? @Email Email 형식인가?
@URL URL 형식인가? @Length 문자열 길이 min 과 max 사이인가?
@Range 숫자 범위 min 과 max 사이인가?
Bean Validation : 구현체에서 제공하는 Annotation 종류
Hibernate Constraint Annotation
Pattern Annotation 사용한전화번호 검증
Bean Validation : Pattren Annotation을 사용한 전화번호 검증
public class User {
@Pattern(regexp="^[0-9]\\d{2}-(\\d{3}|\\d{4})-\\d{4}$")private String phone;
... (getter / setter)
... (toString) }
Pattern Annotation 선언된 User Model
전화번호 형식의정규식을 만족하는가?
Bean Validation : Pattren Annotation을 사용한 전화번호 검증
public class Main {public static void main(String[] arg) throws Exception {
ValidatorFactory validatorfactory = Validation.buildDefaultValidatorFactory();Validator validator = validatorfactory.getValidator();
User user = new User();user.setPhone(“000-0000-0000”);
Set<ConstraintViolation<User>> constraintviolation = validator.validate(user);
if(constraintviolation.size() == 0) {System.out.println(“검증 성공”);
} else {System.out.println(“검증 실패”);for(ConstraintViolation<User> cv : constraintviolation) {
System.out.println(cv.getPropertyPath() + ” : “ + cv.getMessage());}
}}
}
Bean Validaiton Validate : Success
전화번호 형식
Bean Validation : Pattren Annotation을 사용한 전화번호 검증
public class Main {public static void main(String[] arg) throws Exception {
ValidatorFactory validatorfactory = Validation.buildDefaultValidatorFactory();Validator validator = validatorfactory.getValidator();
User user = new User();user.setPhone(“000-0000-0000”);
Set<ConstraintViolation<User>> constraintviolation = validator.validate(user);
if(constraintviolation.size() == 0) {System.out.println(“검증 성공”);
} else {System.out.println(“검증 실패”);for(ConstraintViolation<User> cv : constraintviolation) {
System.out.println(cv.getPropertyPath() + ” : “ + cv.getMessage());}
}}
}
Bean Validaiton Validate : Success
Bean Validation : Pattren Annotation을 사용한 전화번호 검증
public class Main {public static void main(String[] arg) throws Exception {
ValidatorFactory validatorfactory = Validation.buildDefaultValidatorFactory();Validator validator = validatorfactory.getValidator();
User user = new User();user.setPhone(“000-0000-0000”);
Set<ConstraintViolation<User>> constraintviolation = validator.validate(user);
if(constraintviolation.size() == 0) {System.out.println(“검증 성공”);
} else {System.out.println(“검증 실패”);for(ConstraintViolation<User> cv : constraintviolation) {
System.out.println(cv.getPropertyPath() + ” : “ + cv.getMessage());}
}}
}
Bean Validaiton Validate : Success
전화번호 형식
Bean Validation : Pattren Annotation을 사용한 전화번호 검증
public class Main {public static void main(String[] arg) throws Exception {
ValidatorFactory validatorfactory = Validation.buildDefaultValidatorFactory();Validator validator = validatorfactory.getValidator();
User user = new User();user.setPhone(“000-0000-0000”);
Set<ConstraintViolation<User>> constraintviolation = validator.validate(user);
if(constraintviolation.size() == 0) {System.out.println(“검증 성공”);
} else {System.out.println(“검증 실패”);for(ConstraintViolation<User> cv : constraintviolation) {
System.out.println(cv.getPropertyPath() + ” : “ + cv.getMessage());}
}}
}
Bean Validaiton Validate : Success
Bean Validation : Pattren Annotation을 사용한 전화번호 검증
public class Main {public static void main(String[] arg) throws Exception {
ValidatorFactory validatorfactory = Validation.buildDefaultValidatorFactory();Validator validator = validatorfactory.getValidator();
User user = new User();user.setPhone(“000-0000-0000”);
Set<ConstraintViolation<User>> constraintviolation = validator.validate(user);
if(constraintviolation.size() == 0) {System.out.println(“검증 성공”);
} else {System.out.println(“검증 실패”);for(ConstraintViolation<User> cv : constraintviolation) {
System.out.println(cv.getPropertyPath() + ” : “ + cv.getMessage());}
}}
}
Bean Validaiton Validate : Success
Bean Validation : Pattren Annotation을 사용한 전화번호 검증
public class Main {public static void main(String[] arg) throws Exception {
ValidatorFactory validatorfactory = Validation.buildDefaultValidatorFactory();Validator validator = validatorfactory.getValidator();
User user = new User();user.setPhone(“000-0000-0000”);
Set<ConstraintViolation<User>> constraintviolation = validator.validate(user);
if(constraintviolation.size() == 0) {System.out.println(“검증 성공”);
} else {System.out.println(“검증 실패”);for(ConstraintViolation<User> cv : constraintviolation) {
System.out.println(cv.getPropertyPath() + ” : “ + cv.getMessage());}
}}
}
Bean Validaiton Validate : Success
Bean Validation : Pattren Annotation을 사용한 전화번호 검증
public class Main {public static void main(String[] arg) throws Exception {
ValidatorFactory validatorfactory = Validation.buildDefaultValidatorFactory();Validator validator = validatorfactory.getValidator();
User user = new User();user.setPhone(“000-0000-0000”);
Set<ConstraintViolation<User>> constraintviolation = validator.validate(user);
if(constraintviolation.size() == 0) {System.out.println(“검증 성공”);
} else {System.out.println(“검증 실패”);for(ConstraintViolation<User> cv : constraintviolation) {
System.out.println(cv.getPropertyPath() + ” : “ + cv.getMessage());}
}}
}
Bean Validaiton Validate : Success
검증 성공
Bean Validation : Pattren Annotation을 사용한 전화번호 검증
public class Main {public static void main(String[] arg) throws Exception {
ValidatorFactory validatorfactory = Validation.buildDefaultValidatorFactory();Validator validator = validatorfactory.getValidator();
User user = new User();user.setPhone(“00000000000”);
Set<ConstraintViolation<User>> constraintviolation = validator.validate(user);
if(constraintviolation.size() == 0) {System.out.println(“검증 성공”);
} else {System.out.println(“검증 실패”);for(ConstraintViolation<User> cv : constraintviolation) {
System.out.println(cv.getPropertyPath() + ” : “ + cv.getMessage());}
}}
}
Bean Validaiton Validate : Fail
일반숫자 형식
Bean Validation : Pattren Annotation을 사용한 전화번호 검증
public class Main {public static void main(String[] arg) throws Exception {
ValidatorFactory validatorfactory = Validation.buildDefaultValidatorFactory();Validator validator = validatorfactory.getValidator();
User user = new User();user.setPhone(“00000000000”);
Set<ConstraintViolation<User>> constraintviolation = validator.validate(user);
if(constraintviolation.size() == 0) {System.out.println(“검증 성공”);
} else {System.out.println(“검증 실패”);for(ConstraintViolation<User> cv : constraintviolation) {
System.out.println(cv.getPropertyPath() + ” : “ + cv.getMessage());}
}}
}
Bean Validaiton Validate : Fail
Bean Validation : Pattren Annotation을 사용한 전화번호 검증
public class Main {public static void main(String[] arg) throws Exception {
ValidatorFactory validatorfactory = Validation.buildDefaultValidatorFactory();Validator validator = validatorfactory.getValidator();
User user = new User();user.setPhone(“00000000000”);
Set<ConstraintViolation<User>> constraintviolation = validator.validate(user);
if(constraintviolation.size() == 0) {System.out.println(“검증 성공”);
} else {System.out.println(“검증 실패”);for(ConstraintViolation<User> cv : constraintviolation) {
System.out.println(cv.getPropertyPath() + ” : “ + cv.getMessage());}
}}
}
Bean Validaiton Validate : Fail
일반숫자 형식
Bean Validation : Pattren Annotation을 사용한 전화번호 검증
public class Main {public static void main(String[] arg) throws Exception {
ValidatorFactory validatorfactory = Validation.buildDefaultValidatorFactory();Validator validator = validatorfactory.getValidator();
User user = new User();user.setPhone(“00000000000”);
Set<ConstraintViolation<User>> constraintviolation = validator.validate(user);
if(constraintviolation.size() == 0) {System.out.println(“검증 성공”);
} else {System.out.println(“검증 실패”);for(ConstraintViolation<User> cv : constraintviolation) {
System.out.println(cv.getPropertyPath() + ” : “ + cv.getMessage());}
}}
}
Bean Validaiton Validate : Fail
Bean Validation : Pattren Annotation을 사용한 전화번호 검증
public class Main {public static void main(String[] arg) throws Exception {
ValidatorFactory validatorfactory = Validation.buildDefaultValidatorFactory();Validator validator = validatorfactory.getValidator();
User user = new User();user.setPhone(“00000000000”);
Set<ConstraintViolation<User>> constraintviolation = validator.validate(user);
if(constraintviolation.size() == 0) {System.out.println(“검증 성공”);
} else {System.out.println(“검증 실패”);for(ConstraintViolation<User> cv : constraintviolation) {
System.out.println(cv.getPropertyPath() + ” : “ + cv.getMessage());}
}}
}
Bean Validaiton Validate : Fail
Bean Validation : Pattren Annotation을 사용한 전화번호 검증
public class Main {public static void main(String[] arg) throws Exception {
ValidatorFactory validatorfactory = Validation.buildDefaultValidatorFactory();Validator validator = validatorfactory.getValidator();
User user = new User();user.setPhone(“00000000000”);
Set<ConstraintViolation<User>> constraintviolation = validator.validate(user);
if(constraintviolation.size() == 0) {System.out.println(“검증 성공”);
} else {System.out.println(“검증 실패”);for(ConstraintViolation<User> cv : constraintviolation) {
System.out.println(cv.getPropertyPath() + ” : “ + cv.getMessage());}
}}
}
Bean Validaiton Validate : Fail
Bean Validation : Pattren Annotation을 사용한 전화번호 검증
public class Main {public static void main(String[] arg) throws Exception {
ValidatorFactory validatorfactory = Validation.buildDefaultValidatorFactory();Validator validator = validatorfactory.getValidator();
User user = new User();user.setPhone(“00000000000”);
Set<ConstraintViolation<User>> constraintviolation = validator.validate(user);
if(constraintviolation.size() == 0) {System.out.println(“검증 성공”);
} else {System.out.println(“검증 실패”);for(ConstraintViolation<User> cv : constraintviolation) {
System.out.println(cv.getPropertyPath() + ” : “ + cv.getMessage());}
}}
}
Bean Validaiton Validate : Fail
검증 실패phone : 정규 표현식 [0-9]\d{2}-(\d{3}|\d{4})-\d{4}$ 패턴과 일치해야 합니다.
사용자가 직접 정의하여 사용하는Annotation
Bean Validation : 사용자 정의 Annotation – Custom Contstraint
Custom Constraints 란?
사용되는 경우: 기본적으로 제공되는 Anntation 만으로 검증이 어려울 경우
: Annotation 직접 정의하여 사용
Custom Constraints 필수 구성: Custom Annotation
: Custom Validator
Bean Validation : 사용자 정의 Annotation – Custom Contstraint
@Target({ElementType.METHOD, ElementType.FIELD})@Retention(RetentionPolicy.RUNTIME)@Constraint(validatedBy = PhoneValidator.class)@Size(min = 12, max = 13)public @interface PhoneAnnotation {
String message() default “{phone.message}”;
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};}
Custom Annotation 정의
Bean Validation : 사용자 정의 Annotation – Custom Contstraint
@Target({ElementType.METHOD, ElementType.FIELD})@Retention(RetentionPolicy.RUNTIME)@Constraint(validatedBy = PhoneValidator.class)@Size(min = 12, max = 13)public @interface PhoneAnnotation {
String message() default “{Phone.message}”;
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};}
Custom Annotation 정의METHOD, FIELD 에검증규칙을 선언 가능
Bean Validation : 사용자 정의 Annotation – Custom Contstraint
@Target({ElementType.METHOD, ElementType.FIELD})@Retention(RetentionPolicy.RUNTIME)@Constraint(validatedBy = PhoneValidator.class)@Size(min = 12, max = 13)public @interface PhoneAnnotation {
String message() default “{Phone.message}”;
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};}
Custom Annotation 정의
데이터 검증은RUMTIME 시 적용
Bean Validation : 사용자 정의 Annotation – Custom Contstraint
@Target({ElementType.METHOD, ElementType.FIELD})@Retention(RetentionPolicy.RUNTIME)@Constraint(validatedBy = PhoneValidator.class)@Size(min = 12, max = 13)public @interface PhoneAnnotation {
String message() default “{Phone.message}”;
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};}
Custom Annotation 정의
정의된 Validator에 의해데이터 검증
Bean Validation : 사용자 정의 Annotation – Custom Contstraint
@Target({ElementType.METHOD, ElementType.FIELD})@Retention(RetentionPolicy.RUNTIME)@Constraint(validatedBy = PhoneValidator.class)@Size(min = 12, max = 13)public @interface PhoneAnnotation {
String message() default “{Phone.message}”;
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};}
Custom Annotation 정의
Custom Annotation 에서다른 Anootation 을 선언 가능
Bean Validation : 사용자 정의 Annotation – Custom Contstraint
@Target({ElementType.METHOD, ElementType.FIELD})@Retention(RetentionPolicy.RUNTIME)@Constraint(validatedBy = PhoneValidator.class)@Size(min = 12, max = 13)public @interface PhoneAnnotation {
String message() default “{Phone.message}”;
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};}
Custom Annotation 정의
Custom Annotation 이기본적으로 갖고 있는 속성
Bean Validation : 사용자 정의 Annotation – Custom Contstraint
public class PhoneValidator implements ConstraintValidator<PhoneAnnotaion, String> {private java.util.regex.Pattern pattern
= java.util.regex.Pattern.compile(“^[0-9]\\d{2}-(\\d{3}|\\d{4})-\\d{4}$”);
public void initialize(PhoneAnnotation annotaton) {}
public boolean isValid(String value. ConstraintValidatorContext context) {if(value == null || value.length() == 0) {
return true;}Matcher m = pattern.matcher(value);return m.matches();
}}
Custom Validator 정의
Bean Validation : 사용자 정의 Annotation – Custom Contstraint
public class PhoneValidator implements ConstraintValidator<PhoneAnnotaion, String> {private java.util.regex.Pattern pattern
= java.util.regex.Pattern.compile(“^[0-9]\\d{2}
public void initialize(PhoneAnnotation annotaton) {}
public boolean isValid(String value. ConstraintValidatorContext context) {if(value == null || value.length() == 0) {
return true;}Matcher m = pattern.matcher(value);return m.matches();
}}
Custom Validator 정의
Custom Validator 에서필수적으로 Implements 하는Interface
Bean Validation : 사용자 정의 Annotation – Custom Contstraint
public class PhoneValidator implements ConstraintValidator<PhoneAnnotaion, String> {private java.util.regex.Pattern pattern
= java.util.regex.Pattern.compile(“^[0-9]\\d{2}-(\\d{3}|\\d{4})-\\d{4}$”);
public void initialize(PhoneAnnotation annotaton) {}
public boolean isValid(String value. ConstraintValidatorContext context) {if(value == null || value.length() == 0) {
return true;}Matcher m = pattern.matcher(value);return m.matches();
}}
Custom Validator 정의
검증규칙으로 사용될정규식 패턴
Bean Validation : 사용자 정의 Annotation – Custom Contstraint
public class PhoneValidator implements ConstraintValidator<PhoneAnnotaion, String> {private java.util.regex.Pattern pattern
= java.util.regex.Pattern.compile(“^[0-9]\\d{2}-(\\d{3}|\\d{4})-\\d{4}$”);
public void initialize(PhoneAnnotation annotaton) {}
public boolean isValid(String value. ConstraintValidatorContext context) {if(value == null || value.length() == 0) {
return true;}Matcher m = pattern.matcher(value);return m.matches();
}}
Custom Validator 정의
실제로 데이터 검증이이루어지는 로직
Bean Validation : 사용자 정의 Annotation – Custom Contstraint
Custom Constraints 선언된 Model
… …
public class User {
@PhoneAnnotaionprivate String phone;
... (getter / setter)
... (toString) }
public class Address {
@PhoneAnnotaionprivate String phone;
... (getter / setter)
... (toString) }
여러 Model 에서의Custom Constraints 사용
그룹정보 속성을 사용한 동일한 필드에서서로 다른 데이터 검증
Bean Validation : Annotation 속성- groups
groups 무엇인가?
검증규칙에 대한 그룹 정보를 정의
그룹 정보에 따라 동일한 필드 값에 대해서도 서로 다른 데이터 검증
아이디
KSUG 등록
∨가입
비밀번호
이름
전화번호
public class User {
private String id;
private String password;
private String name;
private String phone;
}
아이디
KSUG 수정
∨가입
비밀번호
이름
전화번호
Bean Validation : Annotation 속성- groups
import javax.validation.groups.Default;
public interface Insert extends Default {};
public interface Update extends Default {};
groups 정의
사용자의 등록 단계를 체크할Insert group 정의
사용자의 수정 단계를 체크할Update group 정의
Bean Validation : Annotation 속성- groups
public class User {
@NotNull(groups = Insert.class)private String name;
@Min(value = 19, groups = {Insert.class, Update.class})private Int age;
... (getter / setter)
... (toString) }
groups 정보가 추가로 정의된 User Model
groups 정보Insert.class 정의
groups 정보Insert.class, Update.class 정의
Bean Validation : Annotation 속성- groups
public class Main {public static void main(String[] arg) throws Exception {
ValidatorFactory validatorfactory = Validation.buildDefaultValidatorFactory();Validator validator = validatorfactory.getValidator();
User user = new User();
Set<ConstraintViolation<User>> constraintviolation= validator.validate(user, Insert.class);
if(constraintviolation.size() == 0) {System.out.println(“검증 성공”);
} else {System.out.println(“검증 실패”);for(ConstraintViolation<User> cv : constraintviolation) {
System.out.println(cv.getPropertyPath() + ” : “ + cv.getMessage());}
}}
}
Bean Validaiton Validate : Insert
데이터 검증 수행 시Insert.class 그룹정보 바인드
Bean Validation : Annotation 속성- groups
public class Main {public static void main(String[] arg) throws Exception {
ValidatorFactory validatorfactory = Validation.buildDefaultValidatorFactory();Validator validator = validatorfactory.getValidator();
User user = new User();
Set<ConstraintViolation<User>> constraintviolation= validator.validate(user, Insert.class);
if(constraintviolation.size() == 0) {System.out.println(“검증 성공”);
} else {System.out.println(“검증 실패”);for(ConstraintViolation<User> cv : constraintviolation) {
System.out.println(cv.getPropertyPath() + ” : “ + cv.getMessage());}
}}
}
Bean Validaiton Validate : Insert
Bean Validation : Annotation 속성- groups
public class Main {public static void main(String[] arg) throws Exception {
ValidatorFactory validatorfactory = Validation.buildDefaultValidatorFactory();Validator validator = validatorfactory.getValidator();
User user = new User();
Set<ConstraintViolation<User>> constraintviolation= validator.validate(user, Insert.class);
if(constraintviolation.size() == 0) {System.out.println(“검증 성공”);
} else {System.out.println(“검증 실패”);for(ConstraintViolation<User> cv : constraintviolation) {
System.out.println(cv.getPropertyPath() + ” : “ + cv.getMessage());}
}}
}
Bean Validaiton Validate : Insert
Bean Validation : Annotation 속성- groups
public class Main {public static void main(String[] arg) throws Exception {
ValidatorFactory validatorfactory = Validation.buildDefaultValidatorFactory();Validator validator = validatorfactory.getValidator();
User user = new User();
Set<ConstraintViolation<User>> constraintviolation= validator.validate(user, Insert.class);
if(constraintviolation.size() == 0) {System.out.println(“검증 성공”);
} else {System.out.println(“검증 실패”);for(ConstraintViolation<User> cv : constraintviolation) {
System.out.println(cv.getPropertyPath() + ” : “ + cv.getMessage());}
}}
}
Bean Validaiton Validate : Insert
데이터 검증 수행 시Insert.class 그룹정보 바인드
Bean Validation : Annotation 속성- groups
public class Main {public static void main(String[] arg) throws Exception {
ValidatorFactory validatorfactory = Validation.buildDefaultValidatorFactory();Validator validator = validatorfactory.getValidator();
User user = new User();
Set<ConstraintViolation<User>> constraintviolation= validator.validate(user, Insert.class);
if(constraintviolation.size() == 0) {System.out.println(“검증 성공”);
} else {System.out.println(“검증 실패”);for(ConstraintViolation<User> cv : constraintviolation) {
System.out.println(cv.getPropertyPath() + ” : “ + cv.getMessage());}
}}
}
Bean Validaiton Validate : Insert
Bean Validation : Annotation 속성- groups
public class Main {public static void main(String[] arg) throws Exception {
ValidatorFactory validatorfactory = Validation.buildDefaultValidatorFactory();Validator validator = validatorfactory.getValidator();
User user = new User();
Set<ConstraintViolation<User>> constraintviolation= validator.validate(user, Insert.class);
if(constraintviolation.size() == 0) {System.out.println(“검증 성공”);
} else {System.out.println(“검증 실패”);for(ConstraintViolation<User> cv : constraintviolation) {
System.out.println(cv.getPropertyPath() + ” : “ + cv.getMessage());}
}}
}
Bean Validaiton Validate : Insert
Bean Validation : Annotation 속성- groups
public class Main {public static void main(String[] arg) throws Exception {
ValidatorFactory validatorfactory = Validation.buildDefaultValidatorFactory();Validator validator = validatorfactory.getValidator();
User user = new User();
Set<ConstraintViolation<User>> constraintviolation= validator.validate(user, Insert.class);
if(constraintviolation.size() == 0) {System.out.println(“검증 성공”);
} else {System.out.println(“검증 실패”);for(ConstraintViolation<User> cv : constraintviolation) {
System.out.println(cv.getPropertyPath() + ” : “ + cv.getMessage());}
}}
}
Bean Validaiton Validate : Insert
검증 실패name : 반드시 값이 있어야 합니다.age : 반드시 19보다 같거나 커야 합니다.
Bean Validation : Annotation 속성- groups
public class Main {public static void main(String[] arg) throws Exception {
ValidatorFactory validatorfactory = Validation.buildDefaultValidatorFactory();Validator validator = validatorfactory.getValidator();
User user = new User();
Set<ConstraintViolation<User>> constraintviolation= validator.validate(user, Update.class);
if(constraintviolation.size() == 0) {System.out.println(“검증 성공”);
} else {System.out.println(“검증 실패”);for(ConstraintViolation<User> cv : constraintviolation) {
System.out.println(cv.getPropertyPath() + ” : “ + cv.getMessage());}
}}
}
Bean Validaiton Validate : Update
데이터 검증 수행 시Update.class 그룹정보 바인드
Bean Validation : Annotation 속성- groups
public class Main {public static void main(String[] arg) throws Exception {
ValidatorFactory validatorfactory = Validation.buildDefaultValidatorFactory();Validator validator = validatorfactory.getValidator();
User user = new User();
Set<ConstraintViolation<User>> constraintviolation= validator.validate(user, Update.class);
if(constraintviolation.size() == 0) {System.out.println(“검증 성공”);
} else {System.out.println(“검증 실패”);for(ConstraintViolation<User> cv : constraintviolation) {
System.out.println(cv.getPropertyPath() + ” : “ + cv.getMessage());}
}}
}
Bean Validaiton Validate : Update
Bean Validation : Annotation 속성- groups
public class Main {public static void main(String[] arg) throws Exception {
ValidatorFactory validatorfactory = Validation.buildDefaultValidatorFactory();Validator validator = validatorfactory.getValidator();
User user = new User();
Set<ConstraintViolation<User>> constraintviolation= validator.validate(user, Update.class);
if(constraintviolation.size() == 0) {System.out.println(“검증 성공”);
} else {System.out.println(“검증 실패”);for(ConstraintViolation<User> cv : constraintviolation) {
System.out.println(cv.getPropertyPath() + ” : “ + cv.getMessage());}
}}
}
Bean Validaiton Validate : Update
Bean Validation : Annotation 속성- groups
public class Main {public static void main(String[] arg) throws Exception {
ValidatorFactory validatorfactory = Validation.buildDefaultValidatorFactory();Validator validator = validatorfactory.getValidator();
User user = new User();
Set<ConstraintViolation<User>> constraintviolation= validator.validate(user, Update.class);
if(constraintviolation.size() == 0) {System.out.println(“검증 성공”);
} else {System.out.println(“검증 실패”);for(ConstraintViolation<User> cv : constraintviolation) {
System.out.println(cv.getPropertyPath() + ” : “ + cv.getMessage());}
}}
}
Bean Validaiton Validate : Update
데이터 검증 수행 시Update.class 그룹정보 바인드
Bean Validation : Annotation 속성- groups
public class Main {public static void main(String[] arg) throws Exception {
ValidatorFactory validatorfactory = Validation.buildDefaultValidatorFactory();Validator validator = validatorfactory.getValidator();
User user = new User();
Set<ConstraintViolation<User>> constraintviolation= validator.validate(user, Update.class);
if(constraintviolation.size() == 0) {System.out.println(“검증 성공”);
} else {System.out.println(“검증 실패”);for(ConstraintViolation<User> cv : constraintviolation) {
System.out.println(cv.getPropertyPath() + ” : “ + cv.getMessage());}
}}
}
Bean Validaiton Validate : Update
Bean Validation : Annotation 속성- groups
public class Main {public static void main(String[] arg) throws Exception {
ValidatorFactory validatorfactory = Validation.buildDefaultValidatorFactory();Validator validator = validatorfactory.getValidator();
User user = new User();
Set<ConstraintViolation<User>> constraintviolation= validator.validate(user, Update.class);
if(constraintviolation.size() == 0) {System.out.println(“검증 성공”);
} else {System.out.println(“검증 실패”);for(ConstraintViolation<User> cv : constraintviolation) {
System.out.println(cv.getPropertyPath() + ” : “ + cv.getMessage());}
}}
}
Bean Validaiton Validate : Update
Bean Validation : Annotation 속성- groups
public class Main {public static void main(String[] arg) throws Exception {
ValidatorFactory validatorfactory = Validation.buildDefaultValidatorFactory();Validator validator = validatorfactory.getValidator();
User user = new User();
Set<ConstraintViolation<User>> constraintviolation= validator.validate(user, Update.class);
if(constraintviolation.size() == 0) {System.out.println(“검증 성공”);
} else {System.out.println(“검증 실패”);for(ConstraintViolation<User> cv : constraintviolation) {
System.out.println(cv.getPropertyPath() + ” : “ + cv.getMessage());}
}}
}
Bean Validaiton Validate : Update
검증 실패age : 반드시 19보다 같거나 커야 합니다.
메시지 속성을 사용한 메시지 표현
Bean Validation : Annotation 속성- message
public class Main {public static void main(String[] arg) throws Exception {
ValidatorFactory validatorfactory = Validation.buildDefaultValidatorFactory();Validator validator = validatorfactory.getValidator();
User user = new User();user.setPhone(“00000000000”);
Set<ConstraintViolation<User>> constraintviolation = validator.validate(user);
if(constraintviolation.size() == 0) {System.out.println(“검증 성공”);
} else {System.out.println(“검증 실패”);for(ConstraintViolation<User> cv : constraintviolation) {
System.out.println(cv.getPropertyPath() + ” : “ + cv.getMessage());}
}}
}
Pattren Annotaion을 사용한 검증에서의 message
검증 실패phone : 정규 표현식 [0-9]\d{2}-(\d{3}|\d{4})-\d{4}$" 패턴과 일치해야 합니다.
불친절한 메시지 표현
Bean Validation : Annotation 속성- message
message 무엇인가?
Annotation 에러 메시지를 정의하여 표현 가능
Annotation 기본적인 메시지로 표현이 힘들 경우 사용
Bean Validation : Annotation 속성- message
public class User {
@Pattern(regexp = "^[0-9]\\d{2}-(\\d{3}|\\d{4})-\\d{4}$“, message = “전화번호 형식이 아닙니다.”)
private String phone;
... (getter / setter)
... (toString) }
message 정보가 추가로 정의된 User Model
검증규칙에
message 속성을 정의
Bean Validation : Annotation 속성- message
public class Main {public static void main(String[] arg) throws Exception {
ValidatorFactory validatorfactory = Validation.buildDefaultValidatorFactory();Validator validator = validatorfactory.getValidator();
User user = new User();user.setPhone(“00000000000”);
Set<ConstraintViolation<User>> constraintviolation = validator.validate(user);
if(constraintviolation.size() == 0) {System.out.println(“검증 성공”);
} else {System.out.println(“검증 실패”);for(ConstraintViolation<User> cv : constraintviolation) {
System.out.println(cv.getPropertyPath() + ” : “ + cv.getMessage());}
}}
}
message 속성을 사용한 검증에서의 message
검증 실패phone : 전화번호 형식이 아닙니다.
친절한 메시지 표현
properties을 이용한 메시지 관리
Bean Validation : messageInterpolator
Properties 사용한 message 관리
user.id.null = id를 입력하세요.user.name.null = 이름을 입력하세요.user.password.null = 비밀번호를 입력하세요.user.phone.null = 전화번호를 입력하세요....
아이디
KSUG 등록
∨가입
비밀번호
이름
전화번호
message.properties 파일
동일한 Annotation에서서로 다른 심각도 정보를 표시
Bean Validation : Annotation 속성- payload
payload 무엇인가?
검증규칙에 대한 더 자세한 정보 정의
데이터 검증 에러가 발생하였을 경우 정의된 정보로 심각도 확인
Payload 정의된 정보에 따라 처리가 가능
Bean Validation : Annotation 속성- payload
import javax.validation.Payload;
public class Severity {public static interface Warning extends Payload {};
public static interface Error extends Payload {};
}
payload 정보 정의
경고를 표현할Warning payload 정의
에러를 표현할Error payload 정의
Bean Validation : Annotation 속성- payload
public class User {
@NotNull(payload = Serverity.Error.class)private String name;
@NotNull (payload = Serverity.Warning.class)private Int age;
... (getter / setter)
... (toString) }
payload 정보가 추가로 정의된 User Model
payload 정보Error.class 정의
payload 정보Warning.class 정의
Bean Validation : Annotation 속성- payload
public class Main {public static void main(String[] arg) throws Exception {
ValidatorFactory validatorfactory = Validation.buildDefaultValidatorFactory();Validator validator = validatorfactory.getValidator();
User user = new User();
Set<ConstraintViolation<User>> constraintviolation = validator.validate(user);
if(constraintviolation.size() == 0) {System.out.println(“검증 성공”);
} else {System.out.println(“검증 실패”);for(ConstraintViolation<User> cv : constraintviolation) {
System.out.println(cv.getPropertyPath() + ” : “ + cv.getConstraintDescriptor().getPayload());
}}
}}
Bean Validaiton Validate
Bean Validation : Annotation 속성- payload
public class Main {public static void main(String[] arg) throws Exception {
ValidatorFactory validatorfactory = Validation.buildDefaultValidatorFactory();Validator validator = validatorfactory.getValidator();
User user = new User();
Set<ConstraintViolation<User>> constraintviolation = validator.validate(user);
if(constraintviolation.size() == 0) {System.out.println(“검증 성공”);
} else {System.out.println(“검증 실패”);for(ConstraintViolation<User> cv : constraintviolation) {
System.out.println(cv.getPropertyPath() + ” : “ + cv.getConstraintDescriptor().getPayload());
}}
}}
Bean Validaiton Validate
Bean Validation : Annotation 속성- payload
public class Main {public static void main(String[] arg) throws Exception {
ValidatorFactory validatorfactory = Validation.buildDefaultValidatorFactory();Validator validator = validatorfactory.getValidator();
User user = new User();
Set<ConstraintViolation<User>> constraintviolation = validator.validate(user);
if(constraintviolation.size() == 0) {System.out.println(“검증 성공”);
} else {System.out.println(“검증 실패”);for(ConstraintViolation<User> cv : constraintviolation) {
System.out.println(cv.getPropertyPath() + ” : “ + cv.getConstraintDescriptor().getPayload());
}}
}}
Bean Validaiton Validate
Bean Validation : Annotation 속성- payload
public class Main {public static void main(String[] arg) throws Exception {
ValidatorFactory validatorfactory = Validation.buildDefaultValidatorFactory();Validator validator = validatorfactory.getValidator();
User user = new User();
Set<ConstraintViolation<User>> constraintviolation = validator.validate(user);
if(constraintviolation.size() == 0) {System.out.println(“검증 성공”);
} else {System.out.println(“검증 실패”);for(ConstraintViolation<User> cv : constraintviolation) {
System.out.println(cv.getPropertyPath() + ” : “ + cv.getConstraintDescriptor().getPayload());
}}
}}
Bean Validaiton Validate
Bean Validation : Annotation 속성- payload
public class Main {public static void main(String[] arg) throws Exception {
ValidatorFactory validatorfactory = Validation.buildDefaultValidatorFactory();Validator validator = validatorfactory.getValidator();
User user = new User();
Set<ConstraintViolation<User>> constraintviolation = validator.validate(user);
if(constraintviolation.size() == 0) {System.out.println(“검증 성공”);
} else {System.out.println(“검증 실패”);for(ConstraintViolation<User> cv : constraintviolation) {
System.out.println(cv.getPropertyPath() + ” : “ + cv.getConstraintDescriptor().getPayload());
}}
}}
Bean Validaiton Validate
Bean Validation : Annotation 속성- payload
public class Main {public static void main(String[] arg) throws Exception {
ValidatorFactory validatorfactory = Validation.buildDefaultValidatorFactory();Validator validator = validatorfactory.getValidator();
User user = new User();
Set<ConstraintViolation<User>> constraintviolation = validator.validate(user);
if(constraintviolation.size() == 0) {System.out.println(“검증 성공”);
} else {System.out.println(“검증 실패”);for(ConstraintViolation<User> cv : constraintviolation) {
System.out.println(cv.getPropertyPath() + ” : “ + cv.getConstraintDescriptor().getPayload());
}}
}}
Bean Validaiton Validate
Bean Validation : Annotation 속성- payload
public class Main {public static void main(String[] arg) throws Exception {
ValidatorFactory validatorfactory = Validation.buildDefaultValidatorFactory();Validator validator = validatorfactory.getValidator();
User user = new User();
Set<ConstraintViolation<User>> constraintviolation = validator.validate(user);
if(constraintviolation.size() == 0) {System.out.println(“검증 성공”);
} else {System.out.println(“검증 실패”);for(ConstraintViolation<User> cv : constraintviolation) {
System.out.println(cv.getPropertyPath() + ” : “ + cv.getConstraintDescriptor().getPayload());
}}
}}
Bean Validaiton Validate
Bean Validation : Annotation 속성- payload
public class Main {public static void main(String[] arg) throws Exception {
ValidatorFactory validatorfactory = Validation.buildDefaultValidatorFactory();Validator validator = validatorfactory.getValidator();
User user = new User();
Set<ConstraintViolation<User>> constraintviolation = validator.validate(user);
if(constraintviolation.size() == 0) {System.out.println(“검증 성공”);
} else {System.out.println(“검증 실패”);for(ConstraintViolation<User> cv : constraintviolation) {
System.out.println(cv.getPropertyPath() + ” : “ + cv.getConstraintDescriptor().getPayload());
}}
}}
Bean Validaiton Validate
검증 실패name : [interface com.example.beanvalidation.payload.PayloadInterface$Error]age : [interface com.example.beanvalidation.payload.PayloadInterface$Warning]
같은 Null 값에 대해서도 payload 속성에따라 서로 다른 심각도 정보 표현 가능
Annotation 사용시 유의사항
Bean Validation : 유의사항
Constraint Annotation 의 사용시 유의사항
검증규칙의 모순을 구분하지 않고 검증을 진행@Min(1) @DecimalMin(“0.2”)int value;
@Min(3) @Max(2)int value;
검증규칙의 데이터 유형이 다를 경우 Exception 발생@Pastint value;
@Pattern(regexp=“ .+@.+\\.[a-z]+”)int value;
value 는 1이상이면서 0.2이상의 실수인가?
Bean Validation : 유의사항
Constraint Annotation 의 사용시 유의사항
검증규칙의 모순을 구분하지 않고 검증을 진행@Min(1) @DecimalMin(“0.2”)int value;
@Min(3) @Max(2)int value;
검증규칙의 데이터 유형이 다를 경우 Exception 발생@Pastint value;
@Pattern(regexp=“ .+@.+\\.[a-z]+”)int value;
value 는 3이상이면서 2이하인가?
Bean Validation : 유의사항
Constraint Annotation 의 사용시 유의사항
검증규칙의 모순을 구분하지 않고 검증을 진행@Min(1) @DecimalMin(“0.2”)int value;
@Min(3) @Max(2)int value;
검증규칙의 데이터 유형이 다를 경우 Exception 발생@Pastint value;
@Pattern(regexp=“ .+@.+\\.[a-z]+”)int value;
value 는 과거 날짜인가?
Bean Validation : 유의사항
Constraint Annotation 의 사용시 유의사항
검증규칙의 모순을 구분하지 않고 검증을 진행@Min(1) @DecimalMin(“0.2”)int value;
@Min(3) @Max(2)int value;
검증규칙의 데이터 유형이 다를 경우 Exception 발생@Pastint value;
@Pattern(regexp=“ .+@.+\\.[a-z]+”)int value;
value 정규식을 만족하는가?
Bean Validation : 요약
Bean Validation 요약
필드에 사용된 Annotation으로 런타임 시에 데이터 검증
필요에 따라 사용자가 직접 Annotation을 정의 가능
Annotation 속성: groups - 동일한 Model에서의 서로 다른 검증
: message - 사용자 정의 메시지 표현
: payload - 데이터 검증 에러 시 상세 정보 표현
사용시 유의사항: 검증규칙의 모순을 구분하지 않고 검증을 진행
: 검증규칙의 데이터 유형이 다를 경우 Exception 발생
Bean Validation : 추가적으로 다루고싶은 내용
추가적으로 다루고싶은 내용
Class에서의 데이터 검증
EL표현식을 사용한 message 표현
Spring MVC에서의 Bean Validation 사용
Bean Validation : 참고자료
참고자료
JSR-349 Specification : https://jcp.org/en/jsr/detail?id=349
Java Bean Validation API - 발표자료: http://www.slideshare.net/lguerin/cours-javabean-validationv11
SpringMVC Bean Validation 1.1 (JSR-349) – 블로그: http://jinnianshilongnian.iteye.com/blog/1495594
Spring3.1 Bean Validation – 블로그: http://jinnianshilongnian.iteye.com/blog/1990081
Spring 3의 JSR 303(Bean Validation) 지원 – 발표자료: http://www.slideshare.net/kingori/spring-3-jsr-303
고맙습니다
KSUG Spring-camp ( 2016 )