You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
RuoYi-Vue/docs/architecture/api-interaction-spec.md

23 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

RuoYi-Vue 前后端交互规范

文档版本v1.0 | 生成日期2026-06-28 | 适用范围RuoYi-Vue 全项目


1. API 接口清单

1.1 接口总览

项目共包含 35 个前端 API 模块文件19 个后端 Controller,梳理出 约 180+ 个 API 端点

1.2 按模块分类

1.2.1 系统管理模块system

序号 模块 前端 API 文件 后端 Controller 接口数 基础路径
1 用户管理 system/user.js SysUserController 13 /system/user
2 角色管理 system/role.js SysRoleController 11 /system/role
3 菜单管理 system/menu.js SysMenuController 7 /system/menu
4 部门管理 system/dept.js SysDeptController 8 /system/dept
5 岗位管理 system/post.js SysPostController 5 /system/post
6 字典类型 system/dict/type.js SysDictTypeController 7 /system/dict/type
7 字典数据 system/dict/data.js SysDictDataController 6 /system/dict/data
8 参数配置 system/config.js SysConfigController 7 /system/config
9 公告管理 system/notice.js SysNoticeController 5 /system/notice

系统管理模块小计69 个接口

1.2.2 监控模块monitor

序号 模块 前端 API 文件 后端 Controller 接口数 基础路径
1 在线用户 monitor/online.js SysUserOnlineController 2 /monitor/online
2 登录日志 monitor/logininfor.js SysLogininforController 3 /monitor/logininfor
3 操作日志 monitor/operlog.js SysOperlogController 3 /monitor/operlog
4 服务监控 monitor/server.js ServerController 1 /monitor/server
5 缓存监控 monitor/cache.js CacheController 1 /monitor/cache
6 定时任务 monitor/job.js SysJobController 7 /monitor/job
7 任务日志 monitor/jobLog.js SysJobLogController 3 /monitor/jobLog

监控模块小计20 个接口

1.2.3 业务模块 — 记账系统booksystem

序号 模块 前端 API 文件 后端 Controller 接口数 基础路径
1 交易账户 booksystem/account.js AccountController 5 /booksystem/account
2 交易记账 booksystem/book.js AccountBookController 5 /booksystem/book
3 当日操作 booksystem/operations.js OperationsController 5 /booksystem/operations
4 单笔统计 booksystem/statistics.js StatisticsController 5 /booksystem/statistics
5 持仓统计 booksystem/statistictotal.js StatisticsTotalController 5 /booksystem/statistictotal
6 当日持仓 booksystem/statisticremain.js StatisticsRemainController 5 /booksystem/statisticremain

记账系统模块小计30 个接口

1.2.4 业务模块 — 股票系统stocksystem

序号 模块 前端 API 文件 后端 Controller 接口数 基础路径
1 行情数据 stocksystem/stocks.js StocksController 6 (+16 扩展) /stocksystem/stocks
2 基础数据 stocksystem/stockbasic.js StockBasicController 5 /stocksystem/stockbasic
3 财务数据 stocksystem/financial.js StockFinancialController 5 /stocksystem/financial
4 指数行情 stocksystem/stockindex.js StockIndexController 5 /stocksystem/stockindex
5 涨跌停板 stocksystem/stockslimit.js StocksLimitController 5 /stocksystem/stockslimit
6 动量结果 stocksystem/trends.js TrendsController 5 (+9 扩展) /stocksystem/trends
7 动量个股 stocksystem/trendStocks.js StocksInTrendController 5 /stocksystem/trendStocks
8 创新高低 stocksystem/newrecord.js StocksNewRecordController 5 (+2 扩展) /stocksystem/newrecord
9 股票记账 stocksystem/book.js StocksBookController 5 /stocksystem/book

股票系统模块小计:约 63 个接口

1.2.5 工具与通用模块

序号 模块 前端 API 文件 后端 Controller 接口数 基础路径
1 代码生成 tool/gen.js GenController 9 /tool/gen
2 登录认证 login.js SysLoginController / CaptchaController 6 /login, /register
3 路由信息 menu.js SysLoginController 1 /getRouters
4 首页聚合 index.js 多 Controller 组合 16 分散
5 通用上传 - CommonController 2 /common/upload, /common/download

工具与通用模块小计:约 34 个接口

1.3 分类统计

模块大类 接口数量 占比
系统管理 ~69 38%
监控管理 ~20 11%
记账系统 ~30 17%
股票系统 ~63 35%
工具与通用 ~34 -
合计 ~182 100%

2. 请求/响应格式

2.1 统一响应格式

所有 API 接口统一使用 AjaxResult 作为响应载体,其本质是 HashMap<String, Object>

2.1.1 成功响应(无数据)

{
  "code": 200,
  "msg": "操作成功"
}

2.1.2 成功响应(带数据)

{
  "code": 200,
  "msg": "操作成功",
  "data": {
    "userId": 1,
    "userName": "admin"
  }
}

2.1.3 成功响应(多字段 — AjaxResult.put 扩展)

{
  "code": 200,
  "msg": "操作成功",
  "data": { /* 用户详情 */ },
  "roles": [ /* 角色列表 */ ],
  "posts": [ /* 岗位列表 */ ],
  "postIds": [1, 2],
  "roleIds": [1]
}

注意:后端使用 ajax.put(key, value) 动态追加字段,前端通过 response.roles 等方式访问。

2.1.4 分页响应TableDataInfo

{
  "total": 100,
  "rows": [
    { "userId": 1, "userName": "admin" },
    { "userId": 2, "userName": "test" }
  ],
  "code": 200,
  "msg": "查询成功"
}
字段 类型 说明
total long 总记录数
rows List<?> 当前页数据列表
code int 状态码(固定 200
msg String 消息文本

2.1.5 失败响应

{
  "code": 500,
  "msg": "新增用户'admin'失败,登录账号已存在"
}

2.2 请求格式规范

2.2.1 查询列表GET

// 前端
export function listUser(query) {
  return request({ url: '/system/user/list', method: 'get', params: query })
}

// 请求参数通过 URL Query 传递
GET /system/user/list?pageNum=1&pageSize=10&userName=admin&status=0

2.2.2 查询详情GET + PathVariable

export function getUser(userId) {
  return request({ url: '/system/user/' + userId, method: 'get' })
}

// 请求
GET /system/user/1

2.2.3 新增POST + JSON Body

export function addUser(data) {
  return request({ url: '/system/user', method: 'post', data: data })
}

// 请求头: Content-Type: application/json;charset=utf-8
POST /system/user
Body: { "userName": "test", "phonenumber": "13800138000" }

2.2.4 修改PUT + JSON Body

export function updateUser(data) {
  return request({ url: '/system/user', method: 'put', data: data })
}

PUT /system/user
Body: { "userId": 1, "userName": "admin" }

2.2.5 删除DELETE + PathVariable

export function delUser(userId) {
  return request({ url: '/system/user/' + userId, method: 'delete' })
}

DELETE /system/user/1

后端实际接收 Long[] 数组,支持批量删除:DELETE /system/user/1,2,3

2.2.6 文件下载POST + Blob

export function download(url, params, filename) {
  return service.post(url, params, {
    transformRequest: [(params) => { return tansParams(params) }],
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    responseType: 'blob'
  })
}

2.2.7 登录请求(跳过 Token

export function login(username, password, code, uuid) {
  return request({
    url: '/login',
    headers: { isToken: false },  // 不携带 Token
    method: 'post',
    data: { username, password, code, uuid }
  })
}

2.3 登录认证机制

环节 说明
Token 载体 JWT Token
Token 传递 Authorization: Bearer {token}
请求头配置 axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'
Token 跳过 headers: { isToken: false }
超时时间 60 秒(验证码接口 20 秒)

3. 错误处理机制

3.1 前端响应拦截器

位置:ruoyi-ui/src/utils/request.js

service.interceptors.response.use(res => {
  const code = res.data.code || 200;     // 默认成功
  const msg = errorCode[code] || res.data.msg || errorCode['default']

  // 二进制数据直接返回
  if (res.request.responseType === 'blob' || res.request.responseType === 'arraybuffer') {
    return res.data
  }

  if (code === 401) {
    // 弹出确认框 → 重新登录
    MessageBox.confirm('登录状态已过期...', '系统提示', {...})
    return Promise.reject('无效的会话...')
  } else if (code === 500) {
    // 全局 Message.error 提示
    Message({ message: msg, type: 'error' })
    return Promise.reject(new Error(msg))
  } else if (code !== 200) {
    // 其他错误码 → Notification.error
    Notification.error({ title: msg })
    return Promise.reject('error')
  } else {
    return res.data  // 正常返回
  }
}, error => {
  // HTTP 层错误处理
  let { message } = error;
  if (message == "Network Error") {
    message = "后端接口连接异常";
  } else if (message.includes("timeout")) {
    message = "系统接口请求超时";
  } else if (message.includes("Request failed with status code")) {
    message = "系统接口" + message.substr(message.length - 3) + "异常";
  }
  Message({ message, type: 'error', duration: 5000 })
  return Promise.reject(error)
})

3.2 后端全局异常处理

位置:ruoyi-framework/src/main/java/com/ruoyi/framework/web/exception/GlobalExceptionHandler.java

异常类型 处理方式 返回状态码
AccessDeniedException 权限校验失败 403 — "没有权限,请联系管理员授权"
HttpRequestMethodNotSupportedException 不支持的请求方法 500 — 异常消息
ServiceException 业务异常(带自定义 code code 或 500
BindException 参数校验失败 500 — 校验错误消息
MethodArgumentNotValidException @Valid 校验失败 500 — 字段错误消息
DemoModeException 演示模式限制 500 — "演示模式,不允许操作"
RuntimeException 未知运行时异常 500 — 异常消息
Exception 兜底系统异常 500 — 异常消息

3.3 错误码体系

位置:ruoyi-common/src/main/java/com/ruoyi/common/constant/HttpStatus.java

状态码 常量名 含义
200 SUCCESS 操作成功
201 CREATED 对象创建成功
202 ACCEPTED 请求已被接受
204 NO_CONTENT 操作成功但无返回数据
301 MOVED_PERM 资源已永久移除
303 SEE_OTHER 重定向
304 NOT_MODIFIED 资源未修改
400 BAD_REQUEST 参数错误
401 UNAUTHORIZED 未授权 / Token 过期
403 FORBIDDEN 访问受限 / 权限不足
404 NOT_FOUND 资源/服务未找到
405 BAD_METHOD 不支持的 HTTP 方法
409 CONFLICT 资源冲突/被锁
415 UNSUPPORTED_TYPE 不支持的媒体类型
500 ERROR 系统内部错误
501 NOT_IMPLEMENTED 接口未实现

前端错误码映射

位置:ruoyi-ui/src/utils/errorCode.js

export default {
  '401': '认证失败,无法访问系统资源',
  '403': '当前操作没有权限',
  '404': '访问资源不存在',
  'default': '系统未知错误,请反馈给管理员'
}

注意:前端仅映射了 3 个业务错误码其余错误码400、409、415 等)直接 fallback 到后端返回的 msgdefault

3.4 错误处理流程图

HTTP 层错误                    业务层错误
     │                              │
     ▼                              ▼
Network Error / Timeout       res.data.code
     │                              │
     ▼                              ▼
Message.error               code === 401 → MessageBox.confirm → 跳转登录
                            code === 500 → Message.error
                            code !== 200 → Notification.error
                            code === 200 → 正常返回 res.data

4. 分页 / 排序 / 过滤

4.1 分页实现

基于 PageHelper 实现,采用 ThreadLocal 模式。

4.1.1 后端处理流程

前端请求                         后端处理
  │                               │
  │  GET /system/user/list        │
  │  ?pageNum=1&pageSize=10       │
  ▼                               ▼
                          TableSupport.buildPageRequest()
                               │
                               ▼
                          PageUtils.startPage()
                               │
                               ▼
                          PageHelper.startPage(pageNum, pageSize, orderBy)
                               │
                               ▼
                          执行 MyBatis 查询(自动添加 LIMIT
                               │
                               ▼
                          BaseController.getDataTable(list)
                               │
                               ▼
                          new PageInfo(list).getTotal() → total
                          return TableDataInfo { total, rows, code, msg }

4.1.2 分页参数

参数名 类型 必填 默认值 说明
pageNum Integer - 当前页码(从 1 开始)
pageSize Integer - 每页记录数
orderByColumn String - 排序字段名
isAsc String - 排序方向:ascdesc,多字段用逗号分隔
reasonable Boolean - 分页合理化pageNum<=0 查第一页pageNum>总页数查最后一页)

4.1.3 后端代码示例

@GetMapping("/list")
public TableDataInfo list(SysUser user) {
    startPage();                              // 从请求参数读取分页信息
    List<SysUser> list = userService.selectUserList(user);
    return getDataTable(list);                 // 封装为 TableDataInfo
}

4.2 排序规范

4.2.1 排序参数传递

// 前端通过分页组件传递
{
  pageNum: 1,
  pageSize: 10,
  orderByColumn: 'createTime',
  isAsc: 'desc'
}

4.2.2 多字段排序

isAsc: createTime desc,updateTime desc

4.2.3 SQL 注入防护

// SqlUtil.escapeOrderBySql() 方法对排序字段进行转义
// 只允许字母、数字、下划线、点号、逗号、空格、ASC、DESC
String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy());
PageHelper.orderBy(orderBy);

4.3 过滤规范

4.3.1 列表查询过滤

采用 对象参数绑定 方式:

// 后端
@GetMapping("/list")
public TableDataInfo list(SysUser user) {
    startPage();
    // user 对象自动绑定 query 参数中的字段
    List<SysUser> list = userService.selectUserList(user);
    return getDataTable(list);
}

// 前端
GET /system/user/list?userName=admin&phonenumber=138&status=0

4.3.2 权限过滤

// 每个接口通过 @PreAuthorize 进行权限校验
@PreAuthorize("@ss.hasPermi('system:user:list')")
@GetMapping("/list")
public TableDataInfo list(SysUser user) { ... }

4.3.3 数据权限过滤

// 在 Service 层通过 AOP 实现数据权限(部门数据范围)
// 支持:全部数据、本部门数据、本部门及以下、仅本人数据、自定义数据范围

4.4 导出/导入规范

操作 HTTP 方法 路径模式 说明
导出 Excel POST /{module}/export 直接写入 HttpServletResponse
导入 Excel POST /{module}/importData MultipartFile + updateSupport 参数
下载模板 POST /{module}/importTemplate 返回空模板文件

5. 存在的问题

5.1 问题清单

# 问题类型 严重程度 问题描述 涉及范围 优化建议
1 响应格式不统一 AjaxResult(普通 CRUDTableDataInfo(分页列表)返回结构完全不同:前者用 data 字段,后者用 rows + total 字段。前端需要分别处理两种响应结构,增加认知负担。 全部列表接口 vs 详情/操作接口 统一使用单一响应结构,如 { code, msg, data: { list, total } },或在 TableDataInfo 中也使用 data 字段包裹
2 错误码体系不完整 前端 errorCode.js 仅映射了 401/403/404 三个错误码400/409/415 等 HTTP 标准错误码未做前端映射,全部 fallback 到 default 或后端 msg。后端虽定义了 16 个状态码,但实际使用集中在 200 和 500。 全局错误处理 完善前端错误码映射表;后端减少 500 的滥用,对参数错误返回 400对业务冲突返回 409
3 排序字段 SQL 注入风险 虽然使用了 SqlUtil.escapeOrderBySql() 进行过滤,但正则表达式级别的过滤存在被绕过的可能。排序参数直接从请求参数读取并拼接到 SQL ORDER BY 子句中。 TableSupport + SqlUtil 使用白名单机制,仅允许传入已知的字段名;或使用 MyBatis 动态 SQL 的 <choose> 标签做安全排序
4 前后端 API 路径不一致 前端 index.js 调用 /stocksystem/stocks/groupLimitlist,而后端 StocksController 中该方法被注释了权限控制(@PreAuthorize 被注释)。另外部分接口前端使用 /querylist,后端映射为 /list,存在冗余接口。 股票系统模块 清理未使用的接口;补全权限控制;统一前后端路径命名规范
5 分页参数隐式依赖 分页参数通过 ServletUtils.getParameter() 从 HttpServletRequest 中隐式读取,而非通过 @RequestParam 显式声明。这使得 API 文档(如 Swagger无法自动生成分页参数说明API 可读性差。 TableSupport.getPageDomain() 使用 @RequestParam(defaultValue = "1") Integer pageNum 显式声明分页参数,或使用 PageRequest 对象作为 Controller 方法参数
6 HTTP 状态码与业务状态码混用 后端 HTTP Response 的 Status Code 始终为 200真正的业务状态码在响应体 code 字段中。这导致前端无法利用 HTTP 状态码进行路由/拦截逻辑,也与 RESTful 最佳实践不符。 全局 保持当前模式(业界常见做法)但需在文档中明确说明;或改为 HTTP Status Code 与业务 code 一致
7 GET 请求参数转换方式不标准 前端 GET 请求的 params 被手动拼接为 URL 字符串(tansParams 函数),而不是使用 axios 原生的 paramsSerializer。这可能导致特殊字符编码问题。 request.js 请求拦截器 使用 axios 的 paramsSerializer 配置,或 URLSearchParams 进行参数序列化
8 批量删除路径参数格式不一致 部分 Controller 使用 @DeleteMapping("/{ids}") 接收 Long[],但 URL 中数组的传递格式(逗号分隔 vs 多次参数)缺乏统一规范,前端需要手动拼接字符串。 所有支持批量删除的接口 统一使用 @DeleteMapping + @RequestParam List<Long> ids@RequestBody 传递数组
9 大量调试代码未清理 StocksController 中存在大量 System.out.println() 调试输出(超过 50 处以及大段被注释的代码1000+ 行)。这些代码在生产环境中会污染日志,且增加维护成本。 stock-system 模块 统一替换为 logger.info/debug;清理历史注释代码
10 接口文档缺失 项目虽引入了 Swagger 依赖(TestController 中有示例),但所有业务 Controller 均未添加 Swagger 注解(@Api@ApiOperation@ApiParam 等),导致无法自动生成 API 文档。 全部 Controller 补充 Swagger/OpenAPI 注解;或接入 SpringDoc / Knife4j

5.2 综合优化建议

短期优化1-2 周)

  1. 补充前端错误码映射:在 errorCode.js 中补充 400/409/415 等常见错误码的中文提示
  2. 清理调试代码:将 StocksController 中的 System.out.println 替换为 logger
  3. 补全权限注解:取消 StocksController 中被注释的 @PreAuthorize

中期优化1-2 月)

  1. 接入 API 文档:为所有 Controller 补充 Swagger 注解,启用 Knife4j 文档页面
  2. 规范分页参数:考虑使用 @Validated 显式声明分页参数
  3. 统一响应格式:评估是否需要统一 AjaxResultTableDataInfo 的字段结构

长期优化(持续)

  1. 排序安全加固:实施白名单机制替代正则过滤
  2. RESTful 对齐:评估是否将业务状态码与 HTTP 状态码对齐
  3. API 版本管理:当接口变更时引入 /api/v1/ 等版本前缀

附录

A. 关键技术栈

层级 技术 版本
前端框架 Vue 2 + Element UI 2.x
HTTP 客户端 Axios -
后端框架 Spring Boot 2.x
Web 框架 Spring MVC -
权限框架 Spring Security -
分页组件 PageHelper -
ORM MyBatis -

B. 核心文件路径

文件 路径
前端请求封装 ruoyi-ui/src/utils/request.js
前端错误码映射 ruoyi-ui/src/utils/errorCode.js
前端 API 目录 ruoyi-ui/src/api/
后端统一响应 ruoyi-common/.../AjaxResult.java
后端分页响应 ruoyi-common/.../TableDataInfo.java
后端分页工具 ruoyi-common/.../PageUtils.java
后端排序支持 ruoyi-common/.../TableSupport.java
后端全局异常 ruoyi-framework/.../GlobalExceptionHandler.java
后端状态码常量 ruoyi-common/.../HttpStatus.java
后端 BaseController ruoyi-common/.../BaseController.java

C. HTTP 方法使用统计

方法 用途 使用频率
GET 查询列表、查询详情、查询树结构、下载 ~45%
POST 新增、登录、注册、导出、导入、分析 ~30%
PUT 修改、状态变更、授权、重置密码 ~20%
DELETE 删除、清空日志、刷新缓存 ~5%