> Hello World !!!

     

@syaku

Spring validator & Hibernate validator - 선언적인 방식 유효성 검증기

Spring validator & Hibernate validator 를 이용한 선언적인 방식 유효성 검증기

스프링 프레임워크를 이용한 유효성 검증기를 구현하는 방법에 대해 설명한다. 다양한 유효성 검증을 위해 hibernate-validator 를 사용하였다.

몇가지 기능을 추가하여 개발한 예제를 https://github.com/syakuis/spring-validation 통해 공개하였다.

<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>4.3.2.Final</version>
</dependency>

hibernate-validator 는 어떤 버전을 사용해도 상관없다.

일반적으로 스프링 validator 를 사용하기 위해 @Controller 스테레오 타입의 구현체 클래스에서 메서드 인수에 @Valid 를 선언하면 자동으로 동작한다.

@Controller
public class FormController {

    @GetMapping
    public String display(@Valid Form form) {
        return "validation/form";
    }
    
}

유효성 검사를 적용하기 위해 2개의 어노테이션을 선언할 수 있다.

@Valid : JSR-303 에 의해 만들어진 어노테이션이다.
@Validated : spring framework 의 만들어진 어노테이션이다.

그리고 그룹을 이용하여 특정 검증을 실행할 수 있다.

@Controller
public class FormController {

    @GetMapping
    public String display(@Valid(Add.class) Form form) {
        return "validation/form";
    }
    
}

public class Foo {

    // Add.class 그룹인 경우에만 유효성 검사를 실행한다.
    @NotEmpty(groups = Add.class)
    private String idx;

}

메서드에 BindingResult 인수가 없는 경우 MethodArgumentNotValidException 예외가 발생하게 된다. @ControllerAdvice 를 이용해서 예외를 가로채서 오류를 처리하면 된다.

@ControllerAdvice
public class ExceptionController {
    private MessageSourceAccessor messageSource;

    @Autowired
    public void setMessageSource(MessageSourceAccessor messageSource) {
        this.messageSource = messageSource;
    }

    private SuccessHandler<List<ErrorResult>> validationSuccessHandler(BindingResult bindingResult) {
        return new SuccessHandler(
                messageSource.getMessage("text.error.validation"),
                true, StatusCode.FormValidation,
                new ValidationResult(
                        bindingResult,
                        new AppValidationMessage(messageSource)
                ).getFieldErrors());
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseBody
    public SuccessHandler<List<ErrorResult>> validationException(MethodArgumentNotValidException e) {
        return validationSuccessHandler(e.getBindingResult());
    }
}

예제 소스를 알맞게 수정해서 사용하면 된다.

검증을 얻어서 직접 처리하려면 다음과 같다.

@Controller
public class FormController {

    @GetMapping
    public String display(@Valid(Add.class) Form form, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            return "validation/form";
        }
        return "validation/done";
    }
    
}

몇가지 오류??에 대한 팁

아무값도 전달하지 않고 도메인 필드가 int 타입에 유효성 검증을 하면 바인딩 과정에서 오류가 발생했다는 오류가 반환된다. 실제는 바인딩이 잘되지만 유효성 검증에서는 오류로 처리된다. 다만 레퍼런스 타입을 사용하면 문제가 해결된다.

직접 메서드를 만들어 검증을 할 경우 접근제어는 public 이여야 한다.

@AssertTrue(message = "비밀번호가 일치하지 않습니다.")
public boolean isPassowrdCompare() {
    // 이전에 빈값을 검증하기 때문에 널 검사는 제외한다. (null pointer 예외를 피하기 위함)
    if (this.password == null || this.password2 == null) {
        return true;
    }

    return this.password.equals(this.password2);
}

스프링에서는 @Valid* 이하 모든 명은 유효성 검증에 사용되는 어노테이션으로 인식한다. @Validation, @Validsdfsf @Validewrewr 등등 모두 유효성 검증이 실행된다. 그리고 다음과 같은 어노테이션 명을 사용하면 오류가 발생한다. ValidResponse 어노테이션명을 사용했을때 발생하는 오류. 아마 유효성검증이 실행되었지만 의도한 봐와 다른 의미로 사용했기때문에 오류가 발생한것 같다.

Caused by: java.lang.IllegalArgumentException:
warning no match for this type name:
org.syaku.tutorials.spring.apps.validation.support.ValidResponse 
[Xlint:invalidAbsoluteTypeName] 

스프링 자바기반 설정을 사용할때 Bean Context 의 클래스명과 Bean Application Context 클래스명이 같으면 Application Context 가 무시된다.

국제화 메세지를 사용할때 ReloadableResourceBundleMessageSource 과 ResourceBundleMessageSource 을 사용할때 설정을 setUseCodeAsDefaultMessage = false 해야한다.

원래 메세지 키가 없는 경우 예외가 발생하는 예외대신 기본 값을 사용할지 여부를 설정하는 데... 기본값을 제대로 찾지 못하는 건지 정상적인 메세지가 출력되지 않는 다.

다른 설정없이 hibernate-validator 국제화 메세지를 직접 수정하려면 최상단 경로에 ValidationMessage.properties 만들어서 사용해야 한다.

Reference 타입은 유효성 검증을 할 수 없다. 자세한 설명 JSR-303 이나 https://stackoverflow.com/questions/17207766/spring-mvc-valid-on-list-of-beans-in-rest-service 참고한다. 일반적으로 아래와 같은 유형이 문제가 된다.

@Valid List<Foo> foos

위와 같은 컬랙션은 유효성 검증에서 제외된다. 이걸 가능하게 하였다.

참고: https://github.com/syakuis/spring-validation

Java Validator 와 Hibernate Validator 어노테이션 종류

가끔 필요할 것 같아... 구글 번역기 돌려서 복사해왔다... 시간이 많지 않아 쏘리~~~ 대충 참고하길;;;

원본: https://docs.jboss.org/hibernate/stable/validator/reference/en-US/html_single/#section-builtin-constraints

@AssertFalse
주석 첨부 요소가 false인가 어떤가를 판정합니다.

지원되는 데이터 유형
Boolean, boolean

최대 절전 모드 메타 데이터 영향
없음
@AssertTrue
주석 첨부 요소가 true인가 어떤가를 판정합니다.

지원되는 데이터 유형
Boolean, boolean

최대 절전 모드 메타 데이터 영향
없음
@DecimalMax(value=, inclusive=)
주석 첨부의 값이 지정된 최대치 ( inclusive= false )보다 작은 지 어떤지를 판정합니다 . 그렇지 않은 경우에는 값이 지정된 최대 값보다 작거나 같은지 여부. 매개 변수 값은 문자열 표현에 따라 최대 값의 BigDecimal문자열 표현입니다.

지원되는 데이터 유형
BigDecimal, BigInteger, CharSequence, byte, short, int, long및 프리미티브 타입의 각 래퍼; 추가적으로 HV 의해 지원되는 임의의 서브 타입 Number및 javax.money.MonetaryAmount(경우 생성 JSR 354 API 및 구현 클래스 경로가)

최대 절전 모드 메타 데이터 영향
없음
@DecimalMin(value=, inclusive=)
주석 첨부의 값이 지정된 최소치보다 큰지 어떤지 ( inclusive= false)를 판정합니다. 그렇지 않은 경우는, 값이 지정된 최소치보다 큰가 어떤가 매개 변수 값은 문자열 표현에 따른 최소값의 BigDecimal문자열 표현입니다.

지원되는 데이터 유형
BigDecimal, BigInteger, CharSequence, byte, short, int, long및 프리미티브 타입의 각 래퍼; 추가적으로 HV 의해 지원되는 임의의 서브 타입 Number및javax.money.MonetaryAmount

최대 절전 모드 메타 데이터 영향
없음
@Digits(integer=, fraction=)
주석 된 값이 최대 integer자릿수와 fraction소수 자릿수 가있는 숫자인지 확인합니다.

지원되는 데이터 유형
BigDecimal를, BigInteger, CharSequence, byte, short, int, long및 프리미티브 타입의 각 래퍼; HV에 의해 추가로 지원됨 :Number

최대 절전 모드 메타 데이터 영향
열의 정밀도와 스케일을 정의합니다.
@Future
주석 달기 날짜가 미래인지 확인합니다.

지원되는 데이터 유형
java.util.Date, java.util.Calendar, java.time.chrono.ChronoZonedDateTime, java.time.Instant, java.time.OffsetDateTime; 경우 추가, HV 지원 Joda 시간 날짜 / 시간 API 클래스 경로에 :의 구현 ReadablePartial및ReadableInstant

최대 절전 모드 메타 데이터 영향
없음
@Max(value=)
주석 된 값이 지정된 최대 값보다 작거나 같은지 확인합니다.

지원되는 데이터 유형
BigDecimal, BigInteger, byte, short, int, long및 프리미티브 타입의 각 래퍼; HV에 의해 추가로 지원됩니다. CharSequence(문자 시퀀스가 ​​나타내는 숫자 값이 평가 됨)의 모든 하위 유형, Number및javax.money.MonetaryAmount

최대 절전 모드 메타 데이터 영향
열에 check 제약 조건을 추가합니다.
@Min(value=)
주석 첨부의 값이 지정된 최소치보다 큰지 어떤지를 판정합니다.

지원되는 데이터 유형
BigDecimal, BigInteger, byte, short, int, long및 프리미티브 타입의 각 래퍼; HV에 의해 추가로 지원됩니다. CharSequence(문자 시퀀스가 ​​나타내는 숫자 값이 평가 됨)의 모든 하위 유형, Number및javax.money.MonetaryAmount

최대 절전 모드 메타 데이터 영향
열에 check 제약 조건을 추가합니다.
@NotNull
주석 된 값이 아닌지 검사합니다. null

지원되는 데이터 유형
모든 유형

최대 절전 모드 메타 데이터 영향
열은 null 허용되지 않습니다.
@Null
주석 된 값이 null

지원되는 데이터 유형
모든 유형

최대 절전 모드 메타 데이터 영향
없음
@Past
주석 달기 날짜가 과거인지 검사합니다.

지원되는 데이터 유형
java.util.Date, java.util.Calendar, java.time.chrono.ChronoZonedDateTime, java.time.Instant, java.time.OffsetDateTime; 경우 또한, HV 지원 Joda 시간 날짜 / 시간 API 클래스 경로에 :의 구현 ReadablePartial및ReadableInstant

최대 절전 모드 메타 데이터 영향
없음
@Pattern(regex=, flags=)
regex주어진 플래그를 고려 하여 주석 문자열이 정규식과 일치하는지 확인합니다.match

지원되는 데이터 유형
CharSequence

최대 절전 모드 메타 데이터 영향
없음
@Size(min=, max=)
확인 주석 요소의 크기 사이 인 경우 min와 max(포함)

지원되는 데이터 유형
CharSequence, Collection, Map및 배열

최대 절전 모드 메타 데이터 영향
열 길이는로 설정됩니다. max
@Valid
연결된 객체에서 유효성 검사를 반복적으로 수행합니다. 객체가 컬렉션 또는 배열 인 경우 요소는 재귀 적으로 유효성이 검사됩니다. 객체가지도 인 경우 value 요소는 재귀 적으로 유효성이 검사됩니다.

지원되는 데이터 유형
비 기본 유형

최대 절전 모드 메타 데이터 영향
없음

@CreditCardNumber(ignoreNonDigitCharacters=)
주석 된 문자 시퀀스가 ​​Luhn 체크섬 테스트를 통과하는지 확인합니다. 참고로,이 유효성 검사는 신용 카드 유효 기간이 아닌 사용자 실수를 확인하는 것을 목표로합니다. 신용 카드 번호 분석을 참조하십시오 . ignoreNonDigitCharacters비 숫자 문자는 무시할 수 있습니다. 기본값은 false입니다.

지원되는 데이터 유형
CharSequence

최대 절전 모드 메타 데이터 영향
없음
@Currency(value=)
javax.money.MonetaryAmount주석 된 통화 단위가 지정된 통화 단위의 일부 인지 점검합니다 .

지원되는 데이터 유형
모든 하위 유형 javax.money.MonetaryAmount( JSR 354 API 및 구현이 클래스 경로에있는 경우)

최대 절전 모드 메타 데이터 영향
없음
@EAN
주석 된 문자 시퀀스가 ​​유효한 EAN 바코드 인지 확인합니다 . type은 바코드의 유형을 결정합니다. 기본값은 EAN-13입니다.

지원되는 데이터 유형
CharSequence

최대 절전 모드 메타 데이터 영향
없음
@Email
지정된 문자 시퀀스가 ​​유효한 전자 메일 주소인지 여부를 확인합니다. 선택적 매개 변수 regexp이며 flags전자 메일과 일치해야하는 정규 표현식 플래그를 포함한 추가 정규 표현식을 지정할 수 있습니다.

지원되는 데이터 유형
CharSequence

최대 절전 모드 메타 데이터 영향
없음
@Length(min=, max=)
주석이 붙은 문자 순서가 그 사이 min에 max포함되어 있는지를 검증합니다.

지원되는 데이터 유형
CharSequence

최대 절전 모드 메타 데이터 영향
열 길이가 최대로 설정됩니다.
@LuhnCheck(startIndex= , endIndex=, checkDigitIndex=, ignoreNonDigitCharacters=)
주석이 붙은 문자 시퀀스 내의 숫자가 Luhn 체크섬 알고리즘을 통과하는지 검사합니다 ( Luhn 알고리즘 참조). startIndex그리고 endIndex반드시 지정된 서브 캐릭터에 대한 알고리즘을 실행할 수 있습니다. checkDigitIndex문자 시퀀스 내의 임의의 숫자를 검사 숫자로 사용할 수 있습니다. 지정하지 않으면 검사 숫자가 지정된 범위의 일부라고 가정합니다. 마지막으로 중요한 것은 ignoreNonDigitCharacters비 숫자 문자를 무시할 수 있습니다.

지원되는 데이터 유형
CharSequence

최대 절전 모드 메타 데이터 영향
없음
@Mod10Check(multiplier=, weight=, startIndex=, endIndex=, checkDigitIndex=, ignoreNonDigitCharacters=)
주석이 붙은 문자 순서 내의 숫자가 제네릭 모드 10 체크섬 알고리즘을 통과하는지 검사합니다. multiplier홀수의 배수 (기본값은 3), 짝수의 배율 weight(기본값은 1)을 결정합니다. startIndex그리고 endIndex는 지정된 하위 문자열에 알고리즘을 실행할 수 있습니다. checkDigitIndex문자 시퀀스 내의 임의의 숫자를 검사 숫자로 사용할 수 있습니다. 지정하지 않으면 검사 숫자가 지정된 범위의 일부라고 가정합니다. 마지막으로 중요한 것은 ignoreNonDigitCharacters비 숫자 문자를 무시할 수 있습니다.

지원되는 데이터 유형
CharSequence

최대 절전 모드 메타 데이터 영향
없음
@Mod11Check(threshold=, startIndex=, endIndex=, checkDigitIndex=, ignoreNonDigitCharacters=, treatCheck10As=, treatCheck11As=)
주석 된 문자 시퀀스 내의 숫자가 mod 11 체크섬 알고리즘을 통과하는지 검사합니다. thresholdmod11 배율 증가에 대한 임계 값을 지정합니다. 값을 지정하지 않으면 배율이 무기한 증가합니다. mod 11 체크섬이 각각 10 또는 11 일 때 사용할 체크 수 treatCheck10As를 treatCheck11As지정하십시오. 기본값은 각각 X와 0입니다. startIndex에서 endIndex checkDigitIndex와 ignoreNonDigitCharacters동일한 의미를 지닙 @Mod10Check니다.

지원되는 데이터 유형
CharSequence

최대 절전 모드 메타 데이터 영향
없음
@NotBlank
주석이 붙은 문자 순서가 null는 아니고, 트림 된 길이가 0보다 큰지를 판정 @NotEmpty합니다.이 제약은 캐릭터 라인에만 적용 할 수있어 그 후행하는 공백은 무시됩니다.

지원되는 데이터 유형
CharSequence

최대 절전 모드 메타 데이터 영향
없음
@NotEmpty
주석 첨부 요소가 null도 하늘도 아닌지를 판정합니다.

지원되는 데이터 유형
CharSequence, Collection, Map및 배열

최대 절전 모드 메타 데이터 영향
없음
@Range(min=, max=)
주석 된 값이 지정된 최소값과 최대 값 사이에 있는지 여부를 확인합니다.

지원되는 데이터 유형
BigDecimal, BigInteger, CharSequence, byte, short, int, long및 프리미티브 타입의 각각 포장기

최대 절전 모드 메타 데이터 영향
없음
@SafeHtml(whitelistType= , additionalTags=, additionalTagsWithAttributes=)
주석 된 값에 다음과 같은 잠재적으로 악의적 인 조각이 들어 있는지 확인합니다 <script/>. 이 제약 조건을 사용하려면 jsoup의 라이브러리는 클래스 경로의 일부 여야합니다. 이 whitelistType속성을 사용하면 additionalTags또는 을 통해 세련되게 할 수 있는 미리 정의 된 허용 목록 유형을 선택할 수 있습니다 additionalTagsWithAttributes. 전자는 속성없이 태그를 추가 할 수 있지만, 후자는 주석을 사용하여 태그 및 선택적으로 허용되는 속성을 지정할 수 있습니다 @SafeHtml.Tag.

지원되는 데이터 유형
CharSequence

최대 절전 모드 메타 데이터 영향
없음
@ScriptAssert(lang=, script=, alias=, reportOn=)
주어진 스크립트가 주석이 달린 요소에 대해 성공적으로 평가 될 수 있는지 여부를 확인합니다. 이 제약을 사용하려면, JSR 223 ( 「Java TM 플랫폼 의 스크립트 」) 으로 정의되고있는 Java Scripting API의 구현을 클래스 패스의 일부로 할 필요가 있습니다. 평가할 표현식은 JSR 223 호환 엔진을 클래스 경로에서 찾을 수있는 스크립팅 또는 표현식 언어로 작성할 수 있습니다. 이것은 클래스 수준의 제약 조건 임에도 불구하고이 reportOn속성을 사용하여 전체 개체가 아닌 특정 속성에 대한 제약 조건 위반을보고 할 수 있습니다 .

지원되는 데이터 유형
모든 유형

최대 절전 모드 메타 데이터 영향
없음
@URL(protocol=, host=, port=, regexp=, flags=)
주석 된 문자 시퀀스가 ​​RFC2396에 따라 유효한 URL인지 확인합니다. 선택적 매개 변수 protocol중 host하나 port가 지정되었거나 지정된 경우 해당 URL 조각이 지정된 값과 일치해야합니다. 선택적 매개 변수 regexp이며 flagsURL이 일치해야하는 정규 표현식 플래그를 포함한 추가 정규 표현식을 지정할 수 있습니다. 기본적으로이 제약 조건은 java.net.URL생성자를 사용하여 지정된 문자열이 유효한 URL을 나타내는 지 여부를 확인합니다. RegexpURLValidatorXML을 통해 ( 제약 조건을 통해 제약 조건 매핑constraint-mappings 참조 ) 또는 프로그래밍 방식 API 를 통해 구성 할 수있는 정규 표현식 기반 버전도 사용할 수 있습니다 ( 프로그래밍 방식으로 제약 조건 정의 추가 참조 ).

지원되는 데이터 유형
CharSequence

최대 절전 모드 메타 데이터 영향
없음
국가 별 제약 조건

Hibernate Validator는 또한 사회 보장 번호의 검증과 같은 몇 가지 국가 별 제약을 제공한다.

국가 고유의 제약을 구현해야한다면, Hibernate Validator에 기여하도록 고려해야한다!
@CNPJ
주석이있는 문자 시퀀스가 ​​브라질 법인 법인 납세자 등록 번호 (Cadastro de Pessoa Juríeddica)를 나타내는 지 확인합니다.

지원되는 데이터 유형
CharSequence

최대 절전 모드 메타 데이터 영향
없음

국가
브라질
@CPF
주석이 달린 문자 시퀀스가 ​​브라질의 개별 납세자 등록 번호 (Cadastro de Pessoa Fídsica)를 나타내는 지 확인합니다.

지원되는 데이터 유형
CharSequence

최대 절전 모드 메타 데이터 영향
없음

국가
브라질
@TituloEleitoral
주석이 달린 문자 시퀀스가 ​​브라질 유권자 ID 카드 번호 ( Título Eleitoral )를 나타내는 지 확인 합니다.

지원되는 데이터 유형
CharSequence

최대 절전 모드 메타 데이터 영향
없음

국가
브라질
@NIP
주석 된 문자 시퀀스가 ​​폴란드 VAT 식별 번호 ( NIP ) 를 나타내는 지 확인합니다.

지원되는 데이터 유형
CharSequence

최대 절전 모드 메타 데이터 영향
없음

국가
폴란드
@PESEL
주석 문자 시퀀스는 폴란드 국가 식별 번호를 표시 확인 ( PESEL )

지원되는 데이터 유형
CharSequence

최대 절전 모드 메타 데이터 영향
없음

국가
폴란드
@REGON
주석 된 문자 시퀀스가 ​​폴란드어 납세자 식별 번호 ( REGON ) 를 나타내는 지 검사합니다 . REGON의 9 자리 및 14 자리 버전 모두에 적용 가능

지원되는 데이터 유형
CharSequence

최대 절전 모드 메타 데이터 영향
없음

국가
폴란드



posted syaku blog

Syaku Blog by Seok Kyun. Choi. 최석균.

http://syaku.tistory.com