docs(spec/plan): FileBizType 改为工具类(非枚举),bizType 自由字符串
设计调整原因:上传服务是统一基础设施,强制枚举会要求「加新模块 = 改框架代码」。 改为 final class + normalize() 格式校验,业务模块自定 bizType 字符串即可。 - spec §4.2: 整个 FileBizType 章节重写(工具类 + 格式约束 + 设计意图) - spec flow 5/11: 校验从 values() 改为 normalize() - spec API 表 / 代码结构表 / 订阅方示例 同步更新 - plan Step 1.2/1.4 / 状态表 / 流程校验 / 发布器签名 同步更新
This commit is contained in:
@@ -24,7 +24,7 @@
|
||||
| 路径 | 操作 | 说明 |
|
||||
|------|------|------|
|
||||
| `rui-common/rui-common-core/.../constants/MqTopicConstants.java` | Create | MQ topic 常量 |
|
||||
| `rui-common/rui-common-core/.../enums/FileBizType.java` | Create | 文件业务类型枚举 |
|
||||
| `rui-common/rui-common-core/.../enums/FileBizType.java` | Modify | 工具类(非枚举),含 normalize / uploadType / deletedType |
|
||||
| `rui-service/rui-service-storage/pom.xml` | Create | 新模块 |
|
||||
| `rui-service/rui-service-storage/src/main/java/com/rui/service/storage/StorageApplication.java` | Create | 启动类 |
|
||||
| `rui-service/rui-service-storage/src/main/java/com/rui/service/storage/controller/SysFileController.java` | Create | 上传/查询/删除 |
|
||||
@@ -64,7 +64,7 @@
|
||||
|
||||
**Files:**
|
||||
- Create: `rui-common/rui-common-core/src/main/java/com/rui/common/core/constants/MqTopicConstants.java`
|
||||
- Create: `rui-common/rui-common-core/src/main/java/com/rui/common/core/enums/FileBizType.java`
|
||||
- Modify: `rui-common/rui-common-core/src/main/java/com/rui/common/core/enums/FileBizType.java`(已从 enum 改为 final class,bizType 不维护中央清单)
|
||||
- Reference style: `CacheConstants.java`(沿用 private ctor + Javadoc 写明写入方/使用方)
|
||||
|
||||
- [ ] **Step 1.1:** 创建 `MqTopicConstants`
|
||||
@@ -76,11 +76,11 @@
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 1.2:** 创建 `FileBizType` 枚举(4 个值 + `uploadType()` / `deletedType()` 方法)
|
||||
- [x] **Step 1.2:** ~~创建 `FileBizType` 枚举~~ 改为 final class 工具类(`normalize()` / `uploadType()` / `deletedType()`),**不维护业务类型清单**
|
||||
|
||||
- [ ] **Step 1.3:** 编译 `mvn -pl rui-common/rui-common-core compile` 通过
|
||||
|
||||
- [ ] **Step 1.4:** 提交 `feat(core): 新增 MqTopicConstants 和 FileBizType`
|
||||
- [x] **Step 1.4:** 提交 `feat(core): 新增 MqTopicConstants 和 FileBizType`(后于本计划重构成工具类)
|
||||
|
||||
---
|
||||
|
||||
@@ -270,7 +270,7 @@
|
||||
- [ ] **Step 11.3:** `SysFileController`:
|
||||
- 类级 `@AutoPermission("sys:file:upload")`
|
||||
- `@PostMapping("/upload")` → `upload(file, bizType, storage?)`
|
||||
- 校验 `bizType` ∈ `FileBizType.values()`
|
||||
- 校验 `bizType` 格式(`FileBizType.normalize()`);不再校验「是否已注册」
|
||||
- 加载 `FileProperties.bizTypes[bizType]`,校验大小/扩展名
|
||||
- 调 `FileStorageRouter` 选实现 → `upload`
|
||||
- 算 sha256(`DigestUtils.sha256Hex`)
|
||||
@@ -300,7 +300,7 @@
|
||||
- [ ] **Step 12.2:** `UploadEventPublisher`:
|
||||
- `@Component @RequiredArgsConstructor`
|
||||
- 注入 `MqClient`
|
||||
- `publish(FileBizType bizType, SysFile entity, Long uploaderId, Long tenantId, JSONObject extra)`
|
||||
- `publish(String bizType, SysFile entity, String url, Long uploaderId, Long tenantId, JSONObject extra)` (bizType 是已规范化的字符串,type = FileBizType.uploadType(bizType))
|
||||
- 内部 `mqClient.publish(MqProvider.REDIS, MqTopicConstants.ON_UPLOAD, payload)`
|
||||
- 失败只 `log.error`,不抛(避免上传回滚)
|
||||
|
||||
@@ -367,7 +367,7 @@
|
||||
| 规范要求 | 对应任务 | 状态 |
|
||||
|---------|---------|------|
|
||||
| 公共常量集中 (MqTopicConstants) | Task 1 | ☐ |
|
||||
| 业务枚举集中 (FileBizType) | Task 1 | ☐ |
|
||||
| 业务类型工具类 (FileBizType,非枚举) | Task 1 | ☑ |
|
||||
| 数据库继承 BaseEntity | Task 10 | ☐ |
|
||||
| Strategy 模式可插拔 | Tasks 5-9 | ☐ |
|
||||
| 内置 @AutoPermission 鉴权 | Task 11 | ☐ |
|
||||
|
||||
@@ -82,7 +82,7 @@
|
||||
|
||||
| 模块 | 角色 | 依赖 |
|
||||
|------|------|------|
|
||||
| `rui-common-core` | 提供 `MqTopicConstants` + `FileBizType` 枚举 + `Result` | 无 |
|
||||
| `rui-common-core` | 提供 `MqTopicConstants` + `FileBizType` 工具类 + `Result` | 无 |
|
||||
| `rui-service-storage` | 上传服务本体(Controller + Strategy + Service) | web/mybatis/redis/mq/security |
|
||||
| `rui-service-system` 等 | 订阅方,实现 `MqConsumer` 处理事件 | mq-redis(已通过 starter 引入) |
|
||||
| `rui-service-starter` | 聚合启动器,引入 storage 依赖 | 现有 + storage |
|
||||
@@ -100,7 +100,7 @@ CREATE TABLE sys_file (
|
||||
original_name VARCHAR(200) NOT NULL COMMENT '原始文件名',
|
||||
url VARCHAR(1000) NOT NULL COMMENT '可访问URL',
|
||||
storage_type VARCHAR(20) NOT NULL COMMENT '存储后端 ALIYUN/TENCENT/LOCAL',
|
||||
biz_type VARCHAR(50) NOT NULL COMMENT '业务类型 (见 FileBizType 枚举)',
|
||||
biz_type VARCHAR(50) NOT NULL COMMENT '业务类型 (大写蛇形字符串,业务模块自定)',
|
||||
biz_id VARCHAR(100) DEFAULT NULL COMMENT '业务关联ID (可选)',
|
||||
size BIGINT NOT NULL COMMENT '字节',
|
||||
content_type VARCHAR(100) DEFAULT NULL COMMENT 'MIME 类型',
|
||||
@@ -122,32 +122,44 @@ CREATE TABLE sys_file (
|
||||
|
||||
继承 `BaseEntity`(自动填充 `created_by/created_at/updated_by/updated_at/tenant_id/deleted`),最终 DDL 可省略由框架维护的列定义。
|
||||
|
||||
### 4.2 枚举 `FileBizType`(位于 `rui-common-core`)
|
||||
### 4.2 工具类 `FileBizType`(位于 `rui-common-core`,**不是枚举**)
|
||||
|
||||
`bizType` **不维护中央清单**,新业务模块加新字符串即可,框架不强制注册。
|
||||
|
||||
理由:上传服务是「统一基础设施」,应当对业务透明。强制枚举会让「加个新模块」变成「改框架代码 + 重新发版」,违背开闭原则。
|
||||
|
||||
```java
|
||||
package com.rui.common.core.enums;
|
||||
|
||||
/**
|
||||
* 文件业务类型枚举。
|
||||
* <p>所有 bizType 字符串必须在此枚举中定义,否则上传接口返回 400。</p>
|
||||
*
|
||||
* <p>事件 type 字段 = {@code bizType.name() + "_UPLOAD"}(上传) / {@code "_DELETED"}(删除)</p>
|
||||
* 文件业务类型工具类(已不再是枚举)。
|
||||
* <p>上传接口接收任意 bizType 字符串,框架只做格式校验,不维护"已注册"清单。</p>
|
||||
*/
|
||||
public enum FileBizType {
|
||||
/** 通用文件(无业务白名单限制) */
|
||||
COMMON,
|
||||
/** 第三方应用证书(pem/crt/key/p12,限 5MB) */
|
||||
SYS_APP_CERT,
|
||||
/** 用户头像(jpg/png/webp,限 2MB) */
|
||||
USER_AVATAR,
|
||||
/** CMS 轮播图(jpg/png/webp/gif,限 5MB) */
|
||||
CMS_BANNER;
|
||||
public final class FileBizType {
|
||||
|
||||
public String uploadType() { return name() + "_UPLOAD"; }
|
||||
public String deletedType() { return name() + "_DELETED"; }
|
||||
private static final Pattern PATTERN = Pattern.compile("^[A-Z][A-Z0-9_]*$");
|
||||
private static final int MAX_LENGTH = 50;
|
||||
|
||||
private FileBizType() {}
|
||||
|
||||
/** trim / 大写 / - 转 _ / 格式校验;非法时抛 BizException */
|
||||
public static String normalize(String bizType) { /* ... */ }
|
||||
|
||||
/** 订阅方按此过滤:{@code "SYS_APP_CERT_UPLOAD"} 等 */
|
||||
public static String uploadType(String bizType) { return normalize(bizType) + "_UPLOAD"; }
|
||||
public static String deletedType(String bizType) { return normalize(bizType) + "_DELETED"; }
|
||||
}
|
||||
```
|
||||
|
||||
**bizType 格式约束**(normalize 强制):
|
||||
- 字母/数字开头,仅大写字母 + 数字 + 下划线
|
||||
- 长度 ≤ 50(与 `sys_file.biz_type VARCHAR(50)` 对齐)
|
||||
- 例:`SYS_APP_CERT` / `USER_AVATAR` / `MY_NEW_BIZ` 都可
|
||||
|
||||
**具体业务的大小 / 扩展名限制**走 yml 配置 `rui.file.biz-types.{BIZ_TYPE}`,缺失则走默认值;不属于「注册」。
|
||||
|
||||
> ⚠️ 这是 2026-06-07 第二次设计调整:原计划是 enum + 预定义 4 个值,后改为工具类 + 任意字符串。
|
||||
|
||||
---
|
||||
|
||||
## 5. 关键流程设计
|
||||
@@ -159,7 +171,7 @@ public enum FileBizType {
|
||||
2. SysFileController.upload() 入口
|
||||
3. @AutoPermission 校验 sys:file:upload
|
||||
4. SecurityUtils 取 uploaderId/tenantId
|
||||
5. 校验 bizType ∈ FileBizType.values() 否则 400
|
||||
5. 校验 bizType 格式 (normalize) 否则 400;不再校验「是否在已注册清单」
|
||||
6. 加载 rui.file.biz-types[bizType] 配置
|
||||
├─ 校验 file.size ≤ maxSize
|
||||
└─ 校验 file.ext ∈ allowedExtensions
|
||||
@@ -170,7 +182,7 @@ public enum FileBizType {
|
||||
9. 算 sha256(同步,10MB 以内可接受)
|
||||
10. sys_file 落库 (INSERT)
|
||||
11. mqClient.publish(MqProvider.REDIS, MqTopicConstants.ON_UPLOAD,
|
||||
EventPayload.of(FileBizType.SYS_APP_CERT, file, uploader, tenant))
|
||||
EventPayload.of(bizType, file, uploader, tenant) // bizType 即上传时传的字符串
|
||||
12. return Result.ok(SysFileUploadVO)
|
||||
```
|
||||
|
||||
@@ -219,7 +231,7 @@ public enum FileBizType {
|
||||
| 路径 | 说明 |
|
||||
|------|------|
|
||||
| `rui-common/rui-common-core/.../constants/MqTopicConstants.java` | 跨服务 MQ topic 常量 |
|
||||
| `rui-common/rui-common-core/.../enums/FileBizType.java` | 文件业务类型枚举 |
|
||||
| `rui-common/rui-common-core/.../enums/FileBizType.java` | 文件业务类型工具类(非枚举;normalize / uploadType / deletedType) |
|
||||
| `rui-service/rui-service-storage/pom.xml` | 新模块 |
|
||||
| `rui-service/rui-service-storage/src/main/java/com/rui/service/storage/StorageApplication.java` | 启动类 |
|
||||
| `rui-service/rui-service-storage/.../controller/SysFileController.java` | 上传/查询/删除接口 |
|
||||
@@ -262,7 +274,7 @@ Content-Type: multipart/form-data
|
||||
Authorization: Bearer <JWT> # 网关已注入,storage 服务再校验
|
||||
|
||||
file : MultipartFile (必填)
|
||||
bizType : string (form) (必填,FileBizType 枚举值)
|
||||
bizType : string (form) (必填;大写蛇形字符串,业务模块自定,框架不维护清单)
|
||||
storage : string (query) (可选,aliyun/tencent/local,不传走 active)
|
||||
|
||||
Response (Result<SysFileUploadVO>):
|
||||
@@ -374,7 +386,7 @@ public class SysAppCertUploadConsumer implements MqConsumer {
|
||||
|
||||
@Override
|
||||
public void onMessage(String messageId, String topic, JSONObject data) {
|
||||
if (!FileBizType.SYS_APP_CERT.uploadType().equals(data.getString("type"))) return;
|
||||
if (!FileBizType.uploadType("SYS_APP_CERT").equals(data.getString("type"))) return;
|
||||
String url = data.getString("url");
|
||||
JSONObject extra = data.getJSONObject("extra");
|
||||
String appId = extra == null ? null : extra.getString("appId");
|
||||
|
||||
Reference in New Issue
Block a user