1324a52049
- 新增 Result统一响应类.md 完整文档 - 修正 API设计规范.md 中响应字段与实际代码不一致的问题 - 错误码规范表按实际 ResultCode 枚举对齐
9.0 KiB
9.0 KiB
Result 统一响应类规范
RUI 框架所有 API 接口的统一返回包装
一、类信息
| 属性 | 值 |
|---|---|
| 包路径 | com.rui.common.core.result.Result |
| 所在模块 | rui-common-core |
| 泛型参数 | <T> — data 字段的具体类型 |
| 序列化 | 实现 Serializable |
| JSON 策略 | @JsonInclude(NON_NULL) — 值为 null 的字段自动忽略 |
二、响应结构
2.1 字段定义
| 字段 | 类型 | 说明 | 成功时 | 失败时 |
|---|---|---|---|---|
error |
int |
状态码(0 = 成功) | 0 |
非 0 |
message |
String |
提示信息 | "操作成功" |
具体错误描述 |
code |
String |
业务错误码 | null(不输出) |
如 "AUTH_UNAUTHORIZED" |
data |
T |
业务数据 | 实际数据 | 通常为 null(不输出) |
2.2 成功响应示例
无数据返回:
{
"error": 0,
"message": "操作成功"
}
带数据返回:
{
"error": 0,
"message": "操作成功",
"data": {
"id": 1001,
"username": "admin"
}
}
分页数据:
{
"error": 0,
"message": "操作成功",
"data": {
"records": [],
"total": 100,
"size": 10,
"current": 1,
"pages": 10
}
}
2.3 失败响应示例
通用失败:
{
"error": 1,
"message": "操作失败"
}
带业务错误码:
{
"error": 401,
"message": "未授权",
"code": "AUTH_UNAUTHORIZED"
}
带数据(未找到场景):
{
"error": 404,
"message": "数据不存在",
"code": "DATA_NOT_FOUND",
"data": "dictCode_001"
}
data字段在failNotFound场景下用于传递资源 key,便于前端做国际化模板替换。
三、静态工厂方法
3.1 成功系列
| 方法签名 | 说明 | 使用场景 |
|---|---|---|
Result.ok() |
无数据成功 | 删除、更新等不需要返回数据的操作 |
Result.ok(T data) |
带数据成功 | 查询详情、列表、新增返回实体 |
3.2 失败系列
| 方法签名 | 说明 | 使用场景 |
|---|---|---|
Result.fail() |
通用失败 | 兜底异常、未知错误 |
Result.fail(String message) |
自定义提示 | 需要特定提示信息的业务异常 |
Result.fail(ResultCode resultCode) |
枚举驱动 | 标准业务错误,推荐使用 |
Result.fail(int error, String message) |
自定义错误码+提示 | 非标准错误场景 |
Result.fail(int error, String message, String code) |
完全自定义 | 需要同时指定三个字段 |
Result.fail(ResultCode resultCode, T data) |
枚举+数据 | 失败时需携带部分数据 |
Result.failNotFound(ResultCode resultCode, String key) |
404 未找到 | 数据不存在,key 放入 data |
3.3 判断方法
| 方法 | 说明 |
|---|---|
result.isSuccess() |
判断是否成功(error == 0) |
result.toJsonString() |
序列化为 JSON 字符串 |
四、ResultCode 枚举
4.1 枚举结构
| 属性 | 类型 | 说明 |
|---|---|---|
error |
int |
HTTP 风格状态码,0 为成功 |
message |
String |
默认提示文本 |
code |
String |
业务错误码(大写蛇形,模块前缀) |
4.2 枚举值一览
| 枚举值 | error | message | code | 说明 |
|---|---|---|---|---|
SUCCESS |
0 | 操作成功 | null |
成功 |
FAILURE |
1 | 操作失败 | null |
通用失败 |
UNAUTHORIZED |
401 | 未授权 | AUTH_UNAUTHORIZED |
未登录 |
FORBIDDEN |
403 | 无权限 | AUTH_FORBIDDEN |
无权限 |
NOT_FOUND |
404 | 资源不存在 | COMMON_NOT_FOUND |
资源未找到 |
DATA_NOT_FOUND |
404 | 数据不存在 | DATA_NOT_FOUND |
数据未找到 |
VALIDATE_FAILED |
400 | 参数校验失败 | COMMON_VALIDATE_FAILED |
参数错误 |
TOKEN_EXPIRED |
4001 | Token 已过期 | AUTH_TOKEN_EXPIRED |
Token 过期 |
TOKEN_INVALID |
4002 | Token 无效 | AUTH_TOKEN_INVALID |
Token 无效 |
TENANT_NOT_FOUND |
4003 | 租户不存在 | AUTH_TENANT_NOT_FOUND |
租户不存在 |
TENANT_DISABLED |
4004 | 租户已禁用 | AUTH_TENANT_DISABLED |
租户禁用 |
USER_NOT_FOUND |
4101 | 用户不存在 | USER_INFO_NOT_FOUND |
用户不存在 |
USERNAME_EXISTS |
4102 | 用户名已存在 | USER_INFO_USERNAME_EXISTS |
用户名重复 |
LEVEL_CODE_EXISTS |
4201 | 等级编码已存在 | USER_LEVEL_CODE_EXISTS |
等级编码重复 |
4.3 错误码规划规则
| 区间 | 模块 | code 前缀 |
|---|---|---|
| 0 | 通用成功 | — |
| 1 | 通用失败 | — |
| 400-499 | HTTP 标准错误 | COMMON_* / AUTH_* |
| 4000-4099 | 认证错误 | AUTH_* |
| 4100-4199 | 用户信息错误 | USER_INFO_* |
| 4200-4299 | 用户等级错误 | USER_LEVEL_* |
| 5000-5999 | 文件模块(预留) | FILE_* |
| 6000-6999 | 消息模块(预留) | MSG_* |
新增规则:新模块取 100 的整数倍区间,code 格式为 {模块}_{业务}_{具体}。
五、Controller 使用示例
5.1 标准 CRUD
@RestController
@RequestMapping("/v1/system/roles")
@RequiredArgsConstructor
public class SysRoleController {
private final SysRoleService roleService;
@GetMapping
public Result<IPage<SysRoleVO>> list(SysRoleQuery query) {
return Result.ok(roleService.page(query));
}
@GetMapping("/{id}")
public Result<SysRoleVO> getById(@PathVariable Long id) {
SysRoleVO role = roleService.getById(id);
if (role == null) {
return Result.failNotFound(ResultCode.DATA_NOT_FOUND, String.valueOf(id));
}
return Result.ok(role);
}
@PostMapping
public Result<SysRoleVO> create(@RequestBody @Valid SysRoleDTO dto) {
return Result.ok(roleService.create(dto));
}
@PutMapping("/{id}")
public Result<SysRoleVO> update(@PathVariable Long id, @RequestBody @Valid SysRoleDTO dto) {
return Result.ok(roleService.update(id, dto));
}
@DeleteMapping("/{id}")
public Result<Void> delete(@PathVariable Long id) {
roleService.delete(id);
return Result.ok();
}
}
5.2 异常处理中返回
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(BizException.class)
public Result<Void> handleBizException(BizException e) {
return Result.fail(e.getCode(), e.getMessage());
}
@ExceptionHandler(MethodArgumentNotValidException.class)
public Result<Void> handleValidation(MethodArgumentNotValidException e) {
String message = e.getBindingResult().getFieldErrors().stream()
.map(FieldError::getDefaultMessage)
.collect(Collectors.joining(", "));
return Result.fail(ResultCode.VALIDATE_FAILED.getError(), message, ResultCode.VALIDATE_FAILED.getCode());
}
}
5.3 Feign 远程调用中处理 Result
@Service
@RequiredArgsConstructor
public class UserRemoteService {
private final RemoteUserService remoteUserService;
public UserVO getUserById(Long userId) {
Result<UserVO> result = remoteUserService.getById(userId);
if (result.isSuccess()) {
return result.getData();
}
throw new BizException(result.getError(), result.getMessage());
}
}
六、前端对接指南
6.1 判断成功
// response.data 为 Result<T> 结构
const isSuccess = response.data.error === 0;
6.2 错误处理
if (result.error !== 0) {
// 优先用 code 做国际化
if (result.code) {
showI18nMessage(result.code, { key: result.data });
} else {
// 降级显示 message
showMessage(result.message);
}
}
6.3 TypeScript 类型定义
interface Result<T = any> {
error: number;
message: string;
code?: string; // 失败时存在
data?: T; // 成功时或 failNotFound 时存在
}
七、扩展指南
7.1 新增 ResultCode
在 ResultCode 枚举中添加新值,遵循以下规则:
- error 取值:按模块区间分配(见 4.3 节)
- code 命名:
{模块}_{业务}_{具体},全大写蛇形 - 向后兼容:禁止修改已有枚举值的 error 或 code
// 示例:文件模块新增
FILE_UPLOAD_FAILED(5001, "文件上传失败", "FILE_UPLOAD_FAILED"),
FILE_SIZE_EXCEEDED(5002, "文件大小超限", "FILE_SIZE_EXCEEDED"),
7.2 禁止事项
- ❌ 不要在 Controller 中直接
new Result<>(),必须使用静态工厂方法 - ❌ 不要修改
Result类的字段名(error/message/code/data),影响序列化兼容 - ❌ 不要用
error字段传递 HTTP 状态码(它只是业务状态码,HTTP 状态码由框架控制) - ❌ 不要在
code字段中使用小写或特殊字符
文档版本: v1.0 创建日期: 2026-06-08 源码位置:
rui-common/rui-common-core/src/main/java/com/rui/common/core/result/适用范围: RUI 框架所有模块的 API 响应