alue = ConstraintViolationException.class)
public Response handle1(ConstraintViolationException ex){
StringBuilder msg = new StringBuilder();
Set<ConstraintViolation<?>> constraintViolations = ex.getConstraintViolations();
for (ConstraintViolation<?> constraintViolation : constraintViolations) {
PathImpl pathImpl = (PathImpl) constraintViolation.getPropertyPath();
String paramName = pathImpl.getLeafNode().getName();
String message = constraintViolation.getMessage();
msg.append("[").append(message).append("]");
}
logger.error(msg.toString(),ex);
// 注意:Response类必须有get和set方法,不然会报错
return new Response(RCode.PARAM_INVALID.getCode(),msg.toString());
}
@ExceptionHandler(value = Exception.class)
public Response handle1(Exception ex){
logger.error(ex.getMessage(),ex);
return new Response(RCode.ERROR.getCode(),RCode.ERROR.getMsg());
}
}
调用结果
# 这里没有传 userId
GET http://127.0.0.1:9999/user/getUser
HTTP/1.1 200
Content-Type: application/json
Transfer-Encoding: chunked
Date: Sat, 14 Nov 2020 07:35:44 GMT
Keep-Alive: timeout=60
Connection: keep-alive
{
"rtnCode": "1000",
"rtnMsg": "[userId 不能为空]"
}
实体类 DTO 校验
定义一个 DTO
import org.hibernate.validator.constraints.Range;
import javax.validation.constraints.NotEmpty;
public class UserDTO {
private Integer userId;
@NotEmpty(message = "姓名不能为空")
private String name;
@Range(min = 18,max = 50,message = "年龄必须在18和50之间")
private Integer age;
@DecimalMin(value = "0.00", message = "费率格式不正确",groups = UpdateFeeRate.class)
@DecimalMax(value = "100.00", message = "费率格式不正确",groups = UpdateFeeRate.class)
private BigDecimal gongzi;
//省略get和set方法
}
接收参数时使用@Validated 进行校验
@PostMapping("/saveUser")
@ResponseBody
//注意:如果方法中的参数是对象类型,则必须要在参数对象前面添加 @Validated
public Response<UserDTO> getUser(@Validated @RequestBody UserDTO userDTO){
userDTO.setUserId(100);
Response response = Response.success();
response.setData(userDTO);
return response;
}
统一异常处理
@ExceptionHandler(value = MethodArgumentNotValidException.class)
public Response handle2(MethodArgumentNotValidException ex){
BindingResult bindingResult = ex.getBindingResult();
if(bindingResult!=null){
if(bindingResult.hasErrors()){
FieldError fieldError = bindingResult.getFieldError();
String field = fieldError.getField();
String defaultMessage = fieldError.getDefaultMessage();
logger.error(ex.getMessage(),ex);
return new Response(RCode.PARAM_INVALID.getCode(),field+":"+defaultMessage);
}else {
logger.error(ex.getMessage(),ex);
return new Response(RCode.ERROR.getCode(),RCode.ERROR.getMsg());
}
}else {
logger.error(ex.getMessage(),ex);
return new Response(RCode.ERROR.getCode(),RCode.ERROR.getMsg());
}
}
调用结果
创建用户
POST http://127.0.0.1:9999/user/saveUser
Content-Type: application/json
{
"name1": "程序员自由之路",
"age": "18"
}
下面是返回结果
{
"rtnCode": "1000",
"rtnMsg": "姓名不能为空"
}
对 Service 层方法参数校验
个人不太喜欢这种校验方式,一半情况下调用 service 层方法的参数都需要在 controller 层校验好,不需要再校验一次。这边列举这个功能,只是想说 Spring 也支持这个。