加群聯系作者vx:xiaoda0423
倉庫地址:https://webvueblog.github.io/JavaPlusDoc/
https://1024bat.cn/
一、user
?表(用戶表)
sql
復制編輯
create table?if?not exists user
(id ? ? ? ? ? bigint auto_increment comment?'id'?primary key,userAccount ?varchar(256) ? ? ? ? ? ? ? ? ? ? ? ? ? not null comment?'賬號',userPassword varchar(512) ? ? ? ? ? ? ? ? ? ? ? ? ? not null comment?'密碼',userName ? ? varchar(256) ? ? ? ? ? ? ? ? ? ? ? ? ? null comment?'用戶昵稱',userAvatar ? varchar(1024) ? ? ? ? ? ? ? ? ? ? ? ? ?null comment?'用戶頭像',userProfile ?varchar(512) ? ? ? ? ? ? ? ? ? ? ? ? ? null comment?'用戶簡介',userRole ? ? varchar(256) default?'user'? ? ? ? ? ? not null comment?'用戶角色:user/admin/ban',createTime ? datetime ? ? default CURRENT_TIMESTAMP not null comment?'創建時間',updateTime ? datetime ? ? default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment?'更新時間',isDelete ? ? tinyint ? ? ?default 0 ? ? ? ? ? ? ? ? not null comment?'是否刪除',index idx_userAccount (userAccount)
) comment?'用戶'?collate = utf8mb4_unicode_ci;
列名 | 類型 | 約束 / 默認值 | 說明 |
---|---|---|---|
id | bigint | auto_increment ,主鍵 | 自增唯一 ID |
userAccount | varchar(256) | NOT NULL | 登錄賬號(如手機號、郵箱或自定義賬號) |
userPassword | varchar(512) | NOT NULL | 存儲密碼(建議儲存 bcrypt 等加密后的結果) |
userName | varchar(256) | NULL | 用戶昵稱 |
userAvatar | varchar(1024) | NULL | 用戶頭像 URL |
userProfile | varchar(512) | NULL | 個人簡介 |
userRole | varchar(256) | NOT NULL DEFAULT 'user' | 角色: |
createTime | datetime | NOT NULL DEFAULT CURRENT_TIMESTAMP | 記錄創建時間 |
updateTime | datetime | NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP | 最后更新時間 |
isDelete | tinyint | NOT NULL DEFAULT 0 | 軟刪除標志: |
索引 | idx_userAccount (userAccount) | 登錄查詢或唯一校驗可加唯一索引 | |
表注釋 | collate = utf8mb4_unicode_ci | 支持 4 字節 UTF-8(表情等) |
二、chat
?表(圖表/會話信息表)
sql
復制編輯
create table?if?not exists chat
(id ? ? ? ? ? bigint auto_increment comment?'id'?primary key,goal ? ? ? ? text ? ? ? ? ? ? ? ? ? ? ? ? ? null comment?'分析目標',`name` ? ? ? varchar(128) ? ? ? ? ? ? ? ? ? null comment?'圖表名稱',chartData ? ?text ? ? ? ? ? ? ? ? ? ? ? ? ? null comment?'圖表數據',chartType ? ?varchar(128) ? ? ? ? ? ? ? ? ? null comment?'圖表類型',userId ? ? ? bigint ? ? ? ? ? ? ? ? ? ? ? ? null comment?'用戶id',genChart ? ? text ? ? ? ? ? ? ? ? ? ? ? ? ? null comment?'生成的圖表',genResult ? ?text ? ? ? ? ? ? ? ? ? ? ? ? ? null comment?'生成的數據',status ? ? ? varchar(128) ? ?not null ?default?'wait'?comment?'wait,running,succeed,failed',execMessage ?text ? ? ? ? ? ?null comment?'執行信息',createTime ? datetime ? ? default CURRENT_TIMESTAMP not null comment?'創建時間',updateTime ? datetime ? ? default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment?'更新時間',isDelete ? ? tinyint ? ? ?default 0 ? ? ? ? ? ? ? ? not null comment?'是否刪除'
) comment?'圖表信息表'?collate = utf8mb4_unicode_ci;
列名 | 類型 | 約束 / 默認值 | 說明 |
---|---|---|---|
id | bigint | auto_increment ,主鍵 | 自增唯一 ID |
goal | text | NULL | 分析目標,通常是用戶輸入的需求文本 |
name | varchar(128) | NULL | 圖表/會話名稱 |
chartData | text | NULL | 輸入的原始圖表數據(JSON 等) |
chartType | varchar(128) | NULL | 圖表類型,如? |
userId | bigint | NULL | 關聯? |
genChart | text | NULL | AI 或后端生成的圖表(如圖表配置 JSON) |
genResult | text | NULL | AI 或后端生成的結果數據 |
status | varchar(128) | NOT NULL DEFAULT 'wait' | 任務狀態: |
execMessage | text | NULL | 執行日志或錯誤信息 |
createTime | datetime | NOT NULL DEFAULT CURRENT_TIMESTAMP | 記錄創建時間 |
updateTime | datetime | NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP | 最后更新時間 |
isDelete | tinyint | NOT NULL DEFAULT 0 | 軟刪除標志: |
表注釋 | collate = utf8mb4_unicode_ci | 支持 4 字節 UTF-8 |
三、建議 & 說明
外鍵約束
建議在?
chat.userId
?上增加外鍵:alter table chatadd constraint fk_chat_userforeign key(userId) references user(id);
唯一索引
如果?
userAccount
?需要唯一,改成?unique key
。
狀態字段
status
?建議改為?enum('wait','running','succeed','failed')
,以節省存儲并保證值域。
分表 / 分庫
若?
chat
?表數據量巨大,可考慮按時間或用戶分表。
軟刪除
isDelete
?字段已支持軟刪除,查詢時請加?where isDelete=0
。
字符集
utf8mb4_unicode_ci
?可存儲 Emoji 等 4 字節字符,適合昵稱、頭像 URL 等。
mongo,cassandra,elasticsearch,redis,clickhouse,mysql,postgresql集群,擴展,多節點分布
1. MongoDB
復制集(Replica Set)
一主多從(Primary/Secondary),自動故障切換。
從節點可做讀分擔讀流量。
分片集群(Sharded Cluster)
數據依據 shard key 切分到多個分片(Shard);每個分片內部為復制集。
Config Servers?存儲元數據;Mongos?負責路由查詢。
擴展
增加分片實現水平擴展;增添 Secondary 提升讀可用。
Online Resharding(4.4+)支持在線調整分片鍵。
部署建議:至少 3 個 Config Server,偶數分片時用仲裁節點避免 split-brain。
2. Cassandra
對等節點(Peer-to-Peer)
每個節點都相同,無主從。
基于?Gossip 協議?交換拓撲,一致性哈希環?分配數據。
復制因子(RF) & 一致性級別
RF 控制每條數據復制到多少節點;讀寫可配置 ONE/QUORUM/ALL 等。
擴展
橫向自動擴容:加入新節點,數據自動重分布(Rebalancing)。
部署建議:跨機房多機架部署,保證 RF 的多可用區冗余。
3. Elasticsearch
節點類型:Master、Data、Ingest、Coordinating(Client)
索引與分片
每個索引可設置 N 個 Primary Shard + M 個 Replica Shard。
Primary/Replica 分布在不同 Data 節點。
集群協調
Master 負責元數據管理;Coordinating 節點負責聚合請求。
擴展
增加 Data 節點后,可通過?
cluster.routing.allocation
?平衡分片。增加 Master 候選節點增強穩定性(奇數個,>=3)。
部署建議:Master 節點隔離,Client 節點對外負載均衡。
4. Redis
主從復制 + 哨兵(Sentinel)
一主多從,Sentinel 監控故障并自動 failover。
集群模式(Cluster)
數據分為 16384 個槽(hash slots),分布到不同主節點;每個主節點可有從節點。
客戶端自動感知重定向(MOVED、ASK)。
擴展
增加主節點提升寫吞吐;增加從節點提升讀吞吐。
部署建議:至少 3 個 Sentinel,保證 Quorum;Cluster 模式至少 3 主 3 從。
5. ClickHouse
Shard + Replica
每個表在多個分片(Shard)上水平分區;每個分片可有多個副本(Replica)。
Table Engines
ReplicatedMergeTree
?系列支持復制和副本間自動同步。
擴展
增加分片:編輯集群配置文件,重新部署新分片節點并重平衡。
部署建議:使用 ZooKeeper 管理分布式元數據、跨機房部署副本。
6. MySQL
主從復制(Replication)
一主多從,基于 binlog。讀寫分離提升讀性能。
組復制 / InnoDB Cluster
Group Replication 實現多主(Multi-Primary)或單主模式,自動仲裁。
分庫分表
Sharding Proxy(如 ShardingSphere)、Vitess、ProxySQL 等中間件支持水平拆分。
擴展
增加只讀從實例;使用 Proxy 做負載均衡;使用分片中間件做寫擴展。
部署建議:異地多機房部署 GTID 復制,結合 ProxySQL 做讀寫分離。
主從復制(Streaming Replication)
物理或邏輯復制;熱備從庫用于故障切換或讀擴展。
Patroni / Pgpool-II / PgBouncer
Patroni + Etcd/ZooKeeper 管理高可用;Pgpool-II 做負載均衡和故障切換;PgBouncer 做連接池。
分布式擴展
Citus 擴展:將表分布到 worker 節點,實現分片和并行查詢。
擴展
增加從節點做讀擴展;使用 Citus 或 Citus Cloud 做寫擴展。
部署建議:至少 3 個 Etcd/Consul 實例+3 個 Patroni 主體節點,保證高可用。
通用最佳實踐
奇數節點:無論是仲裁節點還是選主節點,保持奇數個以達成多數派。
跨機架/機房部署:避免單點故障,保證副本分布在不同物理位置。
監控與告警:部署 Prometheus + Grafana 或 ELK、Graylog 等監控各節點健康與性能。
備份與恢復:定期全量備份(快照)+增量備份,確保可快速恢復。
自動化運維:使用 Ansible、Terraform、Kubernetes Operators(如 MongoDB Operator、Etcd Operator)等工具管理集群生命周期。
http://localhost:8108/api/doc.html#/home
1???
@Target(ElementType.METHOD)
意思:這個注解只能加在“方法”上。
舉例:
@AuthCheck(mustRole =?"admin") public void?deleteUser() { ... }
? 可以用在方法上
? 不可以用在類、字段、構造器等位置
2???
@Retention(RetentionPolicy.RUNTIME)
意思:這個注解在程序運行的時候依然“存在”,并可以通過反射讀取它的內容。
說明:你可以在運行時動態讀取?
mustRole
?的值,來做權限校驗。
3???
public @interface AuthCheck { ... }
定義一個叫?
AuthCheck
?的注解。你就可以像使用?@Override
?那樣使用它。
4???
String mustRole() default ""
這是一個?注解的參數,叫?
mustRole
,類型是?String
,表示“必須的角色”。default ""
?表示默認值是空字符串。舉例:
@AuthCheck(mustRole =?"admin") ?// 必須是 admin 角色 @AuthCheck() ?// 不傳參數,相當于默認空字符串
📌 使用場景示例(配合 AOP 做權限控制)
比如你定義了以下方法:
@AuthCheck(mustRole =?"admin") public void?deleteUserAccount() {// 刪除賬號邏輯 }
你可以在后臺通過 AOP 切面讀取這個注解的值,判斷當前登錄用戶是否是?
admin
,否則拒絕執行這個方法。🔹?
@Aspect
?+?@Component
@Aspect @Component
@Aspect
:標識這是一個?切面類,Spring AOP 會識別它。@Component
:讓這個類變成 Spring 管理的 Bean,才能自動注入和工作。
🔹 攔截邏輯的主函數
@Around("@annotation(authCheck)")
@Around
:表示“環繞通知”,就是在目標方法執行?之前和之后都能插手干預。@annotation(authCheck)
:只攔截打了?@AuthCheck
?注解的方法。authCheck
?就是注解的實例。
🔹 獲取注解中的角色要求
String mustRole = authCheck.mustRole();
如果你寫的是:
@AuthCheck(mustRole =?"admin")
那?
mustRole
?就是?"admin"
。🔹 獲取當前請求與用戶
HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest(); User loginUser = userService.getLoginUser(request);
拿到當前請求對象,然后調用?
userService
?拿出登錄用戶。@Component
:把這個類交給 Spring 管理,后續可以自動注入使用。BiMessageProducer
:就是“發送消息的人”。
假設你在一個點餐系統中:
用戶點單后,你需要把這個訂單數據發到“廚房系統”;
那么你可以:
biMessageProducer.sendMessage("訂單:奶茶1杯");
然后 RabbitMQ 就會“幫你傳話”,把這條消息送給對應的消費者。
注入兩個服務類:
AiManager
:調用 AI 分析圖表。ChartService
:查和更新圖表信息。
@RabbitListener(bindings = @QueueBinding(value = @Queue(name = BiMqConstant.BI_QUEUE_NAME),exchange = @Exchange(name = BiMqConstant.BI_EXCHANGE_NAME,?type?= ExchangeTypes.DIRECT),key = BiMqConstant.BI_ROUTING_KEY),ackMode =?"MANUAL" )
監聽器的配置,告訴 RabbitMQ:
哪個隊列(
BI_QUEUE_NAME
);哪個交換機(
BI_EXCHANGE_NAME
);用什么路由鍵(
BI_ROUTING_KEY
);
ackMode = "MANUAL"
?表示:消息手動確認,不確認就不會從隊列移除。
📨 方法參數說明(很關鍵)
private void receiveMessage(String message, Channel channel, @Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag)
message
:收到的消息內容(這里是圖表 ID 的字符串)。channel
:RabbitMQ 通信通道,用于確認/拒絕消息。deliveryTag
:消息唯一編號,確認時要用。
/*** 分析目標*/ private String goal;
/*** 圖表類型*/ private String chartType;
/*** 圖表數據*/ private String chartData;
🧠 拼接 AI
StringBuffer userInput = new StringBuffer(); userInput.append("你是一個數據分析師...").append("分析目標:").append(chart.getGoal())...
把 chart 里的信息拼成 AI 要求的輸入格式:
分析目標
圖表類型(如柱狀圖)
原始數據(CSV 格式)
🧠 調用 AI,生成結果
String result = aiManager.doChat(userInput.toString()); String[] splits = result.split("【【【【【");
? 確認消息處理成功
channel.basicAck(deliveryTag,?false);
RabbitMQ 要求你手動告訴它“這條消息處理完了”,否則它會反復發。
一個流水線機器人:
等待 RabbitMQ 叫它干活;
拿到圖表 ID;
去數據庫拿詳細信息;
拼成 AI 能看懂的輸入;
讓 AI 輸出圖表代碼和結論;
寫回數據庫;
告訴 RabbitMQ:我干完了!
public enum ErrorCode {// ========== 成功 ==========SUCCESS(0,?"成功",?"操作成功"),// ========== 參數錯誤 ==========PARAMS_ERROR(40000,?"請求參數錯誤",?"請求參數不符合預期"),VALIDATION_ERROR(40001,?"參數校驗失敗",?"字段格式或約束錯誤"),// ========== 認證 & 授權 ==========NOT_LOGIN_ERROR(40100,?"未登錄",?"用戶未登錄,請先登錄"),NO_AUTH_ERROR(40101,?"無權限",?"當前用戶無訪問權限"),// ========== 資源訪問錯誤 ==========FORBIDDEN_ERROR(40300,?"禁止訪問",?"服務器理解請求但拒絕執行"),NOT_FOUND_ERROR(40400,?"資源不存在",?"請求的數據或頁面不存在"),// ========== 系統錯誤 ==========SYSTEM_ERROR(50000,?"系統錯誤",?"服務器內部發生錯誤,請聯系管理員"),OPERATION_ERROR(50001,?"操作失敗",?"請求的操作未成功執行"),SERVICE_UNAVAILABLE(50300,?"服務不可用",?"系統維護中,請稍后再試"),// ========== 頻率限制 ==========TOO_MANY_REQUEST(42900,?"請求頻繁",?"請求過于頻繁,請稍后重試"),// ========== 業務邏輯錯誤 ==========DUPLICATE_OPERATION(60001,?"重復操作",?"請勿重復提交"),DATA_CONFLICT(60002,?"數據沖突",?"存在重復或沖突的數據"),DATA_NOT_READY(60003,?"數據未就緒",?"請稍后重試,數據正在處理中");private final int code;private final String message;private final String description;ErrorCode(int code, String message, String description) {this.code = code;this.message = message;this.description = description;}public int?getCode() {return?code;}public String?getMessage() {return?message;}public String?getDescription() {return?description;} }
CORS 跨域配置類,用于讓前端頁面可以訪問后端接口,即使它們的域名或端口不同。
? 什么是 CORS?
CORS 全稱是?Cross-Origin Resource Sharing(跨域資源共享)?。
默認情況下,瀏覽器不允許前端去請求一個不同域名/端口/協議的接口,需要配置后端允許“跨域訪問”。比如:
前端在?
http://localhost:3000
后端在?
http://localhost:8080
👉 這就叫“跨域”@Configuration
:告訴 Spring 這是一個配置類(類似全局設置)。WebMvcConfigurer
:這是 Spring Web 的一個接口,你可以用它來自定義 Web 行為(比如 CORS、靜態資源、攔截器等)。
.allowCredentials(true) 允許前端攜帶 Cookie、token 等憑證。
?? 注意:如果允許攜帶 Cookie,就不能用 allowedOrigins(""),要用 allowedOriginPatterns("")。
@Configuration
:這個類是一個?配置類,會被 Spring 自動加載。@MapperScan("com.sss.bibackend.mapper")
:告訴 MyBatis 去掃描你指定的包下的?
Mapper
?接口(也叫 DAO 層)。例如你有一個接口?
UserMapper
?放在?com.sss.bibackend.mapper
?里,這里就會自動注冊它。
📌 Bonus:分頁查詢怎么用?
你寫完這個配置后,可以這樣分頁查詢:
Page<User> page = new Page<>(1, 5); // 第1頁,每頁5條 Page<User> resultPage = userMapper.selectPage(page, null); List<User> records = resultPage.getRecords(); // 查到的數據 long total = resultPage.getTotal(); ? ? ? ? ? // 總條數
我們有一個?
User
?表,字段如下:id
:主鍵username
:用戶名email
:郵箱age
:年齡
1?? 數據庫建表語句(MySQL)
CREATE TABLE user (id BIGINT PRIMARY KEY AUTO_INCREMENT,username VARCHAR(50),email VARCHAR(100),age INT );
2?? 實體類?
User.java
@Data @TableName("user") public class User {private Long id;private String username;private String email;private Integer age; }
3?? Mapper 接口?
UserMapper.java
public interface UserMapper extends BaseMapper<User> {// 無需添加任何代碼,MyBatis-Plus 會自動實現分頁功能 }
4?? Service 示例?
UserService.java
public interface UserService extends IService<User> {Page<User> searchUsers(String username, Integer minAge, int current, int size); }
實現類?
UserServiceImpl.java
@Service public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {@Overridepublic Page<User> searchUsers(String username, Integer minAge, int current, int size) {QueryWrapper<User> queryWrapper = new QueryWrapper<>();// 如果用戶名不為空,模糊查詢if?(StringUtils.isNotBlank(username)) {queryWrapper.like("username", username);}// 如果設置了最小年齡,做大于等于篩選if?(minAge != null) {queryWrapper.ge("age", minAge);}Page<User> page = new Page<>(current, size);return?this.page(page, queryWrapper); // 調用 MyBatis-Plus 分頁查詢} }
5?? Controller 示例?
UserController.java
@RestController @RequestMapping("/user") public class UserController {@Resourceprivate UserService userService;@GetMapping("/search")public Page<User> searchUsers(@RequestParam(required =?false) String username,@RequestParam(required =?false) Integer minAge,@RequestParam(defaultValue =?"1") int page,@RequestParam(defaultValue =?"10") int size) {return?userService.searchUsers(username, minAge, page, size);} }
@Configuration
:告訴 Spring Boot 這是一個配置類,要自動加載。@ConfigurationProperties(prefix = "threadpool")
:表示你可以在配置文件(如?
application.yml
)里寫?threadpool.xxx
?的配置,自動綁定到這個類的字段上。
@Data
:Lombok 提供的注解,自動生成 getter/setter、toString 等。@Bean
:把這個線程池交給 Spring 管理,以后可以通過注入?@Autowired
?來使用它。Runnable r:每個要執行的任務(也可以看成一個函數)。
newThread(r)?:線程池內部需要新線程時就會調用這個方法。
設置線程名字為:
線程1
、線程2
……,方便日志調試。
🚀 創建線程池本體
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(corePoolSize, ? ? ? ? ? ? ? ? ? ?// 核心線程數maximumPoolSize, ? ? ? ? ? ? ? ? // 最大線程數keepAliveTime, ? ? ? ? ? ? ? ? ? // 非核心線程的存活時間TimeUnit.MILLISECONDS, ? ? ? ? ?// 時間單位new ArrayBlockingQueue<>(4), ? ?// 隊列容量 4 的阻塞隊列threadFactory ? ? ? ? ? ? ? ? ? ?// 上面自定義的線程工廠 );
線程池怎么工作的?
核心線程數(比如 2):一直保留,即使空閑;
最大線程數(比如 4):超過核心線程后再用,任務多了就擴容;
隊列(大小為 4):任務先進入隊列排隊;
自定義線程工廠:創建線程時用你定義的名字;
超出容量(線程 + 隊列都滿)時會報錯(默認策略是?
AbortPolicy
)。
使用線程池的方法(舉個例子)
@Autowired private ThreadPoolExecutor threadPoolExecutor;public void?doSomethingAsync() {threadPoolExecutor.execute(() -> {// 異步任務代碼System.out.println("當前線程:"?+ Thread.currentThread().getName());}); }
public class BusinessException extends RuntimeException
這個類繼承了 RuntimeException,說明它是一個運行時異常。
使用起來很方便,可以不寫 try...catch 也能拋出。
同一個用戶每秒最多請求 2 次
🧩 注入 Redisson 客戶端
@Resource private RedissonClient redissonClient;
RedissonClient
?是操作 Redis 的 Java 客戶端,功能強大,支持分布式鎖、限流器等;這里我們用的是它的限流器(RateLimiter)功能。
🧱 創建限流器
RRateLimiter rateLimiter = redissonClient.getRateLimiter(key); rateLimiter.trySetRate(RateType.OVERALL, 2, 1, RateIntervalUnit.SECONDS);
getRateLimiter(key)
:從 Redis 中拿一個名為?key
?的限流器,如果不存在就創建;trySetRate(...)
:RateType.OVERALL
:總的限流(所有客戶端共享這個限制);2
:允許每個周期(1 秒)最多執行 2 次;RateIntervalUnit.SECONDS
:單位是秒。
?? 翻譯成人話就是:
“我允許這個 key(比如 user:123)每秒最多只能干 2 次,再多就不行。”
你在 Controller 或 Service 中這樣使用:
redisLimiterManager.doRateLimit("user:"?+ userId); // 如果沒拋異常,就可以執行后續邏輯
Redisson 限流 + 接口注解限流
🧱 最終實現效果:
@RateLimit(key =?"user:limit", permitsPerSecond = 2, time = 1, unit = TimeUnit.SECONDS) @GetMapping("/test") public String?test() {return?"請求成功!"; }
請求超過每秒 2 次 → 自動拋出限流異常!
星火大模型(Spark)發送用戶消息
sparkRequest
:后面會構建這個對象,封裝用戶要發給 AI 的內容;sparkClient
:客戶端對象,用來發起請求給大模型。
構建對話內容
List<SparkMessage> messages = new ArrayList<>(); messages.add(SparkMessage.systemContent("你是一個數據分析師...")); messages.add(SparkMessage.userContent(message));
創建對話消息列表:
第一條是系統設定(告訴 AI 它扮演誰);
第二條是用戶真正輸入的分析目標+數據。
數據萬象文本審核
調用騰訊云 COS(對象存儲)進行文檔內容合規檢測
把用戶上傳的文件上傳到騰訊云 COS,然后調用內容審核接口判斷該文件是否包含違規內容(如暴力、涉黃等),如果違規就拋出異常。
📁 獲取文件流并上傳到 COS
inputStream = multipartFile.getInputStream(); ObjectMetadata objectMetadata = new ObjectMetadata(); String bucketName =?"bi-1324629091"; String key =?"folder/"?+ multipartFile.getOriginalFilename(); PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, key, inputStream, objectMetadata); PutObjectResult putObjectResult = cosClient.putObject(putObjectRequest);
將?
MultipartFile
?轉成?InputStream
;構造上傳請求?
PutObjectRequest
;key
?是文件路徑 + 名稱;上傳文件到 COS(騰訊云對象存儲)。
用戶上傳文件 → 上傳到騰訊 COS → 發起內容審核 → 等待審核結果 → 如果不合格就拋異常,阻止后續邏輯執行。