Develop/Springboot

@Valid 를 이용해 @RequestBody 객체 검증하기 | Validating @RequestBody Objects Using @Valid

Springboot를 이용해서 어노테이션을 이용한 validation을 하는 방법을 적으려 한다. RestController를 이용하여 @RequestBody 객체를 사용자로부터 가져올 때, 들어오는 값들을 검증할 수 있는 방법을 소개한다.Jakarata Bean Validation API Packages에 있는 javax.validation.constraints package에 있는 기본적인 검증 어노테이션을 이용한다.@Valid를 이용하면, service 단이 아닌 객체 안에서, 들어오는 값에 대해 검증을 할 수 있다.javax.validation.constraints 패키지를 보면 많은 어노테이션들이 존재한다. @Valid를 이용한 객체 검증 시 기본적으로 이 어노테이션을 이용한다. 사실 이름만 봐..

@Valid 를 이용해 @RequestBody 객체 검증하기 | Validating @RequestBody Objects Using @Valid

728x90

Springboot를 이용해서 어노테이션을 이용한 validation을 하는 방법을 적으려 한다. 
RestController를 이용하여 @RequestBody 객체를 사용자로부터 가져올 때, 들어오는 값들을 검증할 수 있는 방법을 소개한다.

Jakarata Bean Validation API Packages에 있는 javax.validation.constraints package에 있는 기본적인 검증 어노테이션을 이용한다.
@Valid를 이용하면, service 단이 아닌 객체 안에서, 들어오는 값에 대해 검증을 할 수 있다.

javax.validation.constraints 패키지를 보면 많은 어노테이션들이 존재한다. @Valid를 이용한 객체 검증 시 기본적으로 이 어노테이션을 이용한다. 사실 이름만 봐도 각각의 용도를 이해할 수 있다. 

추가 : springboot가 버전업을 하면서 web 의존성안에 있던 constraints packeage가 아예 모듈로 빠졌다.

implementation 'org.springframework.boot:spring-boot-starter-validation'

포스팅 관련 소스코드 : https://github.com/mjung1798/Jyami-Java-Lab/tree/master/annotation-validation

 

mjung1798/Jyami-Java-Lab

Jyami의 Spring boot 및 Java 실험소. Contribute to mjung1798/Jyami-Java-Lab development by creating an account on GitHub.

github.com

 

1. @Valid를 사용하는 방법

간단한 API를 작성해보자.

@RestController
@Slf4j
public class TestController {

    @PostMapping("/user")
    public ResponseEntity<String> savePost(final @Valid @RequestBody UserDto userDto) {
        log.info(userDto.toString());
        return ResponseEntity.ok().body("postDto 객체 검증 성공");
    }
}

파라미터로 @RequestBody 어노테이션 옆에 @Valid를 작성하면, RequestBody로 들어오는 객체에 대한 검증을 수행한다. 이 검증의 세부적인 사항은 객체 안에 정의를 해두어야 한다.

@ToString
@Getter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class UserDto {

    @NotNull
    private String name;
    
    @Email
    private String email;
}

위와 같이 UserDto 객체를 정의한 후 각 필드에 맞는 어노테이션을 사용하면 된다.

@NotNull : 인자로 들어온 필드 값에 null 값을 허용하지 않는다
@Email : 인자로 들어온 값을 Email 형식을 갖추어야 한다.
필드에 맞는 어노테이션에 대한 설명은 아래로 스크롤을 내려보자 : 3. javax.constraint 어노테이션 이해하기

실제로 PostMan을 이용해서 valid가 적용되는지 확인하기 위해, email 값을 이상하게 줘보면,

자동으로 일정 규격에 맞춰서 springboot가 생성한 error 틀에 따라 response가 나간다.
즉, @Valid와 검증 어노테이션만 같이 잘 써줘도, 객체 단에서 에러를 잡을 수 있다는 뜻이다.

@Valid 어노테이션의 동작 여부를 확인하기 위한 테스트 코드는 간단한 Controller 테스트를 이용하여 확인할 수 있다.
아래 테스트 코드는 @NotNull 어노테이션에 따라, name을 null로 넣었을 경우를 가정한 테스트이다.

@SpringBootTest
@AutoConfigureMockMvc
class TestControllerTest {

    @Autowired private MockMvc mockMvc;
    @Autowired private ObjectMapper objectMapper;

    @Test
    @DisplayName("@NotNull 에러 테스트")
    void isValidObject() throws Exception {

        UserDto userDto = UserDto.builder()
                .email("mjung1798@gmail.com")
                .build();

        String userDtoJsonString = objectMapper.writeValueAsString(userDto);

        mockMvc.perform(post("/user")
                .contentType(MediaType.APPLICATION_JSON)
                .content(userDtoJsonString))
                .andExpect(status().isBadRequest());
    }
}

 

2. @Valid시 발생하는 Exception Handling 

@Valid로 requestBody로 들어온 객체의 검증이 이루어지면서 위와 같이 BadRequest가 나가는 경우에 custom 한 errorhandling도 할 수 있다. 

위에서 잘못된 객체 값이 나갔을 때 Springboot에 올라온 Log를 살펴보면 MethodArgumentNotValidException이 발생했음을 알 수 있어, 이 Exception을 사용하여 custom한 ErrorMessage를 response로 내보낼 수도 있다.

@ControllerAdvice를 이용한 전역 에러 핸들링, 혹은 @Controller단에서의 지역 에러 핸들링을 사용하면 된다.
MethodArgumentNotValidException에 대한 @ExceptionHandler 어노테이션을 지정하여 커스텀 에러 핸들링을 해보자

@RestControllerAdvice
public class ApiControllerAdvice {

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<Map<String, String>> handleValidationExceptions(MethodArgumentNotValidException ex){
        Map<String, String> errors = new HashMap<>();
        ex.getBindingResult().getAllErrors()
                .forEach(c -> errors.put(((FieldError) c).getField(), c.getDefaultMessage()));
        return ResponseEntity.badRequest().body(errors);
    }

}

ResponseEntity 값으로, error가 난 field 값과, 에러 메시지를 Map 형태로 만들어서, Response로 넣어주었다. 이때 Map으로 선언하여 forEach를 한 이유는 @Valid를 사용할 때, 해당 객체에서 valid에 실패한 내용을 모두 리턴해주기 때문에, 모든 error 값을 수용하기 위해서이다.

이 상태로 다시 서버를 Run 시켜서 Postman으로 확인을 해본다.
이때는 @NotNull, @Email 모두 validation이 안되도록 requestBody를 작성하였다.

Response값을 살펴보면, BadRequest인 status값, @Valid를 통과하지 못한 모든 필드 값에 대한 어려와, 에러 내용을 커스텀하게 내려준 것이 잘 반영되었음을 알 수 있다.

 

3. javax.constraint 어노테이션 이해하기

가장 아래에 관련 표를 넣어두었다 필요할 때 참고하자.

공식 문서 : https://docs.jboss.org/hibernate/beanvalidation/spec/2.0/api/

 

Jakarta Bean Validation API 2.0.2

 

docs.jboss.org

 

1. 문자열 유무 검증 (@NotBlank, @NotEmpty, @NotNull의 차이점)

@NotBlank 
- null 이 아닌 값이다.
- 공백이 아닌 문자를 하나 이상 포함한다

@NotEmpty
- Type :
 CharSequence (length of character) Collection (collection size) Map (map size Array (array length)
- null 이거나 empty(빈 문자열)가 아니어야 한다.

@NotNull
- Type :
 어떤 타입이든 수용한다.
- null 이 아닌 값이다.

@Null
- Type :
어떤 타입이든 수용한다.
- null 값이다.

이 부분은 헷갈리는 부분이라 DTO와 Contoller를 만들어서 확인해보자.

@NoArgsConstructor
@Getter
@ToString
public class NotDto {
    @NotNull
    private String notNull;
    @NotEmpty
    private String notEmpty;
    @NotBlank
    private String notBlank;
}

결과는 아래와 같다. 각각의 error message를 통해 각 validation 방법을 확인 할 수 있다.

  • @NotNull : 반드시 값이 있어야 한다.
  • @NotEmpty : 반드시 값이 존재하고 길이 혹은 크기가 0보다 커야한다.
  • @NotBrank : 반드시 값이 존재하고 공백 문자를 제외한 길이가 0보다 커야 한다.

 

  null "" " "
@NotNull Invalid Valid Valid
@NotEmpty Invalid Invalid Valid
@NotBlank Invalid Invalid Invalid

용도에 맞게 validation을 할 수 있도록 확인하자.

 

2. 최대 최소에 대한 검증

suppportType 
- BigDecimal BigInteger CharSequence byte, short, int, long, 이에 대응하는 Wrapper 클래스
- double, float는 rounding error 때문에 지원하지 않는다.
- null도 valid로 간주된다.

Validation
- @DecimalMax : 지정된 최대 값보다 작거나 같아야 한다.
      Require : String value  => max 값을 지정한다.
- @DecimalMin : 지정된 최소 값보다 크거나 같아야 한다.
      Require : String value  => min 값을 지정한다.
- @Max : 지정된 최대 값보다 작거나 같아야 한다.
      Require : int value  => max 값을 지정한다.
- @Min : 지정된 최소 값보다 크거나 같아야 한다.
      Require : int value  => min 값을 지정한다.

Usage

@NoArgsConstructor
@Getter
@ToString
public class MinMaxDto {
    @DecimalMax(value = "1000000000")
    private BigInteger decimalMax;
    @DecimalMax(value = "1")
    private BigInteger decimalMin;
    @Max(value = 1000)
    private Integer max;
    @Max(value = 1)
    private Integer min;
}

DecimalMax/Min과, Max/Min의 차이는 범위 값의 차이이다. String을 사용하느냐 Integer를 사용하느냐에 따라 범위 값이 현저히 달라지기 때문이다

 

3. 범위 값에 대한 검증

suppportType 
- BigDecimal BigInteger CharSequence byte, short, int, long, double, float 이에 대응하는 Wrapper 클래스
- null도 valid로 간주된다.

Validation
- @Positive : 양수인 값이다.
- @PositiveOrZero : 0이거나 양수인 값이다.
- @Negative : 음수인 값이다.
- @NegativeOrZero : 0이거나 음수인 값이다.

Usage

@NoArgsConstructor
@Getter
@ToString
public class RangeDto {
    @Positive
    private Integer positive;
    @PositiveOrZero
    private Integer positiveOrZero;
    @Negative
    private Integer negative;
    @NegativeOrZero
    private Integer negativeOrZero;
}

 

4. 시간 값에 대한 검증

suppportType 
- 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
- null도 valid로 간주된다.

Validation
- @Future : Now 보다 미래의 날짜, 시간이어야 한다.
- @FutureOrPresent : Now 거나 미래의 날짜, 시간이어야 한다.
- @Past : Now 보다 과거 의의 날짜, 시간이어야 한다.
- @PastOrPresent : Now 거나 과거의 날짜, 시간이어야 한다.

Now의 기준 : ClockProvider의 가상 머신에 따라 현재 시간을 정의하며 필요한 경우 default time zone을 적용한다.

Usage

@NoArgsConstructor
@Getter
@ToString
public class TimeDto {
    @Future
    private Date future;
    @FutureOrPresent
    private Date futureOrPresent;
    @Past
    private Date past;
    @PastOrPresent
    private Date pastOrPresent;
}

 

4. 이메일 검증

suppportType 
- null도 valid로 간주된다.

Validation
- @Email : 올바른 형식의 이메일 주소여야 한다. (@가 들어가야한다.)

Usage

@NoArgsConstructor
@Getter
@ToString
public class EmailDto {
    @Email
    private String email;
}

 

5. 자릿수 범위 검증

suppportType 
- BigDecimal BigInteger CharSequence byte, short, int, long, 이에 대응하는 Wrapper 클래스
- null도 valid로 간주된다.

Validation
- @Digits : 허용된 범위 내의 숫자이다.
      Require : int integer  => 이 숫자에 허용되는 최대 정수 자릿수
      Require : int fraction  => 이 숫자에 허용되는 최대 소수 자릿수

Usage

@NoArgsConstructor
@Getter
@ToString
@Builder
@AllArgsConstructor
public class DigitsDto {
    @Digits(integer = 5, fraction = 5)
    private Integer digits;
}

 

6. Boolean 값에 대한 검증

suppportType 
- Boolean, boolean

Validation
- @AssertTrue : 값이 항상 True 여야 한다.
- @AssertFalse : 값이 항상 False 여야 한다.

Usage

@NoArgsConstructor
@Getter
@ToString
public class BooleanDto {
    @AssertTrue
    private boolean assertTrue;
    @AssertFalse
    private boolean assertFalse;
}

 

7. 크기 검증

suppportType 
- CharSequence (length of character sequence) Collection (collection size) Map (map size) Array (array length)
- null도 valid로 간주된다.

Validation
- @Size : 이 크기가 지정된 경계(포함) 사이에 있어야 한다.
      Require : int max  => element의 크기가 작거나 같다.
      Require : int min  => element의 크기가 크거나 같다.

Usage

@NoArgsConstructor
@Getter
@ToString
public class SizeDto {
    @Size(max = 5, min = 3)
    private String size;
}

 

8. 정규식 검증

suppportType 
- CharSequence
- null도 valid로 간주된다.

Validation
- @Pattern : 지정한 정규식과 대응되는 문자열 이어야 한다. Java의 Pattern 패키지의 컨벤션을 따른다
      Require : String regexp  => 정규식 문자열을 지정한다

Usage

@NoArgsConstructor
@Getter
@ToString
public class PatternDto {
    //yyyy-mm-dd 형태를 가지는 패턴 조사
    @Pattern(regexp = "^(19|20)\\d{2}-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[0-1])$")
    private String pattern;
}

 

4. @Valid 정리 표

@AssertTrue Boolean, boolean 값이 항상 True 여야 한다.  
@DecimalMax 실수 제외 숫자 클래스. 지정된 최대 값보다 작거나 같아야 하는 숫자이다. String : value (max 값을 지정한다.)
@DecimalMin 실수 제외 숫자 클래스. 지정된 최소 값보다 크거나 같아야하는 숫자이다. String : value (min 값을 지정한다.)
@Digits BigDecimalBigIntegerCharSequencebyte, short, int, long, 이에 대응하는 Wrapper 클래스 허용된 범위 내의 숫자이다. int : integer (이 숫자에 허용되는 최대 정수 자릿수)
int : fraction (이 숫자에 허용되는 최대 소수 자릿수)
@Email null도 valid로 간주된다. 올바른 형식의 이메일 주소여야한다.  
@Future 시간 클래스 Now 보다 미래의 날짜, 시간  
@FutureOrPresent 시간 클래스 Now의 시간이거나 미래의 날짜, 시간  
@Max 실수 제외 숫자 클래스. 지정된 최대 값보다 작거나 같은 숫자이다. long : value (max 값을 지정한다)
@Min 실수 제외 숫자 클래스. 지정된 최소 값보다 크거나 같은 숫자이다. long : value (min 값을 지정한다)
@Negative 숫자 클래스 음수인 값이다.  
@NegativeOrZero 숫자 클래스 0이거나 음수인 값이다  
@NotBlank   null 이 아닌 값이다.공백이 아닌 문자를 하나 이상 포함한다  
@NotEmpty CharSequence,Collection, Map, Array null이거나 empty(빈 문자열)가 아니어야 한다.  
@NotNull 어떤 타입이든 수용한다. null 이 아닌 값이다.  
@Null 어떤 타입이든 수용한다. null 값이다.  
@Past 시간 클래스 Now보다 과거의 날짜, 시간  
@PastOrPresent 시간클래스 Now의 시간이거나 과거의 날짜, 시간  
@Pattern 문자열 지정한 정규식과 대응되는 문자열이어야한다. Java의 Pattern 패키지의 컨벤션을 따른다 String : regexp (정규식 문자열을 지정한다)
@Positive 숫자 클래스 양수인 값이다  
@PositiveOrZero 숫자 클래스 0이거나 양수인 값이다.  
@Size CharSequence,Collection, Map, Array 이 크기가 지정된 경계(포함) 사이에 있어야한다. int : max (element의 크기가 작거나 같다)
int : min (element의 크기가 크거나 같다)

[@ValidAnnotation].List : 동일한 요소에 여러개의 @ValidAnnotation[] 제약조건을 정의한다.

실제로 잘 사용하지는 않는 것으로 보인다.

 

[관련 블로그]

같은 내용의 글을 팀 블로그에도 업로드 한 상태이다.

https://javabom.tistory.com/

 

자바봄

자바 스프링 블로그 입니다.

javabom.tistory.com

 

참고 자료

https://www.baeldung.com/spring-boot-bean-validation

https://www.baeldung.com/java-bean-validation-not-null-empty-blank

 

I'm going to write about how to perform annotation-based validation using Spring Boot. 
This post introduces how to validate incoming values when receiving a @RequestBody object from the user via a RestController.

We'll use the basic validation annotations from the javax.validation.constraints package in the Jakarta Bean Validation API Packages.
By using @Valid, you can validate incoming values within the object itself, rather than at the service layer.

If you look at the javax.validation.constraints package, there are many annotations available. These annotations are used by default when performing object validation with @Valid. Honestly, you can understand what each one does just by looking at the name. 

Update: As Spring Boot has been upgraded, the constraints package that used to be inside the web dependency has been separated into its own module.

implementation 'org.springframework.boot:spring-boot-starter-validation'

Source code for this post: https://github.com/mjung1798/Jyami-Java-Lab/tree/master/annotation-validation

 

mjung1798/Jyami-Java-Lab

Jyami's Spring Boot and Java experiment lab. Contribute to mjung1798/Jyami-Java-Lab development by creating an account on GitHub.

github.com

 

1. How to Use @Valid

Let's write a simple API.

@RestController
@Slf4j
public class TestController {

    @PostMapping("/user")
    public ResponseEntity<String> savePost(final @Valid @RequestBody UserDto userDto) {
        log.info(userDto.toString());
        return ResponseEntity.ok().body("postDto 객체 검증 성공");
    }
}

By writing @Valid next to the @RequestBody annotation in the parameter, validation is performed on the incoming object from the RequestBody. The specific details of this validation must be defined inside the object.

@ToString
@Getter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class UserDto {

    @NotNull
    private String name;
    
    @Email
    private String email;
}

After defining the UserDto object as above, you simply use the appropriate annotation for each field.

@NotNull: Does not allow null values for the incoming field.
@Email: The incoming value must be in a valid email format.
For a detailed explanation of field annotations, scroll down to: 3. Understanding javax.constraint Annotations

To actually verify that validation is working using PostMan, let's try sending an invalid email value:

The response automatically goes out following the error template generated by Spring Boot in a certain format.
In other words, just by using @Valid along with the validation annotations properly, you can catch errors at the object level.

You can verify whether the @Valid annotation works using a simple Controller test.
The test code below assumes the case where name is set to null, according to the @NotNull annotation.

@SpringBootTest
@AutoConfigureMockMvc
class TestControllerTest {

    @Autowired private MockMvc mockMvc;
    @Autowired private ObjectMapper objectMapper;

    @Test
    @DisplayName("@NotNull 에러 테스트")
    void isValidObject() throws Exception {

        UserDto userDto = UserDto.builder()
                .email("mjung1798@gmail.com")
                .build();

        String userDtoJsonString = objectMapper.writeValueAsString(userDto);

        mockMvc.perform(post("/user")
                .contentType(MediaType.APPLICATION_JSON)
                .content(userDtoJsonString))
                .andExpect(status().isBadRequest());
    }
}

 

2. Exception Handling for @Valid 

When validation is performed on the incoming requestBody object with @Valid and a BadRequest is returned as shown above, you can also do custom error handling. 

If you look at the log in Spring Boot when an invalid object value was sent, you can see that a MethodArgumentNotValidException was thrown. You can use this Exception to send a custom ErrorMessage as the response.

You can use global error handling with @ControllerAdvice, or local error handling at the @Controller level.
Let's try custom error handling by specifying the @ExceptionHandler annotation for MethodArgumentNotValidException.

@RestControllerAdvice
public class ApiControllerAdvice {

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<Map<String, String>> handleValidationExceptions(MethodArgumentNotValidException ex){
        Map<String, String> errors = new HashMap<>();
        ex.getBindingResult().getAllErrors()
                .forEach(c -> errors.put(((FieldError) c).getField(), c.getDefaultMessage()));
        return ResponseEntity.badRequest().body(errors);
    }

}

As the ResponseEntity value, we created a Map containing the field that caused the error and the error message, and put it into the Response. The reason we declared a Map and used forEach is that when using @Valid, it returns all the contents that failed validation in the object, so we need to accommodate all error values.

Let's run the server again and check with Postman.
This time, I wrote the requestBody so that both @NotNull and @Email validation would fail.

Looking at the Response, you can see that the BadRequest status value, the errors for all field values that failed @Valid, and the custom error content are all properly reflected.

 

3. Understanding javax.constraint Annotations

I've included a reference table at the very bottom. Refer to it when needed.

Official documentation: https://docs.jboss.org/hibernate/beanvalidation/spec/2.0/api/

 

Jakarta Bean Validation API 2.0.2

 

docs.jboss.org

 

1. String Presence Validation (Differences between @NotBlank, @NotEmpty, and @NotNull)

@NotBlank 
- The value must not be null.
- Must contain at least one non-whitespace character.

@NotEmpty
- Type:
 CharSequence (length of character) Collection (collection size) Map (map size Array (array length)
- Must not be null or empty (empty string).

@NotNull
- Type:
 Accepts any type.
- The value must not be null.

@Null
- Type:
Accepts any type.
- The value must be null.

This part can be confusing, so let's create a DTO and Controller to verify.

@NoArgsConstructor
@Getter
@ToString
public class NotDto {
    @NotNull
    private String notNull;
    @NotEmpty
    private String notEmpty;
    @NotBlank
    private String notBlank;
}

The results are as follows. You can understand each validation method through their respective error messages.

  • @NotNull: A value must be present.
  • @NotEmpty: A value must exist and its length or size must be greater than 0.
  • @NotBlank: A value must exist and its length, excluding whitespace characters, must be greater than 0.

 

  null "" " "
@NotNull Invalid Valid Valid
@NotEmpty Invalid Invalid Valid
@NotBlank Invalid Invalid Invalid

Make sure to use the appropriate validation for your use case.

 

2. Min/Max Value Validation

supportType 
- BigDecimal BigInteger CharSequence byte, short, int, long, and their corresponding Wrapper classes
- double, float are not supported due to rounding errors.
- null is also considered valid.

Validation
- @DecimalMax: Must be less than or equal to the specified maximum value.
      Require: String value  => Specifies the max value.
- @DecimalMin: Must be greater than or equal to the specified minimum value.
      Require: String value  => Specifies the min value.
- @Max: Must be less than or equal to the specified maximum value.
      Require: int value  => Specifies the max value.
- @Min: Must be greater than or equal to the specified minimum value.
      Require: int value  => Specifies the min value.

Usage

@NoArgsConstructor
@Getter
@ToString
public class MinMaxDto {
    @DecimalMax(value = "1000000000")
    private BigInteger decimalMax;
    @DecimalMax(value = "1")
    private BigInteger decimalMin;
    @Max(value = 1000)
    private Integer max;
    @Max(value = 1)
    private Integer min;
}

The difference between DecimalMax/Min and Max/Min is in the range of values. The range differs significantly depending on whether you use String or Integer.

 

3. Range Value Validation

supportType 
- BigDecimal BigInteger CharSequence byte, short, int, long, double, float and their corresponding Wrapper classes
- null is also considered valid.

Validation
- @Positive: The value must be positive.
- @PositiveOrZero: The value must be zero or positive.
- @Negative: The value must be negative.
- @NegativeOrZero: The value must be zero or negative.

Usage

@NoArgsConstructor
@Getter
@ToString
public class RangeDto {
    @Positive
    private Integer positive;
    @PositiveOrZero
    private Integer positiveOrZero;
    @Negative
    private Integer negative;
    @NegativeOrZero
    private Integer negativeOrZero;
}

 

4. Time Value Validation

supportType 
- 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
- null is also considered valid.

Validation
- @Future: Must be a date/time in the future compared to Now.
- @FutureOrPresent: Must be Now or a date/time in the future.
- @Past: Must be a date/time in the past compared to Now.
- @PastOrPresent : Must be Now or a date/time in the past.

Definition of Now: The current time is defined according to the virtual machine of the ClockProvider, and the default time zone is applied if necessary.

Usage

@NoArgsConstructor
@Getter
@ToString
public class TimeDto {
    @Future
    private Date future;
    @FutureOrPresent
    private Date futureOrPresent;
    @Past
    private Date past;
    @PastOrPresent
    private Date pastOrPresent;
}

 

4. Email Validation

supportType 
- null is also considered valid.

Validation
- @Email: Must be a properly formatted email address (must contain @).

Usage

@NoArgsConstructor
@Getter
@ToString
public class EmailDto {
    @Email
    private String email;
}

 

5. Digit Range Validation

supportType 
- BigDecimal BigInteger CharSequence byte, short, int, long, and their corresponding Wrapper classes
- null is also considered valid.

Validation
- @Digits: Must be a number within the allowed range.
      Require: int integer  => Maximum number of integer digits allowed for this number.
      Require: int fraction  => Maximum number of fractional digits allowed for this number.

Usage

@NoArgsConstructor
@Getter
@ToString
@Builder
@AllArgsConstructor
public class DigitsDto {
    @Digits(integer = 5, fraction = 5)
    private Integer digits;
}

 

6. Boolean Value Validation

supportType 
- Boolean, boolean

Validation
- @AssertTrue: The value must always be True.
- @AssertFalse: The value must always be False.

Usage

@NoArgsConstructor
@Getter
@ToString
public class BooleanDto {
    @AssertTrue
    private boolean assertTrue;
    @AssertFalse
    private boolean assertFalse;
}

 

7. Size Validation

supportType 
- CharSequence (length of character sequence) Collection (collection size) Map (map size) Array (array length)
- null is also considered valid.

Validation
- @Size: The size must be between the specified boundaries (inclusive).
      Require: int max  => The element size must be less than or equal to this value.
      Require: int min  => The element size must be greater than or equal to this value.

Usage

@NoArgsConstructor
@Getter
@ToString
public class SizeDto {
    @Size(max = 5, min = 3)
    private String size;
}

 

8. Regex Validation

supportType 
- CharSequence
- null is also considered valid.

Validation
- @Pattern: The string must match the specified regular expression. It follows the conventions of Java's Pattern package.
      Require: String regexp  => Specifies the regex string.

Usage

@NoArgsConstructor
@Getter
@ToString
public class PatternDto {
    //yyyy-mm-dd 형태를 가지는 패턴 조사
    @Pattern(regexp = "^(19|20)\\d{2}-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[0-1])$")
    private String pattern;
}

 

4. @Valid Summary Table

@AssertTrue Boolean, boolean The value must always be True.  
@DecimalMax Numeric classes excluding floating-point types. The number must be less than or equal to the specified maximum value. String : value (specifies the max value.)
@DecimalMin Numeric classes excluding floating-point types. The number must be greater than or equal to the specified minimum value. String : value (specifies the min value.)
@Digits BigDecimal, BigInteger, CharSequence, byte, short, int, long, and their corresponding Wrapper classes The number must be within the allowed range. int : integer (maximum number of integer digits allowed for this number)
int : fraction (maximum number of fractional digits allowed for this number)
@Email null is also considered valid. Must be a properly formatted email address.  
@Future Date/time classes A date or time in the future relative to Now  
@FutureOrPresent Date/time classes A date or time that is Now or in the future  
@Max Numeric classes excluding floating-point types. The number must be less than or equal to the specified maximum value. long : value (specifies the max value)
@Min Numeric classes excluding floating-point types. The number must be greater than or equal to the specified minimum value. long : value (specifies the min value)
@Negative Numeric classes The value must be negative.  
@NegativeOrZero Numeric classes The value must be 0 or negative.  
@NotBlank   The value must not be null. Must contain at least one non-whitespace character.  
@NotEmpty CharSequence, Collection, Map, Array Must not be null or empty (empty string).  
@NotNull Accepts any type. The value must not be null.  
@Null Accepts any type. The value must be null.  
@Past Date/time classes A date or time in the past relative to Now  
@PastOrPresent Date/time classes A date or time that is Now or in the past  
@Pattern String The string must match the specified regular expression. Follows the conventions of Java's Pattern package. String : regexp (specifies the regex string)
@Positive Numeric classes The value must be positive.  
@PositiveOrZero Numeric classes The value must be 0 or positive.  
@Size CharSequence, Collection, Map, Array The size must be between the specified boundaries (inclusive). int : max (the element size must be less than or equal to this)
int : min (the element size must be greater than or equal to this)

[@ValidAnnotation].List : Defines multiple @ValidAnnotation[] constraints on the same element.

In practice, this doesn't seem to be used very often.

 

[Related Blog]

I've also uploaded the same content to our team blog.

https://javabom.tistory.com/

 

Javabom

A Java Spring blog.

javabom.tistory.com

 

References

https://www.baeldung.com/spring-boot-bean-validation

https://www.baeldung.com/java-bean-validation-not-null-empty-blank

 

댓글

Comments