SpringBoot教程(八) | SpringBoot统一结果封装

举报
一缕82年的清风 发表于 2022/01/24 09:48:23 2022/01/24
【摘要】 经过了前面几篇文章,SpringBoot中MVC相关的配置其实都已经差不多了,接下来就可以完全进入接口开发阶段了。前面我们写过几个接口,虽然都加了@RestController注解,相当于统一了我们的返回数据的基本形式为JSON,但是由于我们的项目可能是很多人一起开发,所以我们最好能够把我们的返回结果统一一下,让大家都返回一样的数据格式,这样即规范了代码,也方便了前端人员的调用,不然每个人都...

经过了前面几篇文章,SpringBoot中MVC相关的配置其实都已经差不多了,接下来就可以完全进入接口开发阶段了。前面我们写过几个接口,虽然都加了@RestController注解,相当于统一了我们的返回数据的基本形式为JSON,但是由于我们的项目可能是很多人一起开发,所以我们最好能够把我们的返回结果统一一下,让大家都返回一样的数据格式,这样即规范了代码,也方便了前端人员的调用,不然每个人都按照每个人的风格去写,代码会变得非常混乱。

那我我们怎么还封装这个结果呢,那就要关注我们返回给前端的数据都要包含哪些信息。

一般来讲,首先要有一个code, 用来代表我们这次接口的一个状态,比如 0代表成功,1代表失败,2代表必传参数不对, 4代表系统异常等等。这只是个简单的举例。可能很多人会有疑问,Http协议本身不是已经有了相应的返回码的定义了么,比如200代表成功, 500代表服务器错误,404代表找不到页面,为啥咱们还要在定义呢,这就是划分粒度的问题了,就那200来说,它代表是这次请求成功了,但是它描述不了这次请求中的业务结果,比如用户名已存在,其实业务上就不是一种成功,但http的结果肯定是200,所以我们需要一种描述我们业务状态的编码。

除了编码之外,还有要一些提示信息,比如,操作成功,系统异常,用户名已存在等,所以我们再加一个messge字段。

还有什么呢,还有我们的核心数据,比如我根据id获取数据,那个这个数据的具体内容,我们肯定是必须要返回给前端呢,所以还要 有个data, 那这个data 用什么类型呢,这个类型肯定是五花八门,所以我们要用一个统一的父类,Object才可以接收所有类型,当然为了便于操作我们可以采用泛型的方式。

通过上面的分析,我们的这个类基本上就已经可以设计出来了。

public class Result<T> implements Serializable {

  private static final long serialVersionUID = -3960261604605958516L;
  
  private int code;
  private String msg;
  private T data;
  
  // get set方法,限于篇幅问题,这里不写了,大家操作的时候自己生成一下。或者使用lombok
  public static <T> Result<T> success() {
        return new Result<>();
    }

    /**
     * 成功,默认状态码,返回消息,自定义返回数据
     *
     * @param data 自定义返回数据
     * @param <T>  返回类泛型,不能为String
     * @return 通用返回Result
     */
    public static <T> Result<T> success(T data) {
        return new Result<>(data);
    }

    /**
     * 成功,默认状态码,自定义返回消息,无返回数据
     *
     * @param msg 自定义返回消息
     * @param <T> 返回类泛型
     * @return 通用返回Result
     */
    public static <T> Result<T> success(String msg) {
        return new Result<>(msg);
    }

    /**
     * 成功,默认状态码,自定义返回消息,返回数据
     *
     * @param msg  自定义返回消息
     * @param data 自定义返回数据
     * @param <T>  返回类泛型
     * @return 通用返回Result
     */
    public static <T> Result<T> success(String msg, T data) {
        return new Result<>(msg, data);
    }

    /**
     * 失败,默认状态码,返回消息,无返回数据
     *
     * @param <T> 返回类泛型
     * @return 通用返回Result
     */
    public static <T> Result<T> error() {
        return new Result<>(ResultCode.ERROR);
    }

    /**
     * 失败,默认状态码,自定义返回消息,无返回数据
     *
     * @param <T> 返回类泛型
     * @return 通用返回Result
     */
    public static <T> Result<T> error(String msg) {
        return new Result<>(ResultCode.ERROR.getCode(), msg);
    }

    /**
     * 失败,自定义状态码,返回消息,无返回数据
     *
     * @param code 自定义状态码
     * @param msg  自定义返回消息
     * @param <T>  返回类泛型
     * @return 通用返回Result
     */
    public static <T> Result<T> error(int code, String msg) {
        return new Result<>(code, msg);
    }

    /**
     * 失败,使用CodeMsg状态码,返回消息,无返回数据
     *
     * @param resultCode CodeMsg,参数如下:
     *                   <p> code 状态码
     *                   <p> msg  返回消息
     * @param <T>        返回类泛型
     * @return 通用返回Result
     */
    public static <T> Result<T> error(ResultCode resultCode) {
        return new Result<>(resultCode);
    }

    /**
     * 成功构造器,无返回数据
     */
    private Result() {
        this(ResultCode.SUCCESS);
    }

    /**
     * 成功构造器,自定义返回数据
     *
     * @param data 返回数据
     */
    private Result(T data) {
        this(ResultCode.SUCCESS, data);
    }

    /**
     * 成功构造器,自定义返回消息,无返回数据
     *
     * @param msg 返回消息
     */
    private Result(String msg) {
        this(ResultCode.SUCCESS.getCode(), msg);
    }

    /**
     * 成功构造器,自定义返回信息,返回数据
     *
     * @param msg  返回信息
     * @param data 返回数据
     */
    private Result(String msg, T data) {
        this(ResultCode.SUCCESS.getCode(), msg, data);
    }

    /**
     * 构造器,自定义状态码,返回消息
     *
     * @param code 状态码
     * @param msg  返回消息
     */
    private Result(int code, String msg) {
        this.code = code;
        this.msg = msg;
    }

    /**
     * 构造器,自定义状态码,返回消息,返回数据
     *
     * @param code 状态码
     * @param msg  返回消息
     * @param data 返回数据
     */
    private Result(int code, String msg, T data) {
        this(code, msg);
        this.data = data;
    }

    /**
     * 构造器,使用CodeMsg状态码与返回信息
     *
     * @param resultCode CodeMsg,参数如下:
     *                   <p> code 状态码
     *                   <p> msg  返回消息
     */
    private Result(ResultCode resultCode) {
        this(resultCode.getCode(), resultCode.getMsg());
    }

    /**
     * 构造器,使用CodeMsg状态码与返回信息,自定义返回数据
     *
     * @param resultCode CodeMsg,参数如下:
     *                   <p> code 状态码
     *                   <p> msg  返回消息
     * @param data       返回数据
     */
    private Result(ResultCode resultCode, T data) {
        this(resultCode);
        this.data = data;
    }


}
复制代码

在定义几个常见的错误:这里为了不写那么多的get,set,我们引入了lombok

@Data
@Builder
public class ResultCode implements Serializable {

    private static final long serialVersionUID = -6269841958947880397L;

    /**
     * 状态码
     */
    private int code;

    /**
     * 状态信息
     */
    private String msg;

    /**
     * 默认成功
     */
    public final static ResultCode SUCCESS = dispose(ResultCodeEnum.SUCCESS);
    /**
     * 默认失败
     */
    public final static ResultCode ERROR = dispose(ResultCodeEnum.ERROR);
    /**
     * 通用业务异常
     */
    public final static ResultCode BIZ_ERROR = dispose(ResultCodeEnum.BIZ_ERROR);
    /**
     * 文件超出最大限制
     */
    public final static ResultCode FILE_OUT_MAX = dispose(ResultCodeEnum.FILE_OUT_MAX);
    /**
     * 文件格式不正确
     */
    public final static ResultCode FILE_FORMAT_ERROR = dispose(ResultCodeEnum.FILE_FORMAT_ERROR);
    /**
     * 参数错误
     */
    public final static ResultCode PARAM_ERROR = dispose(ResultCodeEnum.PARAM_ERROR);
    /**
     * Json解析异常
     */
    public final static ResultCode JSON_FORMAT_ERROR = dispose(ResultCodeEnum.JSON_FORMAT_ERROR);
    /**
     * Sql解析异常
     */
    public final static ResultCode SQL_ERROR = dispose(ResultCodeEnum.SQL_ERROR);
    /**
     * 网络超时
     */
    public final static ResultCode NETWORK_TIMEOUT = dispose(ResultCodeEnum.NETWORK_TIMEOUT);
    /**
     * 未知的接口
     */
    public final static ResultCode UNKNOWN_INTERFACE = dispose(ResultCodeEnum.UNKNOWN_INTERFACE);
    /**
     * 请求方式不支持
     */
    public final static ResultCode REQ_MODE_NOT_SUPPORTED = dispose(ResultCodeEnum.REQ_MODE_NOT_SUPPORTED);
    /**
     * 系统异常
     */
    public final static ResultCode SYS_ERROR = dispose(ResultCodeEnum.SYS_ERROR);

    private static ResultCode dispose(ResultCodeEnum codeEnum) {
        return ResultCode.builder().code(codeEnum.getCode()).msg(codeEnum.getMsg()).build();
    }

    public ResultCode(int code, String msg) {
        this.code = code;
        this.msg = msg;
    }
}
复制代码
public enum ResultCodeEnum {

    SUCCESS(0, "操作成功"),
    ERROR(1, "操作失败"),
    BIZ_ERROR(1000, "通用业务异常"),
    FILE_OUT_MAX(9000, "文件超出最大限制"),
    FILE_FORMAT_ERROR(9001, "文件格式不正确"),
    PARAM_ERROR(9050, "参数错误"),
    JSON_FORMAT_ERROR(9051, "Json解析异常"),
    SQL_ERROR(9052, "Sql解析异常"),
    NETWORK_TIMEOUT(9510, "网络超时"),
    UNKNOWN_INTERFACE(9520, "未知的接口"),
    REQ_MODE_NOT_SUPPORTED(9530, "请求方式不支持"),
    SYS_ERROR(9999, "系统异常");

    /**
     * 状态码
     */
    private final int code;

    /**
     * 状态信息
     */
    private final String msg;

    public int getCode() {
        return code;
    }

    public String getMsg() {
        return msg;
    }

    ResultCodeEnum(int code, String msg) {
        this.code = code;
        this.msg = msg;
    }
}
复制代码

这个写完了以后,就可以统一我们的返回结果,以后所有的Controller就都要返回Result类型。比如:

@GetMapping("/withinRangeResource")
    public Result<List<EmergencyExpertResVO>> withinRangeResource(@Valid ResourceRangeReqVO param) {
        List<EmergencyExpertResVO> expertResVOS = emergencyExpertBiz.getWithinRangeResource(param);
        return Result.success(expertResVOS);
    }
复制代码

另: 配套项目代码已托管中gitCode: gitcode.net/lsqingfeng/…

所有文章也会在微信公众号首发更新,欢迎关注: 一缕82年的清风


【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。