设计通用返回类BaseResponse、自定义状态码ErrorCode、返回工具类ResultUtils
通用返回类是对业务异常信息的补充
- 账号、密码信息输入有误,之前用的-1来代表异常,现在就可以以ResultUtil.error()的形式来返回
注意这里是业务异常,通常我们比较熟悉的状态码有这个4xx(404,405)…这一类的它们通常所包含的面太广了,如果只是像信息输入错误的情况,我们完全可以是自定义状态码和信息来说明的,这样也便于维护。
这个error()的形式是什么呢?
在用接口文档发送数据并得到返回值,这个返回值的形式也就是我们设计的BaseResponse。
// 成功
{
"code": 0 // 业务状态码
"data": {
"name": "smile"
},
"message": "ok"
}
// 错误
{
"code": 50001 // 业务状态码
"data": null
"message": "用户操作异常、xxx"
}
注意一点就是如果我们封装返回值类型的这个BaseResponse(通常还会经过ResultUtil来封装),写错了可能会导致SpringMVC无法解析出这个格式数据,从而引发406
BaseResponse包含哪些信息呢?
可以参考市面上做的这个返回值类型,它们包含下面这三个
属性名 | 描述 | 数据类型 |
---|---|---|
code | 状态码 | int |
data | 数据 | 泛型 T |
message | 消息 | String |
description (可选) | 描述 | String |
BaseResponse-common
通用返回类
/**
* 通用返回类
*/
@Data
public class BaseResponse<T> implements Serializable {
private int code;
private T data;
private String message;
private String description;
public BaseResponse(int code, T data, String message, String description) {
this.code = code;
this.data = data;
this.message = message;
this.description = description;
}
public BaseResponse(int code, T data, String message) {
this(code, data, message, "");
}
public BaseResponse(int code, T data) {
this(code, data, "", "");
}
public BaseResponse(ErrorCode errorCode) {
this(errorCode.getCode(), null, errorCode.getMessage(), errorCode.getDescription());
}
}
通用返回类就是覆盖这个所有的返回类型,所以用的泛型T,它是在原有基础上进行增强,新添了状态码和message
this() 是在构造器内部调用另外一个构造器,简化了写法。这里设置多个构造器类型也是为了丰富这个形参的传入
其实通俗来说,写这样一个BaseResponse类就可以进行封装返回型类,只不过比较麻烦的一点是,我们需要先将返回的值用一个对象接受,再将这个对象放置到Base Response的构造函数中
return UserService.userLogin(userAccount,userPassword);
//使用通用返回类
User user = UserService.userLogin(userAccount,userPassword);
return BaseResponse(0,user,"ok")
这样写其实挺麻烦的,所以通常会设计一个返回工具类(ResultUtils)来进行封装。
这样再返回时就可以再简化为
User user = UserService.userLogin(userAccount,userPassword);
return ResultUtils.success(user);
ResultUtils-utils
首先我们需要明白需要封装哪几种情况?
主要就分为两类
- 成功-success
- 失败-error
方法签名 | 描述 | 返回类型 |
---|---|---|
success(T data) | data - 成功时需要返回的数据 | BaseResponse<T> |
error(ErrorCode errorCode) | errorCode - 失败的错误代码 | BaseResponse |
error(int code, String message) | code - 失败的状态码message - 失败的消息 | BaseResponse |
error(ErrorCode errorCode, String message) | errorCode - 失败的错误代码message - 失败的消息 | BaseResponse |
成功比较好理解,成功是能直接拿到方法处理逻辑的数据,code和message也都是固定
- code-0
- message-ok
public static <T> BaseResponse<T> success(T data) {
return new BaseResponse<>(0, data, "ok");
}
失败就比较复杂,失败顾名思义就是拿不到处理的结果,所以data都为null,所以最主要就是code、message
public static BaseResponse error(int code, String message, String description) {
return new BaseResponse(code, null, message, description);
}
前面我们所说的业务异常,就是可以由我们自己定义errorcode、message来表示,这里我们可以使用一个ErrorCode的枚举类来列举业务中可能出现的异常(类似于throws由我们主动抛出)
ErrorCode-common
枚举类的写法是定义属性、构造方法,然后列举结构体
- code
- message
- description(可选)
/**
*
* 错误码
*/
public enum ErrorCode {
SUCCESS(0, "ok", ""),
PARAMS_ERROR(40000, "请求参数错误", ""),
NULL_ERROR(40001, "请求数据为空", ""),
NOT_LOGIN(40100, "未登录", ""),
NO_AUTH(40101, "无权限", ""),
SYSTEM_ERROR(50000, "系统内部异常", "");
private final int code;
/**
* 状态码信息
*/
private final String message;
/**
* 状态码描述(详情)
*/
private final String description;
ErrorCode(int code, String message, String description) {
this.code = code;
this.message = message;
this.description = description;
}
public int getCode() {
return code;
}
public String getMessage() {
return message;
}
public String getDescription() {
return description;
}
}
回顾一下我们做了哪些事情,首先是定义BaseResponse,它是在包装原有数据的基础上添加了code、message
之后为了方便直接返回包装的返回值类型(success情况),我们添加了ResultUtils类,目前只封装了BaseResponse(0,data,“ok”)-success这种情况,后面我们还会封装失败的类型
然后我们定义了错误状态码ErrorCode,这是一个枚举类,列举了业务中可以抛出的异常,后续我们将会以此为基础搭配最开始的BaseResponse的构造函数来封装失败的情况。
完善BaseResponse
ErrorCode中我们定义的code也要包含到BaseResponse这个范畴中,所以我们可以将ErrorCode作为枚举类对象传入,以拿到ErrorCode定义的信息。
public BaseResponse(ErrorCode errorCode) {
this(errorCode.getCode(), null, errorCode.getMessage(), errorCode.getDescription());
}
这里是拿到ErrorCode中定义的异常信息,对应的需要先在ErrorCode中定义getter方法才能拿到message、code
完善ResultUtils
ResultUtils就是在BaseResponse进一步的拓展,同样的我们需要将刚刚拿到ErrorCode类型的BaseResponse进行封装
public static BaseResponse error(ErrorCode errorCode) {
return new BaseResponse<>(errorCode);
}
这里实际上是做了简化,当然正常的写法是:
public static BaseResponse error(ErrorCode errorCode) {
return new BaseResponse<>(errorCode.getCode(), null, errorCode.getMessage(),errorCode.getDescription());
}
对应的用法就是可直接传入ErrorCode定义的枚举值
return ResultUtils.error(ErrorCode.xxx)
当然我们是可以丰富这里的情况:
- 只拿到ErrorCode中的code,而message由我们自己定义
public static BaseResponse error(ErrorCode errorCode, String Message) {
return new BaseResponse(errorCode.getCode(), Message);
}
完整代码:
/**
* 返回工具类
*
* @author yupi
*/
public class ResultUtils {
/**
* 成功
*
* @param data
* @param <T>
* @return
*/
public static <T> BaseResponse<T> success(T data) {
return new BaseResponse<>(0, data, "ok");
}
/**
* 失败
*
* @param errorCode
* @return
*/
public static BaseResponse error(ErrorCode errorCode) {
return new BaseResponse<>(errorCode);
}
/**
* 失败
*
* @param code
* @param message
* @param description
* @return
*/
public static BaseResponse error(int code, String message, String description) {
return new BaseResponse(code, null, message, description);
}
/**
* 失败
*
* @param errorCode
* @return
*/
public static BaseResponse error(ErrorCode errorCode, String message, String description) {
return new BaseResponse(errorCode.getCode(), null, message, description);
}
/**
* 失败
*
* @param errorCode
* @return
*/
public static BaseResponse error(ErrorCode errorCode, String description) {
return new BaseResponse(errorCode.getCode(), errorCode.getMessage(), description);
}
}