SpringBoot统一返回值处理及异常处理

先整体看下代码结构:
在这里插入图片描述
返回结果封装类RestResult:

@Data
@AllArgsConstructor
@NoArgsConstructor
public class RestResult {

    private Integer code;
    private String message;
    private Object data;

    public static RestResult of(Object data) {
        return new RestResult(0, "success", data);
    }

    public static RestResult of(Exception e) {
        if (e instanceof BusinessException) {
            return new RestResult(((BusinessException) e).getCodeId(), e.getMessage(), ((BusinessException) e).getErrors());
        } else {
            return new RestResult(500, e.getMessage(), Collections.emptyMap());
        }
    }

    public static RestResult of(Exception e, Integer code) {
        if (e instanceof BusinessException) {
            return new RestResult(((BusinessException) e).getCodeId(), e.getMessage(), ((BusinessException) e).getErrors());
        } else {
            return new RestResult(code, e.getMessage(), Collections.emptyMap());
        }
    }
}

统一异常封装类:

/**
 * @description: 对于需要给用户展示的异常,统一抛出此异常
 * @author: JJC
 * @createTime: 2019/3/28
 */
public class BusinessException extends RuntimeException implements Serializable {
    private final ErrorCode code;
    private final Map<String, ? extends Object> errors;

    public BusinessException(ErrorCode code, Map<String, Object> errors) {
        super(code.getReason());
        this.code = code;
        this.errors = errors;
    }

    public BusinessException(String message, ErrorCode code, Map<String, ? extends Object> errors) {
        super(message);
        this.code = code;
        this.errors = errors;
    }

    public BusinessException(String message, Throwable cause, ErrorCode code, Map<String, ? extends Object> errors) {
        super(message, cause);
        this.code = code;
        this.errors = errors;
    }

    public BusinessException(Throwable cause, ErrorCode code, Map<String, ? extends Object> errors) {
        super(cause.getMessage(), cause);
        this.code = code;
        this.errors = errors;
    }

    public BusinessException(ErrorCode code) {
        super(code.getReason());
        this.code = code;
        this.errors = new HashMap<>();
    }

    public BusinessException(String message, ErrorCode code) {
        super(message);
        this.code = code;
        this.errors = new HashMap<>();
    }

    public BusinessException(String message, Throwable cause, ErrorCode code) {
        super(message, cause);
        this.code = code;
        this.errors = cause instanceof ServiceException ? ((ServiceException) cause).getErrors() : new HashMap<>();
    }

    public BusinessException(Throwable cause, ErrorCode code) {
        super(cause.getMessage(), cause);
        this.code = code;
        this.errors = cause instanceof ServiceException ? ((ServiceException) cause).getErrors() : new HashMap<>();
    }

    public ErrorCode getCode() {
        return this.code;
    }

    @Override
    public String toString() {
        Map<String, Object> map = new HashMap<>();
        map.put("httpStatus", this.getCode().getHttpStatus());
        map.put("code", this.getCode().getCode());
        map.put("reason", this.getCode().getReason());
        map.put("solution", this.getCode().getSolution());
        map.put("message", this.getMessage());
        return JSONObject.toJSONString(map, SerializerFeature.WriteMapNullValue);
    }

    public Map<String, ? extends Object> getErrors() {
        return this.errors;
    }

    public Integer getCodeId() {
        return this.code.getCode();
    }
}

异常枚举:

@Getter
public enum ErrorCode {

    // 通用
    METHOD_ARGUMENT_NOT_VALID(HttpStatus.BAD_REQUEST.value(),HttpStatus.BAD_REQUEST.value(),"参数约束错误","调整参数");

    private Integer httpStatus;
    private Integer code;
    private String reason;
    private String solution;

    ErrorCode(Integer httpStatus, Integer code, String reason, String solution) {
        // FIXME: 自定义异常的 Http Status 统一为 200
        this.httpStatus = HttpStatus.OK.value();
        // 错误码的前缀为期望的HttpStatus
        this.code = code;
        this.reason = reason;
        this.solution = solution;
    }
}

统一返回值处理:

@ControllerAdvice(annotations = RestController.class)
public class ResultHandlerAdvice implements ResponseBodyAdvice<Object> {

    @Override
    public boolean supports(MethodParameter returnType, Class converterType) {
        return true;
    }

    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType mediaType, Class converterType, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
        if (null == body) {
            return RestResult.of(Collections.emptyMap());
        }
        return RestResult.of(body);
    }

}

统一异常处理:

@ControllerAdvice(annotations = RestController.class)
public class PandaExceptionHandler extends ResponseEntityExceptionHandler {
    private static Logger logger = LoggerFactory.getLogger(PandaExceptionHandler.class);

    /**
     * 处理业务异常
     */
    @ExceptionHandler(value = Exception.class)
    protected ResponseEntity<Object> handleException(Exception exception, HttpServletRequest request, HttpServletResponse response) {
        this.logError(exception, request.getRequestURI(), request.getParameterMap());
        RestResult errorBody = RestResult.of(exception);
        ResponseEntity<Object> responseEntity = new ResponseEntity<>(errorBody, HttpStatus.INTERNAL_SERVER_ERROR);
        return responseEntity;
    }

    private void logError(Exception exception, String uri, Map<String, String[]> parameterMap) {
        logger.error("request error.request url:" + uri + ". params:" + JSONObject.toJSON(parameterMap).toString() + ". traceId:" + Tracer.id());
        logger.error(exception.toString(), exception);
    }

    @Override
    protected ResponseEntity<Object> handleExceptionInternal(Exception exception, @Nullable Object body, HttpHeaders headers, HttpStatus status, WebRequest request) {
        this.logError(exception, ((ServletWebRequest) request).getRequest().getRequestURI(), request.getParameterMap());
        if (HttpStatus.INTERNAL_SERVER_ERROR.equals(status)) {
            request.setAttribute("javax.servlet.error.exception", exception, 0);
        }
        RestResult errorBody = RestResult.of(exception, status.value());
        return new ResponseEntity(errorBody, headers, status);
    }

    /**
     * 处理javax.validation参数校验不通过异常
     */
    @Override
    protected ResponseEntity<Object> handleMethodArgumentNotValid(
        MethodArgumentNotValidException exception, HttpHeaders headers, HttpStatus status, WebRequest request) {
        Map<String, Object> errors = new HashMap<>();
        for (ObjectError error : exception.getBindingResult().getAllErrors()) {
            errors.put(((FieldError) error).getField(), error.getDefaultMessage());
        }
        BusinessException businessException = new BusinessException(ErrorCode.METHOD_ARGUMENT_NOT_VALID, errors);
        return this.handleException(businessException, RequestContextHolderUtil.getRequest(), RequestContextHolderUtil.getResponse());
    }
}

有个坑需要注意,因为统一对@RestController进行了拦截,因此对于健康检查等返回String的Controller会抛异常,因此对于健康检查等返回String的Controller使用@Controller与@ResponseBody代替@RestController即可

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值