highlight: xcode
theme: vuepress
简介
今天给大家介绍一下如何设计一个业务数据响应体类,就是前端每次请求后端返回的数据我们要统一数据结构, 不能想怎么写就怎么写。规定一个通用的后端数据响应体类十分必要。
响应体类R
其实也很简单,只需要声明一个类,随便你叫什么。R
、Result
、RestResponse
都行啦,我这边为了简洁声明为了 R
类。
R
类有 3 个属性,分别是:
- code:
Integer
类型,业务状态码,每种错误都对应着一个业务错误码或者状态码,由项目团队自定义。 - msg:
String
类型,给前端返回的消息,提示文字。 - data:类型是泛型类
T
,用于保存要返回的数据,根据最终要返回的数据类型而定。比如说要返回List<String>
,那么最终 Controller 层方法返回值就可以写成R<List<String>>
。
R
类中还定义了一些常量,比如说提示消息,业务状态码,这个可以根据自身的业务而定。每家公司的业务标准都不太一样。
```java @Data public class R {
private Integer code = NORMAL_CODE;private String msg = "";private T data;public static final String SUCCESS = "操作成功";public static final String FAILURE = "操作失败";public static final Integer ERROR_CODE = 500;public static final Integer NORMAL_CODE = 200;public R() {}public R(T data) {this.data = data;
}public R(Integer code, String msg, T data) {this.code = code;this.msg = msg;this.data = data;
}public static <T> R<T> ok() {return ok(HttpStatus.HTTP_OK, SUCCESS, null);
}public static <T> R<T> ok(Integer code, String msg, T data) {R<T> r = new R<>();r.setCode(code);r.setMsg(msg);r.setData(data);return r;
}public static <T> R<T> ok(T data) {return ok(ERROR_CODE, SUCCESS, data);
}public static <T> R<T> fail(Integer code, String msg) {return ok(code, msg, null);
}public static <T> R<T> fail(String msg) {return ok(ERROR_CODE, msg, null);
}public static <T> R<T> fail() {return ok(ERROR_CODE, FAILURE, null);
}
} ```
接口示例代码
下面演示一下接口的示例代码,以 UserController
为例,声明一个 UserController
类,标记为 @RestController
:
```java @RestController @RequestMapping("/user") public class UserController {
private UserService userService;// 构造器注入
@Autowired
public UserController(UserService userService) {this.userService = userService;
}@GetMapping("/list")
public R<List<User>> selectAll() {List<User> list = userService.selectAll();return R.ok(list);
}
} ```
最后响应的结果应该是这样:
json { code: 200, msg: "操作成功", data: [ { id: 1, username: "特朗普", age: 80 }, // ... ] }
前端一般这样处理获得数据:
```js // 导入封装的查询接口 import { getUserListAPI } from '@/api/user.js'
async function getUserList() { // 结构出 data 字段,axios 需要在后置处理器配置直接返回 AxiosResponse 的 data 字段 // 这样我们才能拿到我们自己定义的响应体,最后解构出我们自己定义的响应体的 data 字段 // 如果担心名称重复可以使用 : 符号重命名 const { data } = await getUserListAPI()
// 赋值之后,自动触发组件刷新
userList.value = data
} ```
其他语言版本的
如果你的后端使用了 Go 开发,那么可以如法炮制。定义一个结构体 R
:
go type R[T any] struct { Code int `json:code` Msg string `json:msg` Data T `json:data` }
现在 Go 里面也可以使用泛型了,泛型类型约束为 any
,也就是任意类型。Go 语言中不存在什么静态方法,可以自定义函数,但是大可不必,Go 语言的结构体使用起来就是强调一个简洁,跟 JS 的对象字面写法很类似。
下面演示一下在 Gin 框架里面使用响应体结构体 R
:
```go type UserController struct { userService *UserService }
// wire 构造器注入 // 设置 Gin 的路由不作赘述 func NewUserController(userService UserService) *UserController { return &UserController{userService: &userService} }
func (c *UserController) getUserList(ctx *gin.Context) { // 返回 User 的切片 users := c.userService.getUserList() r := R[User[]]{ code: 200, msg: "操作成功", data: users } ctx.JSON(200, r) } ```
怎么样,你学会了吗?😁😁😁