Spring Validator and BindingResult - How to set different HttpStatus Codes?

北城以北 提交于 2021-02-19 07:58:12

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!