第三阶段重构:统一接口响应与 Restful 规范化演进
1. 阶段核心目标与背景
在完成核心模块的 DDD 架构重构后,系统内部业务逻辑已高度内聚。但在接口交付层,仍存在前后端联调成本高、错误定位困难(依赖字符串如 msg: "未登录")、以及遗留 API 不规范(如 POST /devices/PageConditional)等工程问题。本阶段聚焦于接口层面的工程化改造,核心目标如下:
- (1) 异常处理分层统一:彻底消灭 Controller 层臃肿的
try-catch代码块,业务异常与系统级异常统一由全局/局部的ExceptionHandler拦截并转译为标准化 Rest 响应。 - (2) 错误码语义标准化 (Error Code):废弃含糊不清的字符串错误提示,建立跨前端、后端、移动端可复用的强类型
ErrorCode体系,提升联调效率与错误埋点分析能力。 - (3) Restful 规范化与平滑迁移:落地符合现代 REST 语义的 API 设计。为避免业务中断,采取“双路径并行”的灰度策略,保留旧路径一个大版本,并通过标准的 HTTP 响应头(Deprecation Headers)输出警告,实现前端零停机平滑过渡。
2. 改造范围与涉及文件
2.1 后端 (Java 74.8%)
(1) 公共基础设施层 (Common):
/common/constant/ErrorCode.java(新增:统一错误码枚举字典)/common/core/domain/Result.java(重构:支持基于 ErrorCode 的工厂方法构建)/common/handler/GlobalExceptionHandler.java(新增:Spring@RestControllerAdvice全局兜底)
(2) 业务系统层 (System - 振动设备与用户域):
/system/controller/DeviceController.java(路由改造:支持/devices/query与旧路径并行)/system/controller/LoginController.java(路由改造:用户鉴权端点标准化)/system/handler/DeviceExceptionHandler.java(新增:处理诸如“振动阈值设置不合法”等专有异常)/system/handler/UserExceptionHandler.java(新增:处理账号封禁、密码连续试错等专有异常)/system/utils/LoginCheckIntercept.java&LoginCheckFilter.java(优化:无权访问时抛出标准未登录异常码)
2.2 前端 (Vue 22.8% / JavaScript 2%)
vibration-web-portal/src/utils/request.js(核心逻辑:Axios 响应拦截器适配新错误码体系)vibration-web-portal/src/views/device/DeviceManager.vue(视图改造:数据表格的分页查询接口平滑切换)
3. 主要改造内容详述
3.1 异常处理机制与错误码统一
3.1.1 建立 ErrorCode 错误码体系
在工业互联网场景中,设备状态与用户权限极为复杂。我们在 Result 封装体中引入了严格的 ErrorCode 枚举,取代了以往 Result.error("设备不存在") 的脆弱做法。错误码按业务域划分号段:
- 通用基础 (1000+):
SYSTEM_ERROR(1000, "系统繁忙,请稍后再试")INVALID_ARGUMENT(1001, "参数校验未通过")
- 认证鉴权 (1100+):
NOT_LOGIN(1101, "访问凭证已过期或未登录")LOGIN_FAILED(1102, "账号或密码错误")USER_DISABLED(1103, "当前操作员账号已被冻结,请联系管理员")
- 用户管理 (1200+):
USER_ACCOUNT_EXISTS(1201, "手机号/账号已被注册")
- 设备与振动业务 (1300+):
DEVICE_VALIDATION_FAILED(1301, "设备参数校验失败(例:振动采样频率超限)")DEVICE_OPERATION_FAILED(1302, "设备指令下发或状态流转失败")
3.1.2 异常处理分层收敛与 Controller 瘦身
此前 Controller 层为了处理保存设备时的唯一性冲突,充斥着大量的代码。重构后,Controller 只保留单行调用代码,异常统一上抛:
- 全局域 (
GlobalExceptionHandler): 负责兜底通用异常。例如,使用正则表达式拦截数据库层面的Duplicate entry(如DataIntegrityViolationException),精准映射为1201冲突业务码。 - 业务域专项处理:
DeviceExceptionHandler: 专项拦截领域层抛出的DeviceValidationException,将其转化为Result.error(ErrorCode.DEVICE_VALIDATION_FAILED)。UserExceptionHandler: 专项拦截登录业务异常。
- 无侵入鉴权拦截: 在
LoginCheckIntercept中,当 JWT 校验失败时,直接通过response.getWriter().write()输出包含ErrorCode.NOT_LOGIN的标准 JSON,前端可无缝解析。
3.2 Restful 双路径并行策略
旧系统存在大量类似 POST /devices/PageConditional(动宾结构且带有大写字母)的反模式 API。本次采取 双路径并行、兼容一个大版本后下线 (预计 v2.5 下线) 的灰度迁移策略。
3.2.1 统一弃用响应头标准(Deprecated Headers)
我们在后端抽离了公共方法,在新旧两个 @PostMapping 中调用相同逻辑,但对旧路径额外注入 HTTP 标准弃用规范头。前端在抓包或控制台网络面板中会清晰看到警告:
HTTP/1.1 200 OK
Content-Type: application/json
Deprecation: true
Sunset: 2026-06-30T23:59:59Z
Link: <https://api.vibration-cloud.com/v2/devices/query>; rel="successor-version"
Warning: 299 - "Deprecated API: /devices/PageConditional will be removed in v2.5"
3.2.2 核心接口路由映射表
| 业务模块 | 新路径(标准 RESTful 规范) | 旧路径(仅作兼容期保留) | 状态与说明 |
|---|---|---|---|
| 设备 - 分页查询 | POST /devices/query | POST /devices/PageConditional | 旧路径已注入 Deprecation 头 |
| 设备 - 缩略图上传 | POST /devices/{id}/image | POST /devices/uploadImage | 将 ID 提取到 URL 路径参数中 |
| 设备 - 云端图库 | POST /devices/images/cloud | POST /devices/uploadImageToCloud | 语义化重构,旧路径保留 |
| 用户 - 新增注册 | POST /users | POST /login/register | 遵循资源导向设计 |
| 用户 - 鉴权登录 | POST /users/login | POST /login | 旧路径保留,将于 v2.5 移除 |
3.3 前端 (Vue) 最小兼容迁移
由于采用了兼容策略,前端的重构压力被极大地释放。前端组仅需对基础框架做一次低侵入式的兼容升级:
1. Axios 拦截器平滑适配 (request.js)
为了兼容旧版后端写死的 msg: "NOT_LOGIN" 和新版的 code: 1101,修改响应拦截器:
instance.interceptors.response.use(res => {
const data = res.data;
// 兼容新旧两套未登录标识,执行统一登出与路由重定向逻辑
if (data.code === 1101 || data.msg === 'NOT_LOGIN') {
store.dispatch('user/resetToken');
router.push({ path: '/login', query: { redirect: router.currentRoute.fullPath } });
return Promise.reject(new Error('凭证失效,请重新登录'));
}
// 业务级报错,统一走 ErrorCode
if (data.code && data.code !== 1) {
Message.error(data.msg || '操作失败');
return Promise.reject(new Error(data.msg));
}
return data.data; // 正常返回脱壳后的数据
});
2. 视图层 API 替换 (DeviceManager.vue)
将设备大屏列表调用的老旧 API 平滑切换为新路径:
// 旧:import { getDevicePageConditional } from '@/api/device'
// 新:切换为符合 REST 规范的请求方法
import { queryDevicePage } from '@/api/device'
// api/device.js 内部已更新为:
// export const queryDevicePage = (data) => request({ url: '/devices/query', method: 'post', data })
4. 阶段性回归与验收标准
A. 用户与认证体系回归
- 正常注册闭环: 模拟新操作员开户,请求
POST /users,校验落库情况并成功返回code: 1。 - 唯一性异常校验: 模拟高并发下注册重复账号(如手机号
13800000000),预期捕获约束异常并返回精准业务码code: 1201。 - 恶意登录拦截: 连续请求
POST /users/login使用错误密码,预期返回code: 1102;使用已被离职管理员标记状态的用户登录,预期返回code: 1103。 - 无感拦截验证: 清除浏览器 Cookie/LocalStore 中的 Token,访问
/devices/query,预期立刻被中间件拦截并返回code: 1101,前端应触发自动跳转登录页。
B. 振动设备管理体系回归
- 查询引擎验证: 调用
POST /devices/query(附带复杂条件:泵类设备、运行状态、频段 10-500Hz),断言分页插件返回预期数据集。 - 文件流上传测试: 模拟向指定振动传感器(ID:
DEV-8890)调用新路径POST /devices/DEV-8890/image,验证本地文件 I/O 与数据库 URL 回写均成功。 - 领域规则边界测试: 构造非法设备载荷(例如:将报警阈值设定低于正常运行基线值),触发领域防腐层校验,预期全局拦截并返回
code: 1301及明确的错误指导信息。
C. 生产环境容灾与平滑兼容验证
- 遗留流量监测: 通过 Postman 调用旧版移动端依赖的遗留路径(如
/devices/PageConditional),验证业务仍可正常闭环响应。 - 弃用声明核验: 检查上述遗留请求的 Header 中,是否成功输出了
Deprecation: true及Sunset: 2026-06-30警告标识,确保规范化要求已落实。