前言
我们常见异常返回如下
{"timestamp":"2020-03-11T07:33:39.442+0000","status":400,"error":"Bad Request","message":"xxxxxxxx","path":"/validParams"}
在尤其在我们是用@Valid和@Validated注解的时候,message信息是不友好的,能不能显示我们希望的异常数据呢?可以的。所有的异常数据最后的处理都是DefaultErrorAttributes类中,重写此类,将异常信息改变成我们希望的即可。
解决
@Slf4j
@RestController
@Validated
public class Valid2Controller {
@PostMapping("validUser")
public String validUser(@RequestBody @Valid User user){
return "success";
}
@PostMapping("validParams")
public String validParams(@RequestParam("list") @NotEmpty(message = "集合不能为空") List<String> list,
@RequestParam("name") @NotBlank(message = "名称不能为空") String name) { return "success"; }
@PostMapping("validUserNotFound")
public String validUserNotFound(@RequestBody User user){
throw new UserNotFoundException("用户不存在?");
}
// reason 会覆盖 message
@ResponseStatus(code = HttpStatus.INTERNAL_SERVER_ERROR,reason = "用户不存在")
static class UserNotFoundException extends RuntimeException{
public UserNotFoundException() {}
public UserNotFoundException(String message) {
super(message);
}
}
}
package com.delicacy.durian.validation.error;
import org.hibernate.validator.internal.engine.path.PathImpl;
import org.springframework.boot.web.servlet.error.DefaultErrorAttributes;
import org.springframework.stereotype.Component;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.context.request.WebRequest;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
@Component
public class ValidDefaultErrorAttributes extends DefaultErrorAttributes {
@Override
public Map<String, Object> getErrorAttributes(WebRequest webRequest,
boolean includeStackTrace) {
Map<String, Object> errorAttributes = super.getErrorAttributes(webRequest, includeStackTrace);
if (errorAttributes.isEmpty()) return errorAttributes;
Throwable error = getError(webRequest);
if (error instanceof MethodArgumentNotValidException) {
BindingResult bindingResult = ((MethodArgumentNotValidException) error).getBindingResult();
Map<String, String> errors1 = new HashMap<>();
bindingResult.getAllErrors().forEach((ee) -> {
String fieldName = ((FieldError) ee).getField();
String errorMessage = ee.getDefaultMessage();
errors1.put(fieldName, errorMessage);
});
handleErrorAttributes(errorAttributes, errors1);
} else if (error instanceof ConstraintViolationException) {
Set<ConstraintViolation<?>> constraintViolations = ((ConstraintViolationException) error).getConstraintViolations();
if (constraintViolations.isEmpty()) return errorAttributes;
Map<String, String> errors1 = new HashMap<>();
constraintViolations.stream().forEach(ee -> {
String fieldName = ((PathImpl) ee.getPropertyPath()).getLeafNode().getName();
String errorMessage = ee.getMessageTemplate();
errors1.put(fieldName, errorMessage);
});
handleErrorAttributes(errorAttributes, errors1);
}
return errorAttributes;
}
private void handleErrorAttributes(Map<String, Object> errorAttributes, Map<String, String> fromError) {
if (fromError.isEmpty()) return;
String msg = fromError.values().stream().collect(Collectors.joining(","));
errorAttributes.put("message", msg);
errorAttributes.put("details", fromError);
errorAttributes.put("status", 400);
errorAttributes.put("error", "Bad Request");
}
}
截取的异常数据日志
2020-04-11 13:19:19.506 ERROR 18036 --- [ main] c.d.d.v.DurianValidationApplicationTests : error={"timestamp":"2020-04-11T05:19:19.336+0000","status":400,"error":"Bad Request","errors":[{"codes":["NotBlank.user.name","NotBlank.name","NotBlank.java.lang.String","NotBlank"],"arguments":[{"codes":["user.name","name"],"arguments":null,"defaultMessage":"name","code":"name"}],"defaultMessage":"名称不能为空","objectName":"user","field":"name","rejectedValue":"","bindingFailure":false,"code":"NotBlank"}],"message":"名称不能为空","path":"/b/validUser","details":{"name":"名称不能为空"}}
null
2020-04-11 13:19:19.575 ERROR 18036 --- [ main] c.d.d.v.DurianValidationApplicationTests : error={"timestamp":"2020-04-11T05:19:19.570+0000","status":400,"error":"Bad Request","message":"名称不能为空,集合不能为空","path":"/b/validParams","details":{"name":"名称不能为空","list":"集合不能为空"}}
null
2020-04-11 13:19:19.594 ERROR 18036 --- [ main] c.d.d.v.DurianValidationApplicationTests : error={"timestamp":"2020-04-11T05:19:19.592+0000","status":500,"error":"Internal Server Error","message":"用户不存在","path":"/b/validUserNotFound"}
null