<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
@Builder
public class ValidRequestDto {
@NotBlank
String name;
@Email
String email;
@Pattern(regexp = "01(?:0|1|[6-9])[.-]?(\\d{3}|\\d{4})[.-]?(\\d{4})$")
String phoneNumber;
@Min(value = 20) @Max(value = 40)
int age;
@Size(min=0, max=40)
String description;
@Positive
int count;
@AssertTrue
boolean booleanCheck;
}
유효성을 검증할 필드에 어노테이션으로 조건을 설정해준다.
유효성 검증 어노테이션
@RestController
@RequestMapping("/validation")
public class ValidationController {
@PostMapping("/valid")
public ResponseEntity<String> checkValidationByValid(
@Valid @RequestBody ValidRequestDto validRequestDto){
return ResponseEntity.status(HttpStatus.OK).body(validRequestDto.toString());
}
}
다음과 같이 phoneNumber에 유효하지 않은 값을 넣을 시 400 오류가 발생한다.
로그 라이브러리를 추가하지 않아서 확인해보지 못했지만 로그 라이브러리 사용 시 실패한 개수 및 실패한 지점을 확인할 수 있다.
@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})$")
String phoneNumber;
@Min(value = 20,groups = ValidationGroup1.class)
@Max(value = 40,groups = ValidationGroup1.class)
int age;
@Size(min=0, max=40)
String description;
@Positive(groups = ValidationGroup2.class)
int count;
@AssertTrue
boolean booleanCheck;
}
groups 속성을 사용해 어느 그룹에 맞춰 유효성 검사를 실시할 것인지 지정한다.
@RestController
@RequestMapping("/validation")
public class ValidationController {
private final Logger LOGGER = LoggerFactory.getLogger(ValidationController.class);
// @PostMapping("/valid")
// public ResponseEntity<String> checkValidationByValid(
// @Valid @RequestBody ValidRequestDto validRequestDto){
// return ResponseEntity.status(HttpStatus.OK).body(validRequestDto.toString());
// }
@PostMapping("/validated")
public ResponseEntity<String> checkValidation(
@Validated @RequestBody ValidatedRequestDto validatedRequestDto){
LOGGER.info(validatedRequestDto.toString());
return ResponseEntity.status(HttpStatus.OK).body(validatedRequestDto.toString());
}
@PostMapping("/validated/group1")
public ResponseEntity<String> checkValidation1(
@Validated(ValidationGroup1.class) @RequestBody ValidatedRequestDto validatedRequestDto){
LOGGER.info(validatedRequestDto.toString());
return ResponseEntity.status(HttpStatus.OK).body(validatedRequestDto.toString());
}
@PostMapping("/validated/gruop2")
public ResponseEntity<String> checkValidation2(
@Validated(ValidationGroup2.class) @RequestBody ValidatedRequestDto validatedRequestDto){
LOGGER.info(validatedRequestDto.toString());
return ResponseEntity.status(HttpStatus.OK).body(validatedRequestDto.toString());
}
@PostMapping("/validated/all-group")
public ResponseEntity<String> checkValidation3(
@Validated({ValidationGroup1.class, ValidationGroup2.class}) @RequestBody ValidatedRequestDto validatedRequestDto){
LOGGER.info(validatedRequestDto.toString());
return ResponseEntity.status(HttpStatus.OK).body(validatedRequestDto.toString());
}
}
@Validated 어노테이션에 해당 그룹을 지정하면 해당 그룹에 맞게 유효성 검사를 실시한다.
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})$");
}
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = TelephoneValidator.class)
public @interface Telephone {
String message() default "전화번호 형식이 일치하지 않음";
Class[] groups() default {};
Class[] payload() default {};
}
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
@Builder
public class ValidatedRequestDto {
@NotBlank
String name;
@Email
String email;
@Telephone
String phoneNumber;
@Min(value = 20)
@Max(value = 40)
int age;
@Size(min=0, max=40)
String description;
@Positive
int count;
@AssertTrue
boolean booleanCheck;
}
책에 groups를 지정하지 않아 오류가 뜨는 것이 당연하다고 하는데 그 해결방법은 알려주지 않았다 다음파트에서 알려준다는데 그 파트가 책에 없음ㅡ.ㅡ
그래서 groups에 처음에 만들어서 적용했던 ValidationGroup1.class도 넣어보고 이것저것 해봤지만 해결이 안되길래 답답한 상태로 남겨둔 채 일단 패스