项目构建基础:统一结果返回

在这里插入图片描述

前言

  在移动互联网,分布式、微服务盛行的今天,现在项目绝大部分都采用的微服务框架,前后端分离方式,前后端的工作职责越来越明确。前端和后端进行交互,前端按照约定请求URL路径,并传入相关参数,后端服务器接收请求,进行业务处理,返回数据给前端。
在这里插入图片描述

API 接口设计

  项目开发中,一般情况下都会对数据返回的格式做一个统一的要求,一般会包括状态码、信息及数据三部分。定义通用返回对象可以在原返回的数据基础上封装一层,将状态码等信息包含进来。后端返回给前端我们一般用JSON体方式,定义如下:

public class AjaxResult {
    // 是否响应成功
    private Boolean success;
    // 响应状态码
    private Integer code;
    // 提示信息
    private String msg;
    // 响应数据
    private Object data;
    // 其他标识符(服务器当前时间、访问url、错误类型、错误的堆栈轨迹)
    private Map<String,Object> extraInfo;
}

2.1 自定义返回状态码

  我们可以参考HTTP请求返回的状态码这样的设计,这样的好处就把错误类型归类到某个区间内,前端开发人员在得到返回值后,根据状态码就可以知道,大概什么错误,再根据message相关的信息描述,可以快速定位。
在这里插入图片描述

@Getter
@AllArgsConstructor
public enum ResultCode {

	/** 成功状态码 */
	SUCCESS(200, "操作成功"),
	/** 失败状态码 */
	FAILURE(500, "操作失败"),

	/**
	 * 参数错误:10001-19999
	 */
	PARAM_IS_INVALID(10001, "参数无效"),

	PARAM_IS_BLANK(10002, "参数为空"),

	PARAM_TYPE_BIND_ERROR(10003, "参数类型错误"),

	PARAM_NOT_COMPLETE(10004, "参数缺失"),

	/**
	 * 用户错误:20001-29999
	 */
	USER_NOT_LOGGED_IN(20001, "用户未登录,访问的路径需要验证,请登录"),

	USER_LOGIN_ERROR(20002, "账号不存在或密码错误"),

	USER_ACCOUNT_FORBIDDEN(20003, "账号已被禁用"),

	USER_NOT_EXIST(20004, "用户不存在"), USER_HAS_EXISTED(20005, "用户已存在"),

	/**
	 * 业务错误:30001-39999
	 */
	SPECIFIED_QUESTIONED_USER_NOT_EXIST(30001, "某业务出现问题"),

	/**
	 * 系统错误:40001-49999
	 */
	SYSTEM_INNER_ERROR(40001, "系统繁忙,请稍后重试"),
	
	UNKNOWN_ERROR(40002,"未知错误"),

	/**
	 * 数据错误:50001-599999
	 */
	RESULE_DATA_NONE(50001, "数据未找到"),

	DATA_IS_WRONG(50002, "数据有误"),

	DATA_ALREADY_EXISTED(50003, "数据已存在"),

	/**
	 * 接口错误:60001-69999
	 */
	INTERFACE_INNER_INVOKE_ERROR(60001, "内部系统接口调用异常"),

	INTERFACE_OUTTER_INVOKE_ERROR(60002, "外部系统接口调用异常"),

	INTERFACE_FORBID_VISIT(60003, "该接口禁止访问"),

	INTERFACE_ADDRESS_INVALID(60004, "接口地址无效"),

	INTERFACE_REQUEST_TIMEOUT(60005, "接口请求超时"),

	INTERFACE_EXCEED_LOAD(60006, "接口负载过高"),

	/**
	 * 权限错误:70001-79999
	 */
	PERMISSION_NO_ACCESS(70001, "无访问权限");

	private Integer code;
	private String message;

	public Integer getCode(String name) {
		for (ResultCode item : ResultCode.values()) {
			if (item.name().equals(name)) {
				return item.code;
			}
		}
		return null;
	}

	public String getMessage(String name) {
		for (ResultCode item : ResultCode.values()) {
			if (item.name().equals(name)) {
				return item.message;
			}
		}
		return name;
	}
}
public interface ResultCode {
    /** 请求t成功 */
    public static Integer SUCCESS = 200;
    /** 请求table成功 */
    public static Integer TABLE_SUCCESS = 0;
    /** 请求失败 */
    public static Integer ERROR = 201;
    /** 请求已经被接受 */
    public static final Integer ACCEPTED = 202;
    /** 操作已经执行成功,但是没有返回数据 */
    public static final Integer NO_CONTENT = 204;
    /** 资源已被移除 */
    public static final Integer MOVED_PERM = 301;
    /** 重定向 */
    public static final Integer SEE_OTHER = 303;
    /** 资源没有被修改 */
    public static final Integer NOT_MODIFIED = 304;
    /** 参数列表错误(缺少,格式不匹配)*/
    public static final Integer BAD_REQUEST = 400;
    /** 未授权 */
    public static final Integer UNAUTHORIZED = 401;
    /** 访问受限,授权过期 */
    public static final Integer FORBIDDEN = 403;
    /** 资源,服务未找到 */
    public static final Integer NOT_FOUND = 404;
    /** 不允许的http方法 */
    public static final Integer BAD_METHOD = 405;
    /** 资源冲突,或者资源被锁  */
    public static final Integer CONFLICT = 409;
    /** 不支持的数据,媒体类型 */
    public static final Integer UNSUPPORTED_TYPE = 415;
    /** 接口未实现 */
    public static final Integer NOT_IMPLEMENTED = 501;
}

2.2 返回的结果封装类

注意:

  1. 外接只可以调用统一返回类的方法,不可以直接创建,因此构造器私有。
  2. 内置静态方法,返回对象。
  3. 为便于自定义统一结果的信息,建议使用链式编程,将返回对象设类本身,即return this。
  4. 响应数据由于为json格式,可定义为JsonObject或Map形式。
import java.io.Serializable;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;
import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public final class RestResult implements Serializable {

	private static final long serialVersionUID = 2201399824548851402L;
	/** 服务器当前时间(添加该字段的原因是便于查找定位请求时间,因为实际开发过程中服务器时间可能跟本地时间不一致,加上这个时间戳便于日后定位) */
	private String currentTime = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(LocalDateTime.now());
	/** 返回结果编码 */
	private Integer resultCode = ResultCode.SUCCESS.getCode();
	/** 返回的数据息 */
	private Object data;
	/** 请求返回的提示信息,给前端进行页面展示的信息 */
	private String message = "操作成功";
	/** 额外参数,不使用Map<String, Object>防止JSON解析时过于复杂 */
	private Map<String, Object> extraInfo = new HashMap<String, Object>();

	/**
	 * 构造器私有
	 */
	private RestResult() {
		super();
	}

	/**
	 * 构造器私有
	 */
	private RestResult(ResultCode resultCode) {
		super();
		this.resultCode = resultCode.getCode();
		this.message = resultCode.getMessage();
	}

	/**
	 * 构造器私有
	 */
	public RestResult(String message, Object data, Map<String, Object> extraInfo) {
		super();
		this.message = message;
		this.data = data;
		this.extraInfo = extraInfo;
	}

	/**
	 * @方法描述: 添加返回数据
	 * 
	 * @param key
	 * @param value
	 */
	public void setData(String key, Object value) {
		extraInfo.put(key, value);
	}

	/**
	 * @方法描述: 可以连接追加调用此方法,添加返回数据
	 * 
	 * @param key
	 * @param value
	 * @return
	 */
	public RestResult add(String key, Object value) {
		extraInfo.put(key, value);
		return this;
	}

	/**
	 * @方法描述: 返回执行成功,不返回数据直接返回成功信息
	 * @return
	 */
	public static RestResult success() {
		return new RestResult();
	}

	/**
	 * @方法描述: 返回执行成功,返回数据
	 * @param message 自定义成功提示信息
	 * @param data    自定义返回数据
	 * @return
	 */
	public static RestResult success(String message, Object data) {
		return new RestResult(message, data, null);
	}

	/**
	 * @方法描述: 返回执行成功,返回数据
	 * @param message 自定义成功提示信息
	 * @return
	 */
	public static RestResult success(Object data) {
		return new RestResult(null, data, null);
	}

	/**
	 * @方法描述: 成功返回执行成功,返回数据并返回额外参数
	 * @param data      自定义返回数据
	 * @param extraInfo 额外参数
	 * @return
	 */
	public static RestResult success(Object data, Map<String, Object> extraInfo) {
		return new RestResult(null, data, extraInfo);
	}

	/**
	 * @方法描述:返回执行成功,返回数据并返回额外参数
	 * @param message   自定义成功提示信息
	 * @param data      自定义返回数据
	 * @param extraInfo 额外参数
	 * @return
	 */
	public static RestResult success(String message, Object data, Map<String, Object> extraInfo) {
		return new RestResult(message, data, extraInfo);
	}

	/**
	 * @方法描述:返回执行失败
	 * @return
	 */
	public static RestResult fail() {
		return new RestResult(ResultCode.FAILURE);
	}

	/**
	 * @方法描述:返回失败的消息
	 * @param message 自定义失败原因
	 * @return
	 */
	public static RestResult fail(String message) {
		RestResult restResult = new RestResult(ResultCode.FAILURE);
		restResult.setMessage(message);
		return restResult;
	}

	/**
	 * @方法描述:返回错误消息
	 * @param resultCode
	 * @return
	 */
	public static RestResult fail(ResultCode resultCode) {
		return new RestResult(resultCode);
	}

	/**
	 * @方法描述:返回失败的状态码以及数据
	 * @param resultCode
	 * @param message    自定义失败原因
	 * @return
	 */
	public static RestResult fail(int resultCode, String message) {
		RestResult restResult = new RestResult();
		restResult.setResultCode(resultCode);
		restResult.setMessage(message);
		return restResult;
	}

	/**
	 * @方法描述:返回失败的状态码以及数据
	 * @param resultCode
	 * @param message    自定义失败原因
	 * @param data       自定义返回数据
	 * @return
	 */
	public static RestResult fail(int resultCode, String message, Object data) {
		RestResult restResult = new RestResult();
		restResult.setResultCode(resultCode);
		restResult.setMessage(message);
		restResult.setData(data);
		return restResult;
	}

	/**
	 * @方法描述:返回失败的状态码以及数据
	 * @param resultCode
	 * @param data       自定义返回数据
	 * @return
	 */
	public static RestResult fail(ResultCode resultCode, Object data) {
		RestResult restResult = new RestResult(resultCode);
		restResult.setData(data);
		return restResult;
	}

	/**
	 * @方法描述:失败,自定义失败返回状态并返回数据、额外参数
	 * @param resultCode
	 * @param data       自定义返回数据
	 * @param extraInfo
	 * @return
	 */
	public static RestResult fail(ResultCode resultCode, Object data, Map<String, Object> extraInfo) {
		RestResult restResult = new RestResult(resultCode);
		restResult.setData(data);
		restResult.setExtraInfo(extraInfo);
		return restResult;
	}
}

2.3 控制层例子

@GetMapping("getUserInfoById")
public Result getUserInfoById(@PathVariable("id") Integer id){
    if(id.equals(0) ){
        return Result.fail(ResultCode.FAILURE);
    } else {
    	return Result.success(userService.getUser(id));
    }
}

2.4 返回结果

// 成功
{
    "code":200,
    "message":"成功",
    "data":{
        "id":1,
        "name":"dllwh"
    }
}

// 失败
{
    "code":0,
    "message":"失败",
    "data":null
}

小结

把今天最好的表现当作明天最新的起点…….~

  投身于天地这熔炉,一个人可以被毁灭,但绝不会被打败!一旦决定了心中所想,便绝无动摇。迈向光明之路,注定荆棘丛生,自己选择的路,即使再荒谬、再艰难,跪着也要走下去!放弃,曾令人想要逃离,但绝境重生方为宿命。若结果并非所愿,那就在尘埃落定前奋力一搏!

在这里插入图片描述

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

独泪了无痕

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

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

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

打赏作者

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

抵扣说明:

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

余额充值