Return @notnull 验证失败时响应代码为 400

Return response code as 400 when @notnull validation fails

我正在使用 javax 和 Hibernate 实现来验证我的请求负载。

版本 - org.hibernate:hibernate-validator:5.4.1.final

示例 Pojo:

import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.io.Serializable;

    public class Customer implements Serializable{

        @NotNull(message="name is null")
        @Size(min = 1)
        public String name;
        @NotNull(message="country is null")
        @Size(min = 1)
        public String country;
    }

示例控制器:

    @RequestMapping(value = {"/customer"}, method = RequestMethod.POST)
    @ResponseBody
    public Customer doAdd(@RequestBody @Valid Customer inData){
        //some logic
return outData
    }

样本输入json:

{
"country":"canada"
}

控制台异常:

org.springframework.web.bind.MethodArgumentNotValidException: Validation failed for argument at index 0 in method: ........ model.request.Customer,java.lang.String,java.lang.String,javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse), with 1 error(s): [Field error in object 'Customer' on field 'name': rejected value [null]; codes [NotNull.Customer.name,NotNull.name,NotNull.java.lang.String,NotNull]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [Customer.name,name]; arguments []; default message [name]]; default message [name is null]]

此处,当 customer.name 为空时,我得到的响应代码为 422(无法处理的实体)。但我想 return 400(BAD Request)。我怎样才能在这里覆盖响应代码?任何文件参考将不胜感激。

注意 - 我不想在控制器端进行这些验证,我可以在哪里检查并相应地发送响应代码。 喜欢这个 -

更新 - 问题已解决 ------

我的问题已经解决了。谢谢大家的回复。

让我解释一下是什么原因造成的,

HttpRequest ----> @Valid on RequestBody ----> Javax validation on Request object-----> If any of the validation fails, **MethodArgumentNotValidException** exception is thrown.

开发人员有责任捕获此异常并抛出相应的 http 响应代码。 在我的例子中,异常处理程序已经存在并且正在捕获此 MethodArgumentNotValidException 和 returning HttpStatus.UNPROCESSABLE_ENTITY。这就是我看到 422 错误代码的原因。

现在我已经将异常处理程序更改如下,

@ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<ErrorResource>
    handleMethodArgumentNotValidException(MethodArgumentNotValidException exception, HttpServletRequest request) {

        List<FieldErrorResource> fieldErrorResources = new ArrayList<>();
        BindingResult bindingResult = exception.getBindingResult();
        for (FieldError constraintViolation : bindingResult.getFieldErrors()) {
            fieldErrorResources.add(FieldErrorResource.builder()
                    .field(constraintViolation.getField())
                    .resource(request.getContextPath())
                    .message(constraintViolation.getDefaultMessage()).build());
        }

        return responseEntityFor(HttpStatus.BAD_REQUEST,
                "The content you've sent contains " + bindingResult.getErrorCount() + " validation errors.", fieldErrorResources);
    }

您应该在 Customer 之后立即设置 BindingResult。喜欢:

@RequestMapping(value = {"/customer"}, method = RequestMethod.POST)
@ResponseBody
public Customer doAdd(@RequestBody @Valid Customer inData, BindingResult bindingResult){
    //some logic
    return outData
}

您可以使用 RestControllerAdvice 来实现同样的效果

@RestControllerAdvice
public class ExceptionRestControllerAdvice {

    @ExceptionHandler({ConstraintViolationException.class})
    @ResponseStatus(value = HttpStatus.BAD_REQUEST)
    public ExceptionResponseMessage handleInvalidParameterException(RuntimeException ex) {

        return sendResponse(HttpStatus.BAD_REQUEST, ex);
    }

    private ExceptionResponseMessage sendResponse(HttpStatus status, RuntimeException ex) {

        return new ExceptionResponseMessage(Instant.now(), status.value(), status.getReasonPhrase(),
                ex.getClass().toString(), ex.getMessage());
    }
}

public class ExceptionResponseMessage {

    private Instant time;
    private int status;
    private String error;
    private String exception;
    private String message;

    // setter and getter and constructor