|
|
|
|
# API参考文档
|
|
|
|
|
|
|
|
|
|
<cite>
|
|
|
|
|
**本文档引用的文件**
|
|
|
|
|
- [CrmAppApplication.java](file://crm-app/src/main/java/com/crm/app/CrmAppApplication.java)
|
|
|
|
|
- [application.yml](file://crm-app/src/main/resources/application.yml)
|
|
|
|
|
- [AuthController.java](file://crm-auth/src/main/java/com/crm/auth/controller/AuthController.java)
|
|
|
|
|
- [SystemController.java](file://crm-auth/src/main/java/com/crm/auth/controller/SystemController.java)
|
|
|
|
|
- [SecurityConfig.java](file://crm-auth/src/main/java/com/crm/auth/config/SecurityConfig.java)
|
|
|
|
|
- [PermissionConfig.java](file://crm-auth/src/main/java/com/crm/auth/config/PermissionConfig.java)
|
|
|
|
|
- [JwtAuthenticationFilter.java](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java)
|
|
|
|
|
- [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java)
|
|
|
|
|
- [AuthLoginUser.java](file://crm-auth/src/main/java/com/crm/auth/security/AuthLoginUser.java)
|
|
|
|
|
- [LoginParam.java](file://crm-auth/src/main/java/com/crm/auth/domain/param/LoginParam.java)
|
|
|
|
|
- [LoginResultDTO.java](file://crm-auth/src/main/java/com/crm/auth/domain/dto/LoginResultDTO.java)
|
|
|
|
|
- [UserInfoDTO.java](file://crm-auth/src/main/java/com/crm/auth/domain/dto/UserInfoDTO.java)
|
|
|
|
|
- [AuthService.java](file://crm-auth/src/main/java/com/crm/auth/service/IAuthService.java)
|
|
|
|
|
- [AuthUserServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/AuthUserServiceImpl.java)
|
|
|
|
|
- [SysMenuServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/SysMenuServiceImpl.java)
|
|
|
|
|
- [GlobalExceptionHandlerAdvice.java](file://crm-base/src/main/java/com/crm/base/advice/GlobalExceptionHandlerAdvice.java)
|
|
|
|
|
- [Result.java](file://crm-base/src/main/java/com/crm/base/domain/result/Result.java)
|
|
|
|
|
- [ResultCodeEnum.java](file://crm-base/src/main/java/com/crm/base/domain/result/ResultCodeEnum.java)
|
|
|
|
|
- [PageResult.java](file://crm-base/src/main/java/com/crm/base/domain/result/PageResult.java)
|
|
|
|
|
- [CommonConstants.java](file://crm-base/src/main/java/com/crm/base/constant/CommonConstants.java)
|
|
|
|
|
- [FileController.java](file://crm-file/src/main/java/com/crm/file/controller/FileController.java)
|
|
|
|
|
- [FileApi.java](file://crm-file/src/main/java/com/crm/file/api/FileApi.java)
|
|
|
|
|
- [FileApiImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileApiImpl.java)
|
|
|
|
|
- [FileInfoService.java](file://crm-file/src/main/java/com/crm/file/service/IFileInfoService.java)
|
|
|
|
|
- [FileInfoServiceImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileInfoServiceImpl.java)
|
|
|
|
|
- [MultipartInitDTO.java](file://crm-file/src/main/java/com/crm/file/domain/dto/MultipartInitDTO.java)
|
|
|
|
|
- [UploadSession.java](file://crm-file/src/main/java/com/crm/file/domain/dto/UploadSession.java)
|
|
|
|
|
- [FileInfoDTO.java](file://crm-file/src/main/java/com/crm/file/domain/dto/FileInfoDTO.java)
|
|
|
|
|
- [FileDownloadDTO.java](file://crm-file/src/main/java/com/crm/file/domain/dto/FileDownloadDTO.java)
|
|
|
|
|
- [ThumbnailDTO.java](file://crm-file/src/main/java/com/crm/file/domain/dto/ThumbnailDTO.java)
|
|
|
|
|
- [ThumbnailPlaceholderService.java](file://crm-file/src/main/java/com/crm/file/service/ThumbnailPlaceholderService.java)
|
|
|
|
|
- [ThumbnailGenerationTask.java](file://crm-file/src/main/java/com/crm/file/task/ThumbnailGenerationTask.java)
|
|
|
|
|
- [FileConstants.java](file://crm-file/src/main/java/com/crm/file/constant/FileConstants.java)
|
|
|
|
|
- [MinioConfig.java](file://crm-file/src/main/java/com/crm/file/config/MinioConfig.java)
|
|
|
|
|
- [FileProperties.java](file://crm-file/src/main/java/com/crm/file/config/FileProperties.java)
|
|
|
|
|
</cite>
|
|
|
|
|
|
|
|
|
|
## 更新摘要
|
|
|
|
|
**变更内容**
|
|
|
|
|
- 新增缩略图获取API端点 `/api/file/thumbnail` 的详细文档
|
|
|
|
|
- 添加缩略图生成功能的完整说明
|
|
|
|
|
- 更新文件服务模块的API清单
|
|
|
|
|
- 补充缩略图相关的错误处理和状态码说明
|
|
|
|
|
|
|
|
|
|
## 目录
|
|
|
|
|
1. [简介](#简介)
|
|
|
|
|
2. [项目结构](#项目结构)
|
|
|
|
|
3. [核心组件](#核心组件)
|
|
|
|
|
4. [架构总览](#架构总览)
|
|
|
|
|
5. [详细组件分析](#详细组件分析)
|
|
|
|
|
6. [依赖关系分析](#依赖关系分析)
|
|
|
|
|
7. [性能考虑](#性能考虑)
|
|
|
|
|
8. [故障排查指南](#故障排查指南)
|
|
|
|
|
9. [结论](#结论)
|
|
|
|
|
10. [附录](#附录)
|
|
|
|
|
|
|
|
|
|
## 简介
|
|
|
|
|
本API参考文档面向前端开发者,系统化梳理认证鉴权、系统管理、文件上传下载等模块的RESTful接口规范。内容覆盖HTTP方法、URL路径、请求参数、响应格式、状态码与错误信息;明确认证方式(JWT)、多部分表单上传流程、权限控制要求;提供完整请求/响应示例、参数校验规则与业务约束,并附带接口测试用例与常见问题解答,帮助快速集成与排障。
|
|
|
|
|
|
|
|
|
|
## 项目结构
|
|
|
|
|
本项目采用多模块架构:
|
|
|
|
|
- crm-app:应用启动入口与全局配置
|
|
|
|
|
- crm-auth:认证鉴权与系统管理(用户、角色、菜单、部门)
|
|
|
|
|
- crm-base:通用基础能力(统一响应、异常处理、安全上下文、分页等)
|
|
|
|
|
- crm-file:文件服务(分片上传、断点续传、预览、下载、缩略图生成)
|
|
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
|
graph TB
|
|
|
|
|
subgraph "应用层"
|
|
|
|
|
APP["crm-app<br/>应用启动"]
|
|
|
|
|
end
|
|
|
|
|
subgraph "认证与系统管理"
|
|
|
|
|
AUTH["crm-auth<br/>认证/权限/系统管理"]
|
|
|
|
|
end
|
|
|
|
|
subgraph "基础能力"
|
|
|
|
|
BASE["crm-base<br/>通用组件/异常/结果封装"]
|
|
|
|
|
end
|
|
|
|
|
subgraph "文件服务"
|
|
|
|
|
FILE["crm-file<br/>文件上传/下载/预览/缩略图"]
|
|
|
|
|
end
|
|
|
|
|
APP --> AUTH
|
|
|
|
|
APP --> FILE
|
|
|
|
|
AUTH --> BASE
|
|
|
|
|
FILE --> BASE
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
图表来源
|
|
|
|
|
- [CrmAppApplication.java](file://crm-app/src/main/java/com/crm/app/CrmAppApplication.java)
|
|
|
|
|
- [application.yml](file://crm-app/src/main/resources/application.yml)
|
|
|
|
|
|
|
|
|
|
章节来源
|
|
|
|
|
- [CrmAppApplication.java](file://crm-app/src/main/java/com/crm/app/CrmAppApplication.java)
|
|
|
|
|
- [application.yml](file://crm-app/src/main/resources/application.yml)
|
|
|
|
|
|
|
|
|
|
## 核心组件
|
|
|
|
|
- 统一响应体 Result<T>:所有接口返回统一包装,包含状态码、消息与数据体
|
|
|
|
|
- 分页 PageResult<T>:标准分页数据结构
|
|
|
|
|
- 全局异常 GlobalExceptionHandlerAdvice:统一捕获业务异常、参数校验异常、权限异常等,输出标准化错误
|
|
|
|
|
- 安全上下文 LoginUser/AuthLoginUser:当前登录用户信息与权限范围
|
|
|
|
|
- TokenService:JWT签发、解析、刷新与黑名单管理
|
|
|
|
|
- JwtAuthenticationFilter:请求级JWT校验与上下文注入
|
|
|
|
|
- FileApi/FileApiImpl:文件上传下载、分片、预览、清理、缩略图生成等能力抽象与实现
|
|
|
|
|
- FileInfoService:文件元数据持久化与查询
|
|
|
|
|
- ThumbnailGenerationTask:异步缩略图生成任务
|
|
|
|
|
- ThumbnailPlaceholderService:动态生成文件类型占位图
|
|
|
|
|
|
|
|
|
|
章节来源
|
|
|
|
|
- [Result.java](file://crm-base/src/main/java/com/crm/base/domain/result/Result.java)
|
|
|
|
|
- [PageResult.java](file://crm-base/src/main/java/com/crm/base/domain/result/PageResult.java)
|
|
|
|
|
- [GlobalExceptionHandlerAdvice.java](file://crm-base/src/main/java/com/crm/base/advice/GlobalExceptionHandlerAdvice.java)
|
|
|
|
|
- [AuthLoginUser.java](file://crm-auth/src/main/java/com/crm/auth/security/AuthLoginUser.java)
|
|
|
|
|
- [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java)
|
|
|
|
|
- [JwtAuthenticationFilter.java](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java)
|
|
|
|
|
- [FileApi.java](file://crm-file/src/main/java/com/crm/file/api/FileApi.java)
|
|
|
|
|
- [FileApiImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileApiImpl.java)
|
|
|
|
|
- [FileInfoService.java](file://crm-file/src/main/java/com/crm/file/service/IFileInfoService.java)
|
|
|
|
|
- [ThumbnailGenerationTask.java](file://crm-file/src/main/java/com/crm/file/task/ThumbnailGenerationTask.java)
|
|
|
|
|
- [ThumbnailPlaceholderService.java](file://crm-file/src/main/java/com/crm/file/service/ThumbnailPlaceholderService.java)
|
|
|
|
|
|
|
|
|
|
## 架构总览
|
|
|
|
|
整体调用链路:客户端通过HTTP访问Controller,Controller调用Service完成业务逻辑,Service通过Mapper访问数据库或调用外部存储(如MinIO)。认证流程由Spring Security过滤器链拦截,基于JWT进行鉴权;权限控制通过注解与数据权限拦截器实现。缩略图功能采用异步生成+同步兜底的策略,确保用户体验。
|
|
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
|
sequenceDiagram
|
|
|
|
|
participant Client as "客户端"
|
|
|
|
|
participant AuthF as "JwtAuthenticationFilter"
|
|
|
|
|
participant Controller as "Controller"
|
|
|
|
|
participant Service as "Service"
|
|
|
|
|
participant Task as "ThumbnailGenerationTask"
|
|
|
|
|
participant DB as "数据库/对象存储"
|
|
|
|
|
Client->>AuthF : "携带Authorization : Bearer <token>"
|
|
|
|
|
AuthF->>AuthF : "校验签名/过期时间"
|
|
|
|
|
AuthF-->>Client : "未通过则返回401"
|
|
|
|
|
AuthF->>Controller : "通过则注入登录用户上下文"
|
|
|
|
|
Controller->>Service : "执行业务方法"
|
|
|
|
|
alt 缩略图请求
|
|
|
|
|
Service->>Task : "检查缩略图状态"
|
|
|
|
|
alt 需要生成
|
|
|
|
|
Task->>DB : "异步生成缩略图"
|
|
|
|
|
Service-->>Client : "返回占位图或等待"
|
|
|
|
|
else 已有缩略图
|
|
|
|
|
Service->>DB : "读取缩略图"
|
|
|
|
|
Service-->>Client : "返回缩略图"
|
|
|
|
|
end
|
|
|
|
|
else 其他操作
|
|
|
|
|
Service->>DB : "读写数据/文件元信息"
|
|
|
|
|
DB-->>Service : "返回结果"
|
|
|
|
|
Service-->>Controller : "业务结果"
|
|
|
|
|
Controller-->>Client : "统一Result包装响应"
|
|
|
|
|
end
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
图表来源
|
|
|
|
|
- [JwtAuthenticationFilter.java](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java)
|
|
|
|
|
- [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java)
|
|
|
|
|
- [GlobalExceptionHandlerAdvice.java](file://crm-base/src/main/java/com/crm/base/advice/GlobalExceptionHandlerAdvice.java)
|
|
|
|
|
- [ThumbnailGenerationTask.java](file://crm-file/src/main/java/com/crm/file/task/ThumbnailGenerationTask.java)
|
|
|
|
|
|
|
|
|
|
## 详细组件分析
|
|
|
|
|
|
|
|
|
|
### 认证与鉴权模块(crm-auth)
|
|
|
|
|
- 认证接口
|
|
|
|
|
- 登录:POST /auth/login
|
|
|
|
|
- 请求体:LoginParam(用户名、密码、验证码/第三方授权信息等)
|
|
|
|
|
- 响应:LoginResultDTO(access_token、refresh_token、过期时间、用户基本信息)
|
|
|
|
|
- 状态码:200成功;400参数校验失败;401账号不存在或密码错误;429频繁请求
|
|
|
|
|
- 刷新令牌:POST /auth/refresh
|
|
|
|
|
- 请求体:refresh_token
|
|
|
|
|
- 响应:新的access_token
|
|
|
|
|
- 状态码:200成功;401无效或过期
|
|
|
|
|
- 登出:POST /auth/logout
|
|
|
|
|
- 行为:将token加入黑名单或失效
|
|
|
|
|
- 状态码:200成功;401未登录
|
|
|
|
|
|
|
|
|
|
- 鉴权机制
|
|
|
|
|
- 认证方式:Bearer JWT
|
|
|
|
|
- 请求头:Authorization: Bearer <token>
|
|
|
|
|
- 过滤器:JwtAuthenticationFilter负责解析与校验
|
|
|
|
|
- 权限模型:基于角色的菜单/按钮权限,支持数据权限范围(部门/个人)
|
|
|
|
|
|
|
|
|
|
- 系统管理接口(需管理员权限)
|
|
|
|
|
- 用户管理:CRUD /system/user/*
|
|
|
|
|
- 角色管理:CRUD /system/role/*
|
|
|
|
|
- 菜单管理:CRUD /system/menu/*
|
|
|
|
|
- 部门管理:CRUD /system/dept/*
|
|
|
|
|
- 权限校验:使用注解或拦截器,结合DataScope实现数据隔离
|
|
|
|
|
|
|
|
|
|
- 统一响应与错误
|
|
|
|
|
- 响应体:Result<T>
|
|
|
|
|
- 错误码:ResultCodeEnum定义
|
|
|
|
|
- 异常处理:GlobalExceptionHandlerAdvice统一捕获并返回
|
|
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
|
classDiagram
|
|
|
|
|
class AuthController {
|
|
|
|
|
+login(param) Result~LoginResultDTO~
|
|
|
|
|
+refresh(token) Result~LoginResultDTO~
|
|
|
|
|
+logout() Result~void~
|
|
|
|
|
}
|
|
|
|
|
class IAuthService {
|
|
|
|
|
+login(param) LoginResultDTO
|
|
|
|
|
+refresh(refreshToken) LoginResultDTO
|
|
|
|
|
+logout(userId) void
|
|
|
|
|
}
|
|
|
|
|
class AuthUserServiceImpl {
|
|
|
|
|
+login(param) LoginResultDTO
|
|
|
|
|
+refresh(refreshToken) LoginResultDTO
|
|
|
|
|
+logout(userId) void
|
|
|
|
|
}
|
|
|
|
|
class TokenService {
|
|
|
|
|
+createToken(user) String
|
|
|
|
|
+parseToken(token) AuthLoginUser
|
|
|
|
|
+isExpired(token) boolean
|
|
|
|
|
+addToBlacklist(token) void
|
|
|
|
|
}
|
|
|
|
|
class JwtAuthenticationFilter {
|
|
|
|
|
+doFilter(request, response, chain) void
|
|
|
|
|
}
|
|
|
|
|
AuthController --> IAuthService : "调用"
|
|
|
|
|
IAuthService <|.. AuthUserServiceImpl : "实现"
|
|
|
|
|
AuthUserServiceImpl --> TokenService : "使用"
|
|
|
|
|
JwtAuthenticationFilter --> TokenService : "校验"
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
图表来源
|
|
|
|
|
- [AuthController.java](file://crm-auth/src/main/java/com/crm/auth/controller/AuthController.java)
|
|
|
|
|
- [IAuthService.java](file://crm-auth/src/main/java/com/crm/auth/service/IAuthService.java)
|
|
|
|
|
- [AuthUserServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/AuthUserServiceImpl.java)
|
|
|
|
|
- [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java)
|
|
|
|
|
- [JwtAuthenticationFilter.java](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java)
|
|
|
|
|
|
|
|
|
|
章节来源
|
|
|
|
|
- [AuthController.java](file://crm-auth/src/main/java/com/crm/auth/controller/AuthController.java)
|
|
|
|
|
- [IAuthService.java](file://crm-auth/src/main/java/com/crm/auth/service/IAuthService.java)
|
|
|
|
|
- [AuthUserServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/AuthUserServiceImpl.java)
|
|
|
|
|
- [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java)
|
|
|
|
|
- [JwtAuthenticationFilter.java](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java)
|
|
|
|
|
- [SecurityConfig.java](file://crm-auth/src/main/java/com/crm/auth/config/SecurityConfig.java)
|
|
|
|
|
- [PermissionConfig.java](file://crm-auth/src/main/java/com/crm/auth/config/PermissionConfig.java)
|
|
|
|
|
- [LoginParam.java](file://crm-auth/src/main/java/com/crm/auth/domain/param/LoginParam.java)
|
|
|
|
|
- [LoginResultDTO.java](file://crm-auth/src/main/java/com/crm/auth/domain/dto/LoginResultDTO.java)
|
|
|
|
|
- [UserInfoDTO.java](file://crm-auth/src/main/java/com/crm/auth/domain/dto/UserInfoDTO.java)
|
|
|
|
|
|
|
|
|
|
### 文件服务模块(crm-file)
|
|
|
|
|
- 文件上传(分片/断点续传)
|
|
|
|
|
- 初始化分片会话:POST /file/upload/init
|
|
|
|
|
- 请求体:MultipartInitDTO(文件名、大小、MD5、分片大小等)
|
|
|
|
|
- 响应:UploadSession(sessionId、分片策略)
|
|
|
|
|
- 状态码:200成功;400参数错误;413文件过大
|
|
|
|
|
- 上传分片:POST /file/upload/chunk
|
|
|
|
|
- Content-Type:multipart/form-data
|
|
|
|
|
- 表单字段:file(二进制)、chunkIndex(分片序号)、totalChunks(总分片数)、sessionId
|
|
|
|
|
- 响应:Result~boolean~(是否上传成功)
|
|
|
|
|
- 状态码:200成功;400参数缺失;404会话不存在;413单分片过大
|
|
|
|
|
- 合并分片:POST /file/upload/merge
|
|
|
|
|
- 请求体:{ sessionId, fileName, totalChunks, md5 }
|
|
|
|
|
- 响应:FileInfoDTO(文件ID、URL、大小、类型等)
|
|
|
|
|
- 状态码:200成功;400参数错误;409MD5不一致
|
|
|
|
|
|
|
|
|
|
- 文件下载与预览
|
|
|
|
|
- 下载:GET /file/download/{fileId}
|
|
|
|
|
- 响应:二进制流,Content-Disposition含文件名
|
|
|
|
|
- 状态码:200成功;404文件不存在;403无权限
|
|
|
|
|
- 预览:GET /file/preview/{fileId}
|
|
|
|
|
- 响应:HTML预览页面或重定向到在线预览地址
|
|
|
|
|
- 状态码:200成功;404文件不存在;403无权限
|
|
|
|
|
|
|
|
|
|
- **新增:缩略图获取**
|
|
|
|
|
- 缩略图:GET /api/file/thumbnail
|
|
|
|
|
- 请求参数:fileId(必填,文件ID)
|
|
|
|
|
- 响应:二进制图片流(image/jpeg或image/png)
|
|
|
|
|
- 状态码:200成功(已就绪或占位图);202接受(正在生成中)
|
|
|
|
|
- 缓存控制:根据缩略图状态自动设置Cache-Control头
|
|
|
|
|
- cacheable=true:max-age=86400(强缓存1天)
|
|
|
|
|
- cacheable=false:no-cache(不缓存)
|
|
|
|
|
- 功能特性:
|
|
|
|
|
- 智能状态检测:READY直接返回缩略图,PENDING触发异步生成
|
|
|
|
|
- 同步兜底:首次请求时尝试同步生成,避免长时间等待
|
|
|
|
|
- 占位图降级:UNSUPPORTED/FAILED/读取失败时返回动态占位图
|
|
|
|
|
- 分布式锁:防止并发重复生成,提高性能
|
|
|
|
|
|
|
|
|
|
- 文件元数据管理
|
|
|
|
|
- 列表:GET /file/list
|
|
|
|
|
- 查询参数:page、size、keyword、type、ownerId等
|
|
|
|
|
- 响应:PageResult~FileInfoDTO~
|
|
|
|
|
- 状态码:200成功;400参数错误
|
|
|
|
|
- 删除:DELETE /file/delete/{fileId}
|
|
|
|
|
- 响应:Result~void~
|
|
|
|
|
- 状态码:200成功;404文件不存在;403无权限
|
|
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
|
flowchart TD
|
|
|
|
|
Start(["开始"]) --> Init["初始化分片会话<br/>POST /file/upload/init"]
|
|
|
|
|
Init --> UploadChunk["循环上传分片<br/>POST /file/upload/chunk"]
|
|
|
|
|
UploadChunk --> Merge["合并分片<br/>POST /file/upload/merge"]
|
|
|
|
|
Merge --> Success{"合并成功?"}
|
|
|
|
|
Success --> |是| ReturnInfo["返回FileInfoDTO"]
|
|
|
|
|
Success --> |否| Error["返回错误码与提示"]
|
|
|
|
|
ReturnInfo --> End(["结束"])
|
|
|
|
|
Error --> End
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
图表来源
|
|
|
|
|
- [FileController.java](file://crm-file/src/main/java/com/crm/file/controller/FileController.java)
|
|
|
|
|
- [FileApi.java](file://crm-file/src/main/java/com/crm/file/api/FileApi.java)
|
|
|
|
|
- [FileApiImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileApiImpl.java)
|
|
|
|
|
- [FileInfoService.java](file://crm-file/src/main/java/com/crm/file/service/IFileInfoService.java)
|
|
|
|
|
- [FileInfoServiceImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileInfoServiceImpl.java)
|
|
|
|
|
- [MultipartInitDTO.java](file://crm-file/src/main/java/com/crm/file/domain/dto/MultipartInitDTO.java)
|
|
|
|
|
- [UploadSession.java](file://crm-file/src/main/java/com/crm/file/domain/dto/UploadSession.java)
|
|
|
|
|
- [FileInfoDTO.java](file://crm-file/src/main/java/com/crm/file/domain/dto/FileInfoDTO.java)
|
|
|
|
|
- [FileDownloadDTO.java](file://crm-file/src/main/java/com/crm/file/domain/dto/FileDownloadDTO.java)
|
|
|
|
|
|
|
|
|
|
章节来源
|
|
|
|
|
- [FileController.java](file://crm-file/src/main/java/com/crm/file/controller/FileController.java)
|
|
|
|
|
- [FileApi.java](file://crm-file/src/main/java/com/crm/file/api/FileApi.java)
|
|
|
|
|
- [FileApiImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileApiImpl.java)
|
|
|
|
|
- [FileInfoService.java](file://crm-file/src/main/java/com/crm/file/service/IFileInfoService.java)
|
|
|
|
|
- [FileInfoServiceImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileInfoServiceImpl.java)
|
|
|
|
|
- [MultipartInitDTO.java](file://crm-file/src/main/java/com/crm/file/domain/dto/MultipartInitDTO.java)
|
|
|
|
|
- [UploadSession.java](file://crm-file/src/main/java/com/crm/file/domain/dto/UploadSession.java)
|
|
|
|
|
- [FileInfoDTO.java](file://crm-file/src/main/java/com/crm/file/domain/dto/FileInfoDTO.java)
|
|
|
|
|
- [FileDownloadDTO.java](file://crm-file/src/main/java/com/crm/file/domain/dto/FileDownloadDTO.java)
|
|
|
|
|
- [ThumbnailDTO.java](file://crm-file/src/main/java/com/crm/file/domain/dto/ThumbnailDTO.java)
|
|
|
|
|
- [ThumbnailGenerationTask.java](file://crm-file/src/main/java/com/crm/file/task/ThumbnailGenerationTask.java)
|
|
|
|
|
- [ThumbnailPlaceholderService.java](file://crm-file/src/main/java/com/crm/file/service/ThumbnailPlaceholderService.java)
|
|
|
|
|
- [FileConstants.java](file://crm-file/src/main/java/com/crm/file/constant/FileConstants.java)
|
|
|
|
|
- [MinioConfig.java](file://crm-file/src/main/java/com/crm/file/config/MinioConfig.java)
|
|
|
|
|
- [FileProperties.java](file://crm-file/src/main/java/com/crm/file/config/FileProperties.java)
|
|
|
|
|
|
|
|
|
|
### 统一响应与异常处理(crm-base)
|
|
|
|
|
- 统一响应体 Result<T>
|
|
|
|
|
- 字段:code(状态码)、message(提示信息)、data(业务数据)
|
|
|
|
|
- 成功示例:{ "code": 200, "message": "操作成功", "data": {...} }
|
|
|
|
|
- 分页 PageResult<T>
|
|
|
|
|
- 字段:records(列表)、total(总数)、page(页码)、size(每页条数)
|
|
|
|
|
- 全局异常处理
|
|
|
|
|
- 业务异常:BusinessErrorException -> code=业务码,message=描述
|
|
|
|
|
- 参数校验:MissingParameterException -> code=400,message=缺参说明
|
|
|
|
|
- 权限异常:PermissionErrorException -> code=403,message=权限不足
|
|
|
|
|
- 资源不存在:ResourceNotExistException -> code=404,message=资源不存在
|
|
|
|
|
|
|
|
|
|
章节来源
|
|
|
|
|
- [Result.java](file://crm-base/src/main/java/com/crm/base/domain/result/Result.java)
|
|
|
|
|
- [PageResult.java](file://crm-base/src/main/java/com/crm/base/domain/result/PageResult.java)
|
|
|
|
|
- [GlobalExceptionHandlerAdvice.java](file://crm-base/src/main/java/com/crm/base/advice/GlobalExceptionHandlerAdvice.java)
|
|
|
|
|
- [ResultCodeEnum.java](file://crm-base/src/main/java/com/crm/base/domain/result/ResultCodeEnum.java)
|
|
|
|
|
- [CommonConstants.java](file://crm-base/src/main/java/com/crm/base/constant/CommonConstants.java)
|
|
|
|
|
|
|
|
|
|
## 依赖关系分析
|
|
|
|
|
- 控制器依赖服务接口,服务实现依赖数据访问与外部存储
|
|
|
|
|
- 认证过滤器依赖TokenService进行JWT校验
|
|
|
|
|
- 文件服务依赖MinIO配置与属性配置
|
|
|
|
|
- 缩略图功能依赖ThumbnailGenerationTask进行异步生成
|
|
|
|
|
- 统一异常处理贯穿各模块
|
|
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
|
graph LR
|
|
|
|
|
AC["AuthController"] --> ASvc["IAuthService"]
|
|
|
|
|
ASvc --> AImpl["AuthUserServiceImpl"]
|
|
|
|
|
AImpl --> Tok["TokenService"]
|
|
|
|
|
FC["FileController"] --> FApi["FileApi"]
|
|
|
|
|
FApi --> FImpl["FileApiImpl"]
|
|
|
|
|
FImpl --> FInfoSvc["IFileInfoService"]
|
|
|
|
|
FInfoSvc --> FInfoImpl["FileInfoServiceImpl"]
|
|
|
|
|
FImpl --> TGT["ThumbnailGenerationTask"]
|
|
|
|
|
Tok --> Sec["JwtAuthenticationFilter"]
|
|
|
|
|
FImpl --> Minio["MinIO(外部存储)"]
|
|
|
|
|
TGT --> Minio
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
图表来源
|
|
|
|
|
- [AuthController.java](file://crm-auth/src/main/java/com/crm/auth/controller/AuthController.java)
|
|
|
|
|
- [IAuthService.java](file://crm-auth/src/main/java/com/crm/auth/service/IAuthService.java)
|
|
|
|
|
- [AuthUserServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/AuthUserServiceImpl.java)
|
|
|
|
|
- [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java)
|
|
|
|
|
- [JwtAuthenticationFilter.java](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java)
|
|
|
|
|
- [FileController.java](file://crm-file/src/main/java/com/crm/file/controller/FileController.java)
|
|
|
|
|
- [FileApi.java](file://crm-file/src/main/java/com/crm/file/api/FileApi.java)
|
|
|
|
|
- [FileApiImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileApiImpl.java)
|
|
|
|
|
- [FileInfoService.java](file://crm-file/src/main/java/com/crm/file/service/IFileInfoService.java)
|
|
|
|
|
- [FileInfoServiceImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileInfoServiceImpl.java)
|
|
|
|
|
- [ThumbnailGenerationTask.java](file://crm-file/src/main/java/com/crm/file/task/ThumbnailGenerationTask.java)
|
|
|
|
|
- [MinioConfig.java](file://crm-file/src/main/java/com/crm/file/config/MinioConfig.java)
|
|
|
|
|
|
|
|
|
|
章节来源
|
|
|
|
|
- [AuthController.java](file://crm-auth/src/main/java/com/crm/auth/controller/AuthController.java)
|
|
|
|
|
- [FileController.java](file://crm-file/src/main/java/com/crm/file/controller/FileController.java)
|
|
|
|
|
- [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java)
|
|
|
|
|
- [JwtAuthenticationFilter.java](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java)
|
|
|
|
|
- [FileApiImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileApiImpl.java)
|
|
|
|
|
- [ThumbnailGenerationTask.java](file://crm-file/src/main/java/com/crm/file/task/ThumbnailGenerationTask.java)
|
|
|
|
|
- [MinioConfig.java](file://crm-file/src/main/java/com/crm/file/config/MinioConfig.java)
|
|
|
|
|
|
|
|
|
|
## 性能考虑
|
|
|
|
|
- 文件上传
|
|
|
|
|
- 合理设置分片大小(建议1MB~5MB),避免单次传输过大
|
|
|
|
|
- 并发上传分片时注意限流与重试退避
|
|
|
|
|
- 合并前校验MD5,减少重复计算
|
|
|
|
|
- 认证鉴权
|
|
|
|
|
- JWT本地校验,避免频繁访问Redis;必要时缓存用户权限
|
|
|
|
|
- 刷新令牌策略应限制频率,防止滥用
|
|
|
|
|
- 分页查询
|
|
|
|
|
- 使用合理的page/size,避免大偏移量查询
|
|
|
|
|
- 对常用查询条件建立索引
|
|
|
|
|
- **缩略图优化**
|
|
|
|
|
- 异步生成:上传完成后后台异步生成,不阻塞主流程
|
|
|
|
|
- 分布式锁:防止并发重复生成,提高系统稳定性
|
|
|
|
|
- 智能缓存:根据状态设置合适的缓存策略,减少重复请求
|
|
|
|
|
- 占位图降级:生成失败或类型不支持时快速返回占位图
|
|
|
|
|
- 同步兜底:首次请求时尝试同步生成,提升用户体验
|
|
|
|
|
|
|
|
|
|
## 故障排查指南
|
|
|
|
|
- 401 未认证
|
|
|
|
|
- 检查Authorization头是否正确携带Bearer token
|
|
|
|
|
- 确认token未过期且未被拉黑
|
|
|
|
|
- 403 权限不足
|
|
|
|
|
- 检查当前用户角色与菜单权限
|
|
|
|
|
- 确认数据权限范围是否包含目标数据
|
|
|
|
|
- 404 资源不存在
|
|
|
|
|
- 核对文件ID或用户ID是否存在
|
|
|
|
|
- 413 文件过大
|
|
|
|
|
- 调整服务端最大文件大小配置
|
|
|
|
|
- 400 参数校验失败
|
|
|
|
|
- 检查必填字段、格式与长度限制
|
|
|
|
|
- **缩略图相关问题**
|
|
|
|
|
- 202 Accepted:缩略图正在生成中,稍后重试即可
|
|
|
|
|
- 占位图显示:文件类型不支持或生成失败,属于正常降级
|
|
|
|
|
- 缓存问题:检查Cache-Control头设置是否符合预期
|
|
|
|
|
- 生成超时:检查缩略图生成任务的执行时间和重试配置
|
|
|
|
|
|
|
|
|
|
章节来源
|
|
|
|
|
- [GlobalExceptionHandlerAdvice.java](file://crm-base/src/main/java/com/crm/base/advice/GlobalExceptionHandlerAdvice.java)
|
|
|
|
|
- [ResultCodeEnum.java](file://crm-base/src/main/java/com/crm/base/domain/result/ResultCodeEnum.java)
|
|
|
|
|
- [SecurityConfig.java](file://crm-auth/src/main/java/com/crm/auth/config/SecurityConfig.java)
|
|
|
|
|
- [PermissionConfig.java](file://crm-auth/src/main/java/com/crm/auth/config/PermissionConfig.java)
|
|
|
|
|
- [FileConstants.java](file://crm-file/src/main/java/com/crm/file/constant/FileConstants.java)
|
|
|
|
|
|
|
|
|
|
## 结论
|
|
|
|
|
本文档从架构到接口细节全面梳理了CRM后端的认证鉴权、系统管理与文件服务三大模块的API规范。通过统一的响应与异常处理、严格的权限控制与健壮的分片上传机制,为前端提供了稳定可靠的集成基础。**新增的缩略图功能**进一步增强了文件处理能力,支持多种文件类型的缩略图生成,具备智能缓存控制和完善的降级机制。建议在前端集成时严格遵循参数校验与错误处理规范,并结合测试用例验证关键流程。
|
|
|
|
|
|
|
|
|
|
## 附录
|
|
|
|
|
|
|
|
|
|
### 接口清单与示例
|
|
|
|
|
- 认证接口
|
|
|
|
|
- POST /auth/login
|
|
|
|
|
- 请求体:LoginParam(用户名、密码等)
|
|
|
|
|
- 响应:Result~LoginResultDTO~
|
|
|
|
|
- 示例响应:{ "code": 200, "message": "登录成功", "data": { "accessToken": "...", "refreshToken": "...", "expiresIn": 7200, "userInfo": {...} } }
|
|
|
|
|
- POST /auth/refresh
|
|
|
|
|
- 请求体:{ "refreshToken": "..." }
|
|
|
|
|
- 响应:Result~LoginResultDTO~
|
|
|
|
|
- POST /auth/logout
|
|
|
|
|
- 响应:Result~void~
|
|
|
|
|
|
|
|
|
|
- 文件接口
|
|
|
|
|
- POST /file/upload/init
|
|
|
|
|
- 请求体:MultipartInitDTO(fileName、fileSize、md5、chunkSize)
|
|
|
|
|
- 响应:Result~UploadSession~
|
|
|
|
|
- POST /file/upload/chunk
|
|
|
|
|
- Content-Type:multipart/form-data
|
|
|
|
|
- 表单字段:file、chunkIndex、totalChunks、sessionId
|
|
|
|
|
- 响应:Result~boolean~
|
|
|
|
|
- POST /file/upload/merge
|
|
|
|
|
- 请求体:{ "sessionId": "...", "fileName": "...", "totalChunks": 10, "md5": "..." }
|
|
|
|
|
- 响应:Result~FileInfoDTO~
|
|
|
|
|
- GET /file/download/{fileId}
|
|
|
|
|
- 响应:二进制流
|
|
|
|
|
- GET /file/preview/{fileId}
|
|
|
|
|
- 响应:HTML预览或重定向
|
|
|
|
|
- **GET /api/file/thumbnail?fileId={fileId}**
|
|
|
|
|
- 请求参数:fileId(必填)
|
|
|
|
|
- 响应:二进制图片流(image/jpeg或image/png)
|
|
|
|
|
- 状态码:200成功;202接受(生成中)
|
|
|
|
|
- 缓存头:Cache-Control根据状态自动设置
|
|
|
|
|
- GET /file/list?page=1&size=10&keyword=...
|
|
|
|
|
- 响应:Result~PageResult~FileInfoDTO~
|
|
|
|
|
|
|
|
|
|
- 系统管理接口(需管理员权限)
|
|
|
|
|
- 用户/角色/菜单/部门CRUD接口,路径以/system/开头
|
|
|
|
|
- 权限要求:具备对应菜单与数据权限
|
|
|
|
|
|
|
|
|
|
### 参数验证规则与业务约束
|
|
|
|
|
- 登录
|
|
|
|
|
- 用户名:非空,长度1~50
|
|
|
|
|
- 密码:非空,长度6~32
|
|
|
|
|
- 验证码:可选,按配置启用
|
|
|
|
|
- 文件上传
|
|
|
|
|
- 文件名:非空,长度1~255
|
|
|
|
|
- 文件大小:不超过配置上限
|
|
|
|
|
- MD5:必填,用于完整性校验
|
|
|
|
|
- 分片序号:从0开始连续,不得重复
|
|
|
|
|
- 分页查询
|
|
|
|
|
- page>=1,size<=100(可配置)
|
|
|
|
|
- keyword:模糊匹配,长度<=100
|
|
|
|
|
- **缩略图请求**
|
|
|
|
|
- fileId:必填,必须是有效的文件ID
|
|
|
|
|
- 支持的文件类型:图片、PDF、Office文档等(取决于渲染器配置)
|
|
|
|
|
- 缓存策略:自动生成,无需手动控制
|
|
|
|
|
|
|
|
|
|
### 接口测试用例(示例)
|
|
|
|
|
- 登录成功
|
|
|
|
|
- 输入:{ "username": "admin", "password": "123456" }
|
|
|
|
|
- 期望:code=200,data.accessToken存在
|
|
|
|
|
- 登录失败(密码错误)
|
|
|
|
|
- 输入:{ "username": "admin", "password": "wrong" }
|
|
|
|
|
- 期望:code!=200,message提示错误
|
|
|
|
|
- 分片上传
|
|
|
|
|
- 步骤:init -> 上传N个chunk -> merge
|
|
|
|
|
- 期望:merge返回FileInfoDTO,download/preview可用
|
|
|
|
|
- 权限不足
|
|
|
|
|
- 步骤:使用低权限token访问/system/role/*
|
|
|
|
|
- 期望:code=403,message提示权限不足
|
|
|
|
|
- **缩略图测试**
|
|
|
|
|
- 已就绪文件:GET /api/file/thumbnail?fileId={ready_file_id}
|
|
|
|
|
- 期望:200状态码,返回image/jpeg缩略图,Cache-Control: max-age=86400
|
|
|
|
|
- 生成中文件:GET /api/file/thumbnail?fileId={pending_file_id}
|
|
|
|
|
- 期望:可能返回202状态码,Cache-Control: no-cache,稍后重试
|
|
|
|
|
- 不支持类型:GET /api/file/thumbnail?fileId={unsupported_file_id}
|
|
|
|
|
- 期望:200状态码,返回image/png占位图,Cache-Control: no-cache
|
|
|
|
|
|
|
|
|
|
### 常见问题解答
|
|
|
|
|
- Q:如何获取并保存token?
|
|
|
|
|
- A:登录成功后从响应data中获取accessToken与refreshToken,保存在本地存储并在后续请求头中携带
|
|
|
|
|
- Q:token过期如何处理?
|
|
|
|
|
- A:优先使用refreshToken调用刷新接口;若失败则引导重新登录
|
|
|
|
|
- Q:分片上传失败如何恢复?
|
|
|
|
|
- A:记录已上传的分片序号,合并前校验MD5,缺失分片继续上传
|
|
|
|
|
- Q:如何限制文件类型与大小?
|
|
|
|
|
- A:在FileProperties中配置允许的类型与大小上限,并在前端做二次校验
|
|
|
|
|
- **Q:缩略图加载慢怎么办?**
|
|
|
|
|
- A:首次请求会触发异步生成,后续请求会命中缓存;如果持续慢,检查缩略图生成任务的执行情况和MinIO性能
|
|
|
|
|
- **Q:为什么有些文件没有缩略图?**
|
|
|
|
|
- A:可能是文件类型不支持,或者缩略图生成失败;系统会自动返回占位图作为降级处理
|
|
|
|
|
- **Q:如何优化缩略图的缓存效果?**
|
|
|
|
|
- A:系统已自动设置合适的Cache-Control头;对于已就绪的缩略图会设置1天的强缓存,对于生成中的文件使用no-cache
|