SpringBoot通用处理结果类/前端使用结果类 Result

文章目录

大家实现的java web项目返回给前端的结果类,结构基本相同,但又各有不同。通过学习,发现以下几点关注点:

  • 错误代码枚举类真的有必要那么繁杂吗?
  • 错误代码实用还是文字信息实用?
  • 返回数据统一定义为Object,直观吗?便于类型检查吗?
  • 返回数据为Map类型时,怎样使用才方便?
  • 高频使用的分页查询列表的满足记录总数,实际记录数为什么不能固定在返回数据中?

对应解决:

  • 错误代码没有文字信息直观(对于程序员同样),基本代码仅四类足够日常使用(正常、用户输入错误,系统错误、其他错误)。善于利用标准定义的web状态码枚举类(org.springframework.http.HttpStatus
  • 使用泛型绑定返回数据data类型,利于编码规范化。
  • 泛型绑定为Map时,使用链式编程方式,灵活添加不同Map元素
  • 为返回数据data,定义count(计数器),total(满足查询条件的记录总数)
  • 自动属性success,使前端使用时不必要判断状态码分类
package com.muyi.common.core.domain;

import com.muyi.common.enums.StatusCode;
import io.swagger.annotations.ApiModel;
import org.springframework.http.HttpStatus;

import java.io.Serializable;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

/**
 * 通用处理结果
 * <pre>
 *     1 默认成功状态,msg=""
 *     2 data为空时,可使用实例链式编程put(String,Object)添加Map集合
 * </pre>
 *
 * @author MuYi
 * @version 1.0
 * @date 2022/4/2 13:43
 **/
@ApiModel(value = "类Result", description = "通用处理结果")
public class Result<T> implements Serializable {
    private static final int OK_CODE_VALUE        = HttpStatus.OK.value();
    private static final int FIRST_ERR_CODE_VALUE = HttpStatus.BAD_REQUEST.value();

    /**
     * 是否成功、只读
     */
    private boolean success;
    /**
     * 状态码
     * <pre>
     *     以HttpStatus为主架构,原有定义不得乱用。
     *     正常返回代码为200,即HttpStatus.OK.value()
     *
     *     用户自定义错误代码需大于1000
     * </pre>
     *
     * @see org.springframework.http.HttpStatus
     */
    private int     code  = HttpStatus.OK.value();
    /**
     * 当data为null时为0;为Map、list、Array时,获取其长度;其他类型为1
     */
    private int     count = 0;
    /**
     * 信息
     */
    private String  msg;
    /**
     * 结果数据
     */
    private T       data;
    /**
     * 满足查询条件的记录总数
     */
    private long    total = 0;

    public long getTotal() {
        return total;
    }

    public void setTotal(long total) {
        this.total = total;
    }

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
        this.success = code >= OK_CODE_VALUE && code < FIRST_ERR_CODE_VALUE;

    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
        count = obtainDataCount(data);
    }

    /**
     * 根据code判断是否成功
     * <pre>
     *     code大于等于200 小于400
     * </pre>
     *
     * @return 是否
     * @see #error(String)
     */
    public boolean isSuccess() {
        return this.success;
    }

    /**
     * 根据code判断是否成功
     * <pre>
     *     code大于等于200 小于400
     * </pre>
     *
     * @return 是否
     * @see #error(String)
     */
    public boolean getSuccess() {
        return this.success;
    }

    public int getCount() {
        return count;
    }

    /**
     * 构造
     *
     * @param code 状态码
     * @param data 结果数据
     * @param msg  信息。为空且处理成功时,前台不显示
     */
    private Result(Integer code, T data, String msg) {
        init(code, data, msg);
    }

    /**
     * 构造
     *
     * @param code 状态码
     * @param data 结果数据
     * @param msg  信息。为空且处理成功时,前台不显示
     */
    private Result(StatusCode code, T data, String msg) {
        init(code.getValue(), data, msg);
    }

    /**
     * 构造
     *
     * @param code 状态码
     * @param data 结果数据
     * @param msg  信息。为空且处理成功时,前台不显示
     */
    private Result(HttpStatus code, T data, String msg) {
        init(code.value(), data, msg);
    }

    private void init(Integer code, T data, String msg) {
        setCode(code);
        setMsg(msg);
        setData(data);
    }

    /**
     * 初始化成功/失败新实例
     *
     * @param code 代码200、300系列一般为成功;400、500系列为失败
     * @param data 处理结果
     * @param msg  信息。为空且且处理成功时,前台可不显示
     * @return 新实例
     */
    public static <T> Result<T> build(Integer code, T data, String msg) {
        if (!isSuccessCode(code)) code = OK_CODE_VALUE;
        return new Result<T>(code, data, msg);
    }

    /**
     * 初始化成功/失败新实例
     *
     * @param code 代码
     * @param data 处理结果
     * @param msg  信息。为空且处理成功时,前台不显示
     * @return 新实例
     */
    public static <T> Result<T> build(StatusCode code, T data, String msg) {
        return build(code.getValue(), data, msg);
    }

    /**
     * 初始化成功/失败新实例
     *
     * @param code 代码200、300系列一般为成功;400、500系列为失败
     * @param data 处理结果
     * @param msg  信息。为空且且处理成功时,前台可不显示
     * @return 新实例
     */
    public static <T> Result<T> build(HttpStatus code, T data, String msg) {
        return build(code.value(), data, msg);
    }

    /**
     * 初始化成功新实例
     * <pre>
     * Result.<Map<String, Object>>success(),可随后使用链式编程.put添加Map数据
     * </pre>
     *
     * @param msg 信息。为空且处理成功时,前台不显示
     * @return 新实例
     */
    public static <T> Result<T> success(String msg) {
        return build(OK_CODE_VALUE, null, msg);
    }

    /**
     * 初始化成功新实例
     * <pre>
     * Result.<Map<String, Object>>success(),可随后使用链式编程.put添加Map数据
     * </pre>
     *
     * @return 新实例
     */
    public static <T> Result<T> success() {
        return build(OK_CODE_VALUE, null, "");
    }


    /**
     * 初始化成功新实例
     *
     * @param data 处理结果
     * @param msg  信息。为空且处理成功时,前台不显示
     * @return 新实例
     */
    public static <T> Result<T> success(T data, String msg) {
        return build(StatusCode.OK.getValue(), data, msg);
    }

    /**
     * 初始化成功新实例
     *
     * @param data 处理结果
     * @return 新实例
     */
    public static <T> Result<T> success(T data) {
        return build(StatusCode.OK.getValue(), data, "");
    }

    /**
     * 初始化失败新实例
     *
     * @param code 代码非200、300系列时自动设置为400 BAD_REQUEST
     * @param data 处理结果
     * @param msg  信息。为空且处理成功时,前台不显示
     * @return 新实例
     */
    public static <T> Result<T> error(Integer code, T data, String msg) {
        if (!isSuccessCode(code)) code = FIRST_ERR_CODE_VALUE;
        return new Result<T>(code, data, msg);
    }


    /**
     * 初始化失败新实例
     *
     * @param code 代码为非200、300系列
     * @param msg  信息。为空且处理成功时,前台不显示
     * @return 新实例
     */
    public static <T> Result<T> error(HttpStatus code, String msg) {
        return build(code, null, msg);
    }

    /**
     * 初始化失败新实例
     *
     * @param code 代码为非OK
     * @param msg  信息。为空且处理成功时,前台不显示
     * @return 新实例
     */
    public static <T> Result<T> error(StatusCode code, String msg) {
        return build(code, null, msg);
    }

    /**
     * 初始化失败新实例
     * <pre>code=StatusCode.SYSTEM_ERR</pre>
     *
     * @param msg 信息。为空且处理成功时,前台不显示
     * @return 新实例
     */
    public static <T> Result<T> error(String msg) {
        return build(StatusCode.SYSTEM_ERR, null, msg);
    }

    /**
     * 初始化失败新实例
     * <pre>msg由代码定义获得</pre>
     *
     * @param code 代码应为非OK
     * @return 新实例
     */
    public static <T> Result<T> error(StatusCode code) {
        return build(code, null, code.getDesc());
    }

    /**
     * 初始化失败新实例
     * <pre>msg由代码定义获得</pre>
     *
     * @param code 代码应为非200、300系列
     * @return 新实例
     */
    public static <T> Result<T> error(HttpStatus code) {
        return build(code, null, code.getReasonPhrase());
    }

    /**
     * 判断状态是否为成功代码
     * <pre>
     *     code大于等于200 小于400
     * </pre>
     *
     * @param code 状态码
     * @return 是否
     */
    public static boolean isSuccessCode(Integer code) {
        if (code == null) return false;
        return code >= OK_CODE_VALUE && code < FIRST_ERR_CODE_VALUE;
    }

    /**
     * 如果data为Collection、Map计算data长度。否则返回0或1
     * <pre>
     *     data为null返回0,
     * </pre>
     *
     * @param data 输入
     * @return 长度
     */
    public static int obtainDataCount(Object data) {
        if (data == null) return 0;
        if (data instanceof Map) return ((Map<?,?>) data).size();
        else if (data instanceof Collection) return ((Collection<?>) data).size();
        else return 1;
    }

    /**
     * 向data添加键值对
     * <pre>
     *     如果本实例的data不为空且不是Map<String,Object>直接返回本实例,添加无效
     * </pre>
     *
     * @param key   键名 为空直接返回本实例,否则,存在则覆盖,不存在新建
     * @param value 值
     * @return 本实例
     */
    public Result<T> put(String key, Object value) {
        if (this.data == null) this.data = (T) new HashMap<String, Object>();
        ((Map<String, Object>) this.data).put(key, value);
        count = obtainDataCount(data);
        return this;
    }

    /**
     * 向data添加键值对
     * <pre>
     *     如果本实例的data不为空且不是Map<String,Object>直接返回本实例,添加无效
     * </pre>
     *
     * @param map 值
     * @return 本实例
     */
    public Result<T> put(Map<String, Object> map) {
        if (this.data == null) this.data = (T) new HashMap<String, Object>();
        ((Map<String, Object>) this.data).putAll(map);
        count = obtainDataCount(data);
        return this;
    }

}

自定义代码枚举

package com.muyi.common.enums;

import io.swagger.annotations.ApiModel;

import java.util.ArrayList;
import java.util.List;

/**
 * 枚举:处理返回状态码
 * <pre>
 *     以HttpStatus为主架构,原有定义不得乱用。
 *     正常返回代码为200,即HttpStatus.OK.value()
 *
 *     用户自定义错误代码需大于1000
 * </pre>
 *
 * @author MuYi
 * @version 1.0
 * @date 2022/4/2 13:58
 * @see org.springframework.http.HttpStatus
 **/
@ApiModel(value = "接口StatusCode", description = "枚举:")
public enum StatusCode  {
    /**
     * 处理成功
     */
    OK(200, "处理成功"),
    /**
     * 用户输入或请求错误
     */
    REQUEST_ERR(400, "用户输入或请求错误"),
    /**
     * 系统异常
     */
    SYSTEM_ERR(500, "系统异常"),
    /**
     * 未知异常
     */
    OTHER_ERR(1000, "未知异常");
    private final Integer value;
    private final String  desc;

    StatusCode(Integer value, String desc) {
        this.desc = desc;
        this.value = value;
    }

    /**
     * 获得所有中文描述
     *
     * @return 中文描述字符串数组
     */

    public static String[] getAllDesc() {
        List<String> result = new ArrayList<>();
        for (ExchangeScopeType item : ExchangeScopeType.values()) {
            result.add(item.getDesc());
        }
        return result.toArray(new String[0]);
    }

 
    public Integer getValue() {
        return this.value;
    }

 
    public String getDesc() {
        return this.desc;
    }

    /**
     * 将数值或枚举名转换为枚举值
     * <pre>
     *     输入无效返回OTHER_ERR
     * </pre>
     *
     * @param valueOrName 枚举对应的数值value(Integer类型)或枚举项名称name(String类型)
     * @return 枚举值或或OTHER_ERR。
     */
    public static StatusCode parse(Object valueOrName) {
        if (valueOrName == null) return OTHER_ERR;
        if (valueOrName instanceof Integer) {
            for (StatusCode item : StatusCode.values()) {
                if (item.getValue() == valueOrName) return item;
            }
        } else if (valueOrName instanceof String) {
            for (StatusCode item : StatusCode.values()) {
                if (item.name().equals(valueOrName)) return item;
            }
        }
        return OTHER_ERR;
    }

    public boolean isError() {
        return this != OK;
    }
}

调用片段

   @GetMapping("/list")
    @ModelViewExceptionProcess
    public Result<List<SysConfig>> list(SysConfig config) {
        PageUtils.startPage();
        Result<List<SysConfig>> result = configService.selectByCondition(config);
        PageUtils.setTotal(result);
        return result;
    }
    @Override
    public Result<Boolean> configKeyIsUnique(String configKey, Long id) {
        if (StringUtils.isBlank(configKey))
           return Result.build(StatusCode.REQUEST_ERR,false,"输入的参数键名称为空字符串");
        Long existingId = baseMapper.selectIdByKey(configKey);
        return Result.success(existingId == null || existingId.equals(id));
    }
SysUser user=new SysUser();
  Result<Map<String, Object>> result = Result.<Map<String, Object>>success()
                .put("key1", 1)
                .put("key2", 2)
                .put("key3","111")
                .put("user",user);
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

muyi517

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值