关于自定义R类-前后端数据交互协议
关于自定义R类-前后端数据交互协议
前言
这是我在学习前后端分离开发时遇到的一种前后端数据交互思想时的笔记记录,以便日后遗忘查阅;
目录
一、什么是前后端数据交互协议
所谓前后端数据交互协议,其实就是将后端服务返回的结果封装到一个通用结果类中返回给前端服务。在这种情况下,前端接收的数据格式就是一个通用的结果类对象,可以有规律的去处理返回的数据结果。这种结果类就是前后端交互时所达成的一种数据交互协议。
二、如何自定义一个结果类
现在,我们知道我们所谓的前后端数据交互协议,其实本质上就是定义一个封装各种后端返回结果的结果类。我们暂且自定义一个R类
来作为我们的结果类。
① 思考R类要包含哪些基础属性
- R类主要目的是分装各种数据类型的后端返回结果,那么首先我们要提供一个data属性用于接收待封装的实际数据。
- 既然我们把返回数据都封装成了一个R类,那么前端不管是响应成功还是失败都能拿到该R类。这种情况并不利于前端对返回数据是否符合要求的判断,所以我们要设置一个响应码属性(code),来用于前端判断响应状态。
- 响应码我们一般使用数字,例如1代表成功、0代表失败,但是实际开发中的响应状态并不止这些。当响应状态有10种或上百种,前端通过数字确定响应状态不太友好,所以一般我们还会设置响应码名称(codeName)来用于响应状态说明提示。
- 在开发的过程中,有时候会返回一些后端程序员给予的失败提示信息,或其他提示信息等。所以我们还需要信息属性(msg)用于封装提示信息。
② 设置响应状态码枚举
/**
* 响应码
*
* @author zhao-XH
* @version 1.0
*/
public enum RCodeEnum {
SUCCESS(1, "SUCCESS", "成功"),
FAIL(0, "FAIL", "失败");
private final Integer code;
private final String name;
private final String description;
RCodeEnum(Integer code, String name, String description) {
this.code = code;
this.name = name;
this.description = description;
}
public Integer getCode() {
return code;
}
public String getName() {
return name;
}
public String getDescription() {
return description;
}
}
③ 自定义R类
/**
* 前后端数据交互协议
*
* @param <D> 数据实体类型
* @author zhao-XH
* @version 1.0
*/
public class R<D> {
private Integer code; // 响应码
private String codeName; // 响应码名称
private String msg; // 响应提示信息
private D data; // 响应实际数据
/**
* 无返回数据响应成功
*
* @param <D>
* @return
*/
public static <D> R<D> success() {
R<D> r = new R<>();
r.setCode(RCodeEnum.SUCCESS.getCode());
r.setCodeName(RCodeEnum.SUCCESS.getName());
return r;
}
/**
* 返回数据响应成功
*
* @param data
* @param <D>
* @return
*/
public static <D> R<D> success(D data) {
R<D> r = new R<>();
r.setCode(RCodeEnum.SUCCESS.getCode());
r.setCodeName(RCodeEnum.SUCCESS.getName());
r.setData(data);
return r;
}
/**
* 无返回数据响应成功,并给出提示信息
*
* @param msg
* @param <D>
* @return
*/
public static <D> R<D> successWithMsg(String msg) {
R<D> r = new R<>();
r.setCode(RCodeEnum.SUCCESS.getCode());
r.setCodeName(RCodeEnum.SUCCESS.getName());
r.setMsg(msg);
return r;
}
/**
* 返回数据响应成功,并给出提示信息
*
* @param data
* @param msg
* @param <D>
* @return
*/
public static <D> R<D> successWithDataAndMsg(D data, String msg) {
R<D> r = new R<>();
r.setCode(RCodeEnum.SUCCESS.getCode());
r.setCodeName(RCodeEnum.SUCCESS.getName());
r.setData(data);
r.setMsg(msg);
return r;
}
/**
* 响应失败并给出提示信息
*
* @param msg
* @param <D>
* @return
*/
public static <D> R<D> failWithMsg(String msg) {
R<D> r = new R<>();
r.setCode(RCodeEnum.FAIL.getCode());
r.setCodeName(RCodeEnum.FAIL.getName());
r.setMsg(msg);
return r;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getCodeName() {
return codeName;
}
public void setCodeName(String codeName) {
this.codeName = codeName;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public D getData() {
return data;
}
public void setData(D data) {
this.data = data;
}
}
三、测试
/**
* 测试控制器
*/
@Slf4j
@RestController
@RequestMapping("/test")
public class TestController {
@GetMapping("testSuccess")
public R testSuccess() {
return R.success();
}
@GetMapping("testSuccessWithData")
public R testSuccessWithData(){
return R.success("hello,word!");
}
@GetMapping("testFail")
public R testFail(){
return R.failWithMsg("失败了");
}
}
测试结果
请求:http://localhost:8080/test/testSuccess
结果:
{
"code": 1,
"codeName": "SUCCESS",
"msg": null,
"data": null
}
请求:http://localhost:8080/test/testSuccessWithData
结果:
{
"code": 1,
"codeName": "SUCCESS",
"msg": null,
"data": "hello,word!"
}
请求:http://localhost:8080/test/testFail
结果:
{
"code": 0,
"codeName": "FAIL",
"msg": "失败了",
"data": null
}