优化Response异常处理(使用jsr303参数校验)

前言

我们常见异常返回如下

{"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
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值