
beanvalidation
https://beanvalidation.org/2.0/spec/
@Size : 문자 길이 측정, int 불가@NotNull : null 불가@NotEmpty : null, ""불가@NotBlank: null,""," " 불가@Pattern: 정규식 적용@Max @Min : 최대값/최소값@AssertTrue/False : 별도 logic 적용@Past @PastOrPresent @Future @FutureOrPresent implementation 'org.springframework.boot:spring-boot-starter-validation'
//controller
@PostMapping("")
public Api<UserRegisterRequest> register(
@Valid
@RequestBody
Api<UserRegisterRequest> userRegisterRequest
){...}
//model
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
public class UserRegisterRequest {
@NotBlank
private String name;
@NotNull
@Min(1)
@Max(100)
private Integer age;
}
이 상태에서 validate 에러가 발생하면 서버의 terminal에만 확인할 수 있다.
클라이언트에게 전달하려면 아래의 방법을 적용한다.

@Slf4j
@RestController
@RequestMapping("/api/user")
public class UserApiControllerValidate {
@PostMapping("")
// public Api<UserRegisterRequest> register(
// error에 body가 없기때문에 UserRegisterRequest 반환못함
public Api<? extends Object> register(
@Valid
@RequestBody
Api<UserRegisterRequest> userRegisterRequest,
BindingResult bindingResult // 에러 잡기 1 . valid실행결과를 binding result에 담아줌
){
log.info("init : {}",userRegisterRequest);
if(bindingResult.hasErrors()){ //에러가 발생했다면
var errorMessageList = bindingResult.getFieldErrors().stream()
.map(it->{
var format = "%s :{ %s } 은 %s";
// 어떤 필드에서 어떤 값이 거절당했는지, 디폴트 메세지 출력
var message = String.format(format, it.getField(),it.getRejectedValue(),it.getDefaultMessage());
return message;
}).collect(Collectors.toList());
var error = Api.Error.builder()
.errorMessage(errorMessageList)
.build();
var errorResponse = Api.builder()
.resultCode(String.valueOf(HttpStatus.BAD_REQUEST.value()))
.resultMessage(HttpStatus.BAD_REQUEST.getReasonPhrase())
.error(error)
.build();
return errorResponse;
}
var body = userRegisterRequest.getData();
Api<UserRegisterRequest> response = Api.<UserRegisterRequest>builder()
.resultCode(String.valueOf(HttpStatus.OK.value()))
.resultMessage(HttpStatus.OK.getReasonPhrase())
.data(body)
.build();
return response;
}
}

🔺 result_code = 400인데 전체 status_code는 200으로 전달됨
public ResponseEntity<Api<? extends Object>> register(
위와 같이 ResponseEntiy로 감싸서 sataus_code를 지정해줄 수 있음
하지만 검증 코드가 너무 길어지고 복잡해짐
@Slf4j
@RestControllerAdvice
public class ValidationExceptionHandler {
@ExceptionHandler(value = {MethodArgumentNotValidException.class})
public ResponseEntity<Api> validateException(
MethodArgumentNotValidException e
){
log.error("",e);
var errorMessageList = e.getFieldErrors().stream()
.map(it->{
var format = "%s :{ %s } 은 %s";
// 어떤 필드에서 어떤 값이 거절당했는지, 디폴트 메세지 출력
var message = String.format(format, it.getField(),it.getRejectedValue(),it.getDefaultMessage());
return message;
}).collect(Collectors.toList());
var error = Api.Error.builder()
.errorMessage(errorMessageList)
.build();
var errorResponse = Api.builder()
.resultCode(String.valueOf(HttpStatus.BAD_REQUEST.value()))
.resultMessage(HttpStatus.BAD_REQUEST.getReasonPhrase())
.error(error)
.build();
return ResponseEntity
.status(HttpStatus.BAD_REQUEST)
.body(errorResponse);
}
}
controller 부분에는 정상 로직만 남겨두어 간결해진다.
@Slf4j
@RestController
@RequestMapping("/api/user")
public class UserApiControllerValidate {
@PostMapping("")
public Api<UserRegisterRequest> register(
@Valid
@RequestBody
Api<UserRegisterRequest> userRegisterRequest
){
log.info("init : {}",userRegisterRequest);
var body = userRegisterRequest.getData();
Api<UserRegisterRequest> response = Api.<UserRegisterRequest>builder()
.resultCode(String.valueOf(HttpStatus.OK.value()))
.resultMessage(HttpStatus.OK.getReasonPhrase())
.data(body)
.build();
return response;
}
}