问题
Dear Spring Community,
I am building my project using Spring. In my API layer, I am leveraging the Validator interface in order to do some custom validation and set an error.
@Override
public void validate(Object obj, Errors e) {
SignUpRequest signUpRequest = (SignUpRequest) obj;
User user = userService.getUserByEmail(signUpRequest.getEmail());
if (user != null) {
e.rejectValue("user", ErrorCodes.USER_EXIST, "user already exist");
}
}
Now, in my API signature, since I am using the BindingResult object, in the @ControllerAdvice that I have, if the user provides an empty value for an attribute of my DTO object, I wont be able to get into the @ExceptionHandler(MethodArgumentNotValidException.class).
What this means is that, I wont be able to throw an HttpStatus.BAD_REQUEST
for any empty value provided.
In the above case of my validator, It wont be a HttpStatus.BAD_REQUEST
but rather it will be a HttpStatus.OK
. So my problem is that, how do I provide different HttpStatus types based on the errors I am getting from my validator? Also is there a way to have the empty value still get picked up by the @ExceptionHandler(MethodArgumentNotValidException.class)
in my @ControllerAdvice
and have my other custom validations picked up by the bindingResult?
I hope I am clear on the question. Appreciate any help!
回答1:
OK, I believe I came up with the solution! In order to have different HttpStatus being thrown base on the type of error you have, you need to have custom exceptions. Then have your custom exceptions thrown inside your Validator. Your ControllerAdvice should register to pick up the custom exceptions and act upon them accordingly.
For example the Validator should have something like this:
if (!matcher.matches()) {
e.rejectValue("email", ErrorCodes.EMAIL_INVALID, "email address is invalid");
throw new BadRequestException("email address is invalid", e);
}
User user = userService.getUserByEmail(signUpRequest.getEmail());
if (user != null) {
e.rejectValue("email", ErrorCodes.USER_EXIST, "user already exist");
throw new ValidationException("User Exist", e);
}
And the Controller Advice should have:
@ExceptionHandler(ValidationException.class)
@ResponseBody
public ResponseEntity<Map<String, Object>> handleValidationException(
ValidationException validationException) {
Map<String, Object> result = createErrorResponse(validationException.getErrors());
return new ResponseEntity<Map<String, Object>>(result, HttpStatus.OK);
}
@ExceptionHandler(BadRequestException.class)
@ResponseBody
public ResponseEntity<Map<String, Object>> handleBadRequestException(
BadRequestException badRequestException) {
Map<String, Object> result = createErrorResponse(badRequestException.getErrors());
return new ResponseEntity<Map<String, Object>>(result, HttpStatus.BAD_REQUEST);
}
This way, you can have different HttpStatus returned base on the type of error you have.
来源:https://stackoverflow.com/questions/31780505/spring-validator-and-bindingresult-how-to-set-different-httpstatus-codes