每个Validation注解都有一个相同的配置参数
message
,用来定义校验失败抛出的异常信息。
Bean属性校验失败,Hibernate Validator
抛出MethodArgumentNotValidException
异常,示例如下:
{
"timestamp": 1604281270618,
"status": 400,
"error": "Bad Request",
"exception": "org.springframework.web.bind.MethodArgumentNotValidException",
"errors": [
{
"codes": [
"AssertTrue.department.locatedInJiNan",
"AssertTrue.locatedInJiNan",
"AssertTrue.java.lang.Boolean",
"AssertTrue"
],
"arguments": [
{
"codes": [
"department.locatedInJiNan",
"locatedInJiNan"
],
"arguments": null,
"defaultMessage": "locatedInJiNan",
"code": "locatedInJiNan"
}
],
"defaultMessage": "只可以为true",
"objectName": "department",
"field": "locatedInJiNan",
"rejectedValue": false,
"bindingFailure": false,
"code": "AssertTrue"
}
],
"message": "Validation failed for object='department'. Error count: 1",
"path": "/department/add"
}
URL参数校验失败,Hibernate Validator
抛出ConstraintViolationException
异常,示例如下:
{
"timestamp": 1604281366585,
"status": 500,
"error": "Internal Server Error",
"exception": "javax.validation.ConstraintViolationException",
"message": "update.desc: 长度需要在1和3之间",
"path": "/department/update/abf"
}
这两个原生异常,对用户不友好,也不符合项目返回数据格式。所以需要进行统一异常处理,统一Hibernate Validator
校验失败时返回数据格式,示例代码如下:
package com.inspur.validator.controller;
import com.inspur.validator.common.ReturnBean;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.Set;
/**
* @author mark
* @date 2020/11/1 16:20
*/
@ControllerAdvice
public class ExceptionHanderController {
/**
* 处理Hibernate Validator校验Bean参数抛出异常
*/
@ResponseBody
@ExceptionHandler(MethodArgumentNotValidException.class)
public ReturnBean handlerMethodArgumentNotValidException(MethodArgumentNotValidException e) {
// 1.校验
Boolean fieldErrorUnobtainable = (e == null || e.getBindingResult() == null
|| CollectionUtils.isEmpty(e.getBindingResult().getAllErrors()) || e.getBindingResult().getAllErrors().get(0) == null);
if (fieldErrorUnobtainable) {
return ReturnBean.success();
}
// 2.错误信息
FieldError fieldError = (FieldError) e.getBindingResult().getAllErrors().get(0);
String objectName = fieldError.getObjectName();
String field = fieldError.getField();
String defaultMessage = fieldError.getDefaultMessage();
String errMsg = "参数" + objectName + '.' + field + ":" + defaultMessage;
// 3.return
return ReturnBean.fail(errMsg);
}
/**
* 处理Hibernate Validator校验URL参数抛出异常
*/
@ResponseBody
@ExceptionHandler(ConstraintViolationException.class)
public ReturnBean handlerConstraintViolationException(ConstraintViolationException e) {
// 1.校验
Set<ConstraintViolation<?>> constraintViolations = e.getConstraintViolations();
if (CollectionUtils.isEmpty(constraintViolations)) {
return ReturnBean.success();
}
// 2.错误信息
ConstraintViolation<?> constraintViolation = constraintViolations.iterator().next();
String name = constraintViolation.getPropertyPath().toString();
String message = constraintViolation.getMessage();
String errMsg = "参数" + name + ":" + message;
// 3.return
return ReturnBean.fail(errMsg);
}
}
补充说明:@ControllerAdvice
注解和@ExceptionHandler
的配合使用,是基于Spring提供的能力,开启全局异常处理。@ExceptionHandler
注解的配置参数value()
是用来指定截获哪种异常。