본문 바로가기
프로그래밍/스프링프레임워크

Hibernate Bean Validator 사용하기(1) - 기본 사용법

by pentode 2018. 4. 21.

폼에서 입력한 값을 클라이언트 측에서는 자바스크립트를 사용해서 유효성을 검증하고 서버측에서도 검증을 하여야 합니다. 서버측에서 폼에 입력된 값을 검정하는데 사용되어질 수 있는 Hibernate Bean Validator 를 사용하는 방법을 알아봅니다.



1. pom.xml 파일에 의존성을 추가합니다.

<dependency>

    <groupId>org.hibernate.validator</groupId>

    <artifactId>hibernate-validator</artifactId>

    <version>6.0.8.Final</version>

</dependency>



2. 메세지 다국어 처리

- 기본적인 다국어 설정은 "Spring Framework 메세지 국제화(다국어 지원) 사용하기"를 참조하세요.

- root-context.xml 파일에 Validator가 messageSource를 사용하도록 설정합니다.


<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">

    <property name="validationMessageSource" ref="messageSource" />

</bean>


- servlet-context.xml 파일에 Controller가 앞에서 설정한 validator를 사용하도록 설정합니다.


<annotation-driven validator="validator"/>



3. Form 작성하기(boardRegisterForm.jsp)

<c:url var="insertUrl" value="/boardInsert.do" />

<form:form commandName="boardVO" action="${insertUrl}" name="boardVO" method="post">

<form:errors path="*" cssClass="error" />

<table border="1">

  <tr>

    <th>이름</th>

      <td>

        <form:input path="name" id="name" size="20" maxlength="20" />

        <form:errors path="name" cssClass="error" />

      </td>

  </tr>

  <tr>

    <th>비밀번호</th>

    <td>

      <form:password path="password" id="password" size="20" maxlength="20" />

      <form:errors path="password" cssClass="error" />

    </td>

  </tr>

  ...

</table>

</form:form>


- <form:errors path="*" cssClass="error" />를 사용해서 전체 에러 메세지를 출력할 수 있습니다.

- <form:errors path="name" cssClass="error" /> 부분에 개별 에러 메세지가 출력됩니다.



4. VO에 제약사항 지정하기(BoardVO.java)

@Size(min=2, message="{board.name}")

private String name;       /* 이름 */

@Size(min=8, message="비밀번호는 8자 이상이어야 합니다.")

private String password;   /* 비밀번호 */

@Size(min=5, message="이메일 형식이 아닙니다.")

@Email(message="이메일 형식이 아닙니다.")

private String email;      /* 이메일 */


- VO객체의 멤버변수에 아노테이션을 사용해서 제약사항을 부여합니다.

- message 부분에 {board.name} 은 다국어 지원으로 messageSource에서 값을 가져옵니다.


5. 내장되어 있는 제약사항


아노테이션 설명 / 지원 데이터 타입
@AssertFalse 값이 false 인지 확인합니다.
Boolean, boolean
@AssertTrue 값이 true 인지 확인합니다.
Boolean, boolean
@DecimalMax(value=, inclusive=) 값이 inclusive=false일때 지정된 최대값 보다 작은지 확인합니다. inclusive=true 이면 값이 지정된 최대값보다 작거나 같은지 확인합니다. 매개변수 값은 BigDecimal 문자열 표현에 따라 최대값의 문자열 표현입니다.
BigDecimal, BigInteger, CharSequence, byte, short, int, long 과 원시타입 래퍼 클래스를 지원합니다; HV에 의해 추가로 지원 : Number 와 javax.money.MonetaryAmount의 서브타입 (만약 JSR 354 API 구현이 클래스 패스에 존재한다면)
@DecimalMin(value=, inclusive=) 값이 inclusive=false일때 지정된 최소값 보다 큰지 확인합니다. inclusive=true 이면 값이 지정된 최소값보다 크나 같은지 확인합니다. 매개변수 값은 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 와 javax.money.MonetaryAmount의 서브타입
@Email 지정된 문자 시퀀스가 유효한 전자 메일 주소인지 여부를 확인합니다. 선택적 매개 변수 regexp 및 flags를 사용하면 전자 메일과 일치해야하는 추가 정규 표현식 (정규식 플래그 포함)을 지정할 수 있습니다.
CharSequence
@Future 날짜가 미래인지 확인합니다.
java.util.Date, java.util.Calendar, java.time.Instant, java.time.LocalDate, java.time.LocalDateTime, java.time.LocalTime, java.time.MonthDay, java.time.OffsetDateTime, java.time.OffsetTime, java.time.Year, java.time.YearMonth, java.time.ZonedDateTime, java.time.chrono.HijrahDate, java.time.chrono.JapaneseDate, java.time.chrono.MinguoDate, java.time.chrono.ThaiBuddhistDate; HV에 의해 추가로 지원, 만약 Joda Time date/time API 가 클래스 패스에 있다면 : 모든 ReadablePartial 과 ReadableInstant의 구현
@FutureOrPresent 날짜가 현재 또는 미래인지 확인합니다.
java.util.Date, java.util.Calendar, java.time.Instant, java.time.LocalDate, java.time.LocalDateTime, java.time.LocalTime, java.time.MonthDay, java.time.OffsetDateTime, java.time.OffsetTime, java.time.Year, java.time.YearMonth, java.time.ZonedDateTime, java.time.chrono.HijrahDate, java.time.chrono.JapaneseDate, java.time.chrono.MinguoDate, java.time.chrono.ThaiBuddhistDate; HV에 의해 추가로 지원, 만약 Joda Time date/time API 가 클래스 패스에 있다면 : 모든 ReadablePartial 과 ReadableInstant의 구현
@Max(value=) 값이 지정된 최대값보다 작거나 같은지 확인합니다.
BigDecimal, BigInteger, byte, short, int, long 과 원시타입의 래퍼 클래스; HV에 의해 추가로 지원: CharSequence의 서브 타입 (문자 시퀀스로 표현된 숫자값이 평가되어집니다.), Number 와 javax.money.MonetaryAmount의 서브 타입
@Min(value=) 값이 지정된 최소값보다 크거나 같은지 확인합니다.
BigDecimal, BigInteger, byte, short, int, long 과 원시타입의 래퍼 클래스; HV에 의해 추가로 지원: CharSequence의 서브 타입 (문자 시퀀스로 표현된 숫자값이 평가되어집니다.), Number 와 javax.money.MonetaryAmount의 서브 타입
@NotBlank 값이 null이 아니고, 트림 된 길이가 0보다 큰지 확인합니다. @NotEmpty와의 차이점은 이 제약은 CharSequence에만 적용되고 트림된다는 것입니다.
CharSequence
@NotEmpty 값이 null도 빈것도 아닌지 확인합니다.
CharSequence, Collection, Map, arrays
@NotNull 값이 null이 아닌지 체크합니다.
모든 타입
@Negative 값이 음수인지 확인합니다.
BigDecimal, BigInteger, byte, short, int, long 과 원시타입의 래퍼 클래스; HV에 의해 추가로 지원: CharSequence의 서브 타입 (문자 시퀀스로 표현된 숫자값이 평가되어집니다.), Number 와 javax.money.MonetaryAmount의 서브 타입
@NegativeOrZero 값이 음수이거나 0인지 확인합니다.
BigDecimal, BigInteger, byte, short, int, long 과 원시타입의 래퍼 클래스; HV에 의해 추가로 지원: CharSequence의 서브 타입 (문자 시퀀스로 표현된 숫자값이 평가되어집니다.), Number 와 javax.money.MonetaryAmount의 서브 타입
@Null 값이 null인지 확인합니다.
모든 타입
@Past 값이 과거일자인지 확인합니다.
java.util.Date, java.util.Calendar, java.time.Instant, java.time.LocalDate, java.time.LocalDateTime, java.time.LocalTime, java.time.MonthDay, java.time.OffsetDateTime, java.time.OffsetTime, java.time.Year, java.time.YearMonth, java.time.ZonedDateTime, java.time.chrono.HijrahDate, java.time.chrono.JapaneseDate, java.time.chrono.MinguoDate, java.time.chrono.ThaiBuddhistDate; HV에 의해 추가로 지원, 만약 Joda Time date/time API 가 클래스 패스에 있다면 : 모든 ReadablePartial 과 ReadableInstant의 구현
@PastOrPresent 값이 과거 또는 현재인지 확인합니다.
java.util.Date, java.util.Calendar, java.time.Instant, java.time.LocalDate, java.time.LocalDateTime, java.time.LocalTime, java.time.MonthDay, java.time.OffsetDateTime, java.time.OffsetTime, java.time.Year, java.time.YearMonth, java.time.ZonedDateTime, java.time.chrono.HijrahDate, java.time.chrono.JapaneseDate, java.time.chrono.MinguoDate, java.time.chrono.ThaiBuddhistDate; HV에 의해 추가로 지원, 만약 Joda Time date/time API 가 클래스 패스에 있다면 : 모든 ReadablePartial 과 ReadableInstant의 구현
@Pattern(regex=, flags=) 주어진 플래그 매치를 고려하여 값이 정규식 regex와 일치하는지 검사합니다.
CharSequence
@Positive 값이 양수 인지 확인합니다.
BigDecimal, BigInteger, byte, short, int, long 과 원시타입의 래퍼 클래스; HV에 의해 추가로 지원: CharSequence의 서브 타입 (문자 시퀀스로 표현된 숫자값이 평가되어집니다.), Number 와 javax.money.MonetaryAmount의 서브 타입
@PositiveOrZero 값이 양수이거나 0인지 확인합니다.
BigDecimal, BigInteger, byte, short, int, long 과 원시타입의 래퍼 클래스; HV에 의해 추가로 지원: CharSequence의 서브 타입 (문자 시퀀스로 표현된 숫자값이 평가되어집니다.), Number 와 javax.money.MonetaryAmount의 서브 타입
@Size(min=, max=) 값이 min=과 max= 사이에 있는지 확인합니다.(경계 포함)
CharSequence, Collection, Map, arrays



6. Validation 하기

@RequestMapping(value = "/boardInsert.do", method = RequestMethod.POST)

public String boardInsert(@Valid BoardVO boardVO, Errors errors, Model model) throws Exception {

    if(errors.hasErrors()) {

        return "boardRegisterForm";

    }

    return "redirect:/boardRegisterForm.do";

}


- 사용자가 입력한 값을 boardVO 에 자동으로 맵핑됩니다. 여기에 @Valid 아노테이션을 지정하면 유효성 검사가 이루어 집니다.

- Errors errors 는 검증한 결과를 가지고 있습니다. BindingResult 객체를 사용해도 됩니다.

- errors.hasErrors() 가 참이면 검증에서 오류가 발생한 것입니다.



7. 실행결과


실행결과



※ 전체소스


반응형