乐趣区

关于springboot:SpringBoot定义优雅全局统一Restful-API-响应框架三

咱们目前曾经设计出了,蕴含全局响应,异样谬误响应进行了对立返回。然而谬误内容咱们设计的比拟含糊对立,还能够进行细化这样更有利于定位谬误

当咱们须要调用 Http 接口时,无论是在 Web 端还是挪动端,都有可能遇到各种谬误,例如参数缺失、类型谬误、零碎谬误等。为了标准错误信息的返回,咱们须要定义一个对立的接口谬误返回值。通过对接口谬误返回值的对立设计,咱们能够标准调用方对各种不同谬误的解决形式,并提供更加具体、精确的谬误提醒,同时也帮忙后端实现接口返回值的规范化设计。因而,接口谬误返回值的设计不仅仅是对错误信息的规范化解决,还波及到业务上的谬误设计。这样的设计能够无效地进步接口的应用效率和可维护性。

错误码定义

依据 http stats 谬误通常能够分为以下几大类

  1. 200:申请胜利
  2. 400:申请参数谬误
  3. 401:未受权拜访
  4. 403:示意禁止拜访资源。
  5. 404:示意未找到资源。
  6. 500:示意服务器外部谬误。

错误码的设计,能够借用 http 错误码 + 三位 api 自定义错误码 一共是 6 位数字,具体每个模块代表什么能够依据你本人的业务逻辑,定义不同数字,位数对应不同模块

对应谬误格局如下

谬误接口

package cn.soboys.springbootrestfulapi.common.error;

/**
 * @author 公众号 程序员三时
 * @version 1.0
 * @date 2023/5/2 21:33
 * @webSite https://github.com/coder-amiao
 * 错误码接口,凡各模块错误码枚举类,皆须为此接口的子类型
 */
public interface ErrorCode {Integer getCode();

    String getMessage();

    boolean getSuccess();}

自定义谬误实现枚举

package cn.soboys.springbootrestfulapi.common.error;

/**
 * @author 公众号 程序员三时
 * @version 1.0
 * @date 2023/5/2 21:36
 * @webSite https://github.com/coder-amiao
 */
public enum CommonErrorCode implements ErrorCode {NOT_FOUND(false, 404, "接口不存在"),
    FORBIDDEN(false, 403, "资源回绝拜访"),
    UNAUTHORIZED(false, 401, "未认证(签名谬误)"),
    INTERNAL_SERVER_ERROR(false, 500, "服务网络不可用"),
    PARAM_ERROR(false, 110001, "参数谬误");



    CommonErrorCode(Boolean success, Integer code, String message) {
        this.success = success;
        this.code = code;
        this.message = message;

    }

    /**
     * 响应是否胜利
     */
    private Boolean success;
    /**
     * 响应状态码
     */
    private Integer code;
    /**
     * 响应信息
     */
    private String message;


    @Override
    public Integer getCode() {return code;}

    @Override
    public String getMessage() {return message;}

    @Override
    public boolean getSuccess() {return success;}


}

全局异样错误处理

package cn.soboys.springbootrestfulapi.common.exception;


import cn.hutool.core.collection.CollectionUtil;
import cn.soboys.springbootrestfulapi.common.error.CommonErrorCode;
import cn.soboys.springbootrestfulapi.common.resp.R;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.context.request.WebRequest;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.List;
import java.util.stream.Collectors;


/**
 * @author 公众号 程序员三时
 * @version 1.0
 * @date 2023/4/29 00:21
 * @webSite https://github.com/coder-amiao
 * 对立异样处理器
 */
@RestControllerAdvice
public class GlobalExceptionHandler {

    /**
     * 通用异样解决办法
     **/
    @ExceptionHandler(Exception.class)
    @ResponseBody
    public R error(Exception e, WebRequest request) {e.printStackTrace();
        return R.setResult(CommonErrorCode.INTERNAL_SERVER_ERROR)
                .request(request.getDescription(true))
                .errorMsg(e.getMessage());
    }



    /**
     * 解决 form data 形式调用接口对象参数校验失败抛出的异样
     */
    @ExceptionHandler(BindException.class)
    @ResponseBody
    public R BindExceptionHandler(BindException e) {String message = e.getBindingResult().getAllErrors().stream().map(DefaultMessageSourceResolvable::getDefaultMessage).collect(Collectors.joining());
        return R.failure().code(CommonErrorCode.PARAM_ERROR.getCode()).message(message);
    }

    /**
     * 解决 Get 申请中 验证门路中 单个参数申请失败抛出异样
     * @param e
     * @return
     */
    @ExceptionHandler(ConstraintViolationException.class)
    public R ConstraintViolationExceptionHandler(ConstraintViolationException e) {String message = e.getConstraintViolations().stream().map(ConstraintViolation::getMessage).collect(Collectors.joining());
        return R.failure().code(CommonErrorCode.PARAM_ERROR.getCode()).message(message);
    }


    /**
     * 解决 json 申请体调用接口对象参数校验失败抛出的异样
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public R jsonParamsException(MethodArgumentNotValidException e) {BindingResult bindingResult = e.getBindingResult();
        String msg=";";

        for (FieldError fieldError : bindingResult.getFieldErrors()) {msg = String.format("%s%s;", fieldError.getField(), fieldError.getDefaultMessage())+msg;
        }
        return R.failure().code(CommonErrorCode.PARAM_ERROR.getCode()).message(msg);
    }

    /**
     * 自定义异样解决办法
     *
     * @param e
     * @return
     */
    @ExceptionHandler(BusinessException.class)
    @ResponseBody
    public R error(BusinessException e) {e.printStackTrace();
        return R.failure().message(e.getMessage()).code(e.getCode());
    }

}

筹备从零做一套本人的开发脚手架模板, 关注公众 程序员三时

具体我的项目代码曾经 同步到 github 上,后续会欠缺更新一系列整合脚手架工具,可能开箱即用

退出移动版