最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

深入詳解SpringBoot中接口異步化實戰(zhàn)指南

 更新時間:2026年03月03日 15:19:15   作者:一勺菠蘿丶  
這篇文章主要為大家詳細(xì)介紹了SpringBoot中接口異步化的相關(guān)方法,文中的示例代碼講解詳細(xì),具有一定的借鑒價值,有需要的小伙伴可以跟隨小編一起學(xué)習(xí)一下

背景

在一個智慧課堂系統(tǒng)中,有一個"生成講稿"的接口,內(nèi)部需要調(diào)用 AI 大模型(Coze),整個過程耗時可能在數(shù)十秒甚至更長。

原始的調(diào)用鏈?zhǔn)沁@樣的:

前端
 │
 ├─ 1. 調(diào) updateCdGenStatus(status=1)   → 把狀態(tài)設(shè)為"生成中"
 │
 ├─ 2. 調(diào) generateSpeech               → 同步等待 AI 生成(可能等幾十秒)
 │
 └─ 3. 調(diào) updateCdGenStatus(status=2)  → 把狀態(tài)設(shè)為"已生成"

這個設(shè)計存在兩個明顯問題:

  • 前端長時間阻塞:第 2 步接口響應(yīng)極慢,用戶體驗差。
  • 狀態(tài)不一致:如果用戶在第 2 步等待期間刷新了頁面,第 3 步永遠(yuǎn)不會執(zhí)行,狀態(tài)永遠(yuǎn)卡在"生成中",無法恢復(fù)。

解決思路

將兩個問題合并解決:

  • 狀態(tài)管理下沉到后端:generateSpeech 內(nèi)部在成功后自動更新狀態(tài)為"已生成",失敗時回滾為"暫存",前端不再負(fù)責(zé)狀態(tài)收尾。
  • 接口改為異步:generateSpeech 立即返回,AI 生成任務(wù)由后臺線程池執(zhí)行,前端輪詢狀態(tài)字段即可感知進(jìn)度。

改造后的調(diào)用鏈:

前端                            后端
 │                                │
 ├─ updateCdGenStatus(1) ────────?│ 同步,立即返回,狀態(tài)="生成中"
 │?──────── 200 OK ───────────────┤
 │                                │
 ├─ generateSpeech ──────────────?│ 立即返回 200 OK
 │?──────── 200 OK ───────────────┤     │
 │                                │     ▼ 后臺線程池異步執(zhí)行
 │  (前端可正常操作/刷新頁面)        │  調(diào)用 AI 大模型(耗時)
 │                                │  成功 → cdGenStatus = 2(已生成)
 │                                │  失敗 → cdGenStatus = 0(暫存,可重試)
 │
 前端定時輪詢查詢接口,檢查 cdGenStatus 字段

實現(xiàn)步驟

第一步:創(chuàng)建異步線程池配置類

Spring Boot 默認(rèn)的異步線程池配置較為簡陋,建議為耗時任務(wù)單獨配置一個命名線程池,便于監(jiān)控和隔離。

package org.jeecg.modules.business.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * @author lxy
 */
@Configuration
@EnableAsync  // 開啟 Spring 異步支持
public class AsyncConfig {

    /**
     * 生成講稿專用異步線程池。
     * AI 調(diào)用屬于 IO 密集型,核心線程數(shù)不需要很大。
     * 使用 CallerRunsPolicy 作為拒絕策略,保證任務(wù)不丟失。
     */
    @Bean("speechExecutor")
    public Executor speechExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(2);       // 核心線程數(shù)
        executor.setMaxPoolSize(5);        // 最大線程數(shù)
        executor.setQueueCapacity(20);     // 隊列容量
        executor.setThreadNamePrefix("speech-async-");
        executor.setKeepAliveSeconds(60);
        // 隊列滿且線程達(dá)到上限時,由調(diào)用方線程執(zhí)行,避免任務(wù)丟失
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.initialize();
        return executor;
    }
}

為什么不用 @SpringBootApplication 上加 @EnableAsync?

將 @EnableAsync 放在獨立的 @Configuration 類中,職責(zé)更清晰,也方便后續(xù)擴(kuò)展其他線程池。

第二步:在 Service 實現(xiàn)方法上加 @Async

/**
 * 異步生成講稿。方法立即返回,由后臺線程池(speechExecutor)執(zhí)行耗時的 AI 調(diào)用。
 * 生成成功后自動將 cdGenStatus 更新為"講稿已生成"(2),
 * 生成失敗則回滾為"暫存"(0),無需前端二次調(diào)用更新狀態(tài)接口。
 *
 * @param speechDto 生成講稿所需參數(shù),包含 courseDetailId、classId 等
 */
@Async("speechExecutor")  // 指定使用 speechExecutor 線程池
@Override
public void generateSpeech(SpeechDto speechDto) {
    try {
        // --- 耗時操作:調(diào)用 AI 大模型 ---
        String genWord = cozeUtil.pptCreate(cozeDto);

        // 其他業(yè)務(wù)邏輯...

        // 生成成功 → 后端直接更新狀態(tài)為"已生成"
        this.updateCdGenStatus("2", speechDto.getCourseDetailId(), speechDto.getClassId());

    } catch (Exception e) {
        // 生成失敗 → 回滾狀態(tài)為"暫存",前端可重試
        this.updateCdGenStatus("0", speechDto.getCourseDetailId(), speechDto.getClassId());
        throw new RuntimeException(e);
    }
}

第三步:Controller 無需任何改動

@PostMapping(value = "/generateSpeech")
public Result<?> generateSpeech(@RequestBody SpeechDto speechDto) {
    bizCourseDetailService.generateSpeech(speechDto);  // 立即返回
    return Result.OK();
}

由于 generateSpeech 已標(biāo)注 @Async,Spring 會在調(diào)用時直接提交任務(wù)到線程池并返回,Controller 完全感知不到異步細(xì)節(jié)。

關(guān)鍵注意事項

@Async 的自調(diào)用陷阱

@Async 基于 Spring AOP 代理實現(xiàn),同一個類內(nèi)部的方法互相調(diào)用無法觸發(fā)異步。

// ? 錯誤:在同一個 Service 內(nèi)部調(diào)用,@Async 不生效
public void someMethod() {
    this.generateSpeech(dto);  // 直接調(diào)用,不走代理,不會異步
}

// ? 正確:從另一個 Spring Bean(如 Controller)注入后調(diào)用
@Autowired
private IBizCourseDetailService bizCourseDetailService;

public void someMethod() {
    bizCourseDetailService.generateSpeech(dto);  // 走代理,異步生效
}

異步方法的返回值

@Async 方法的返回值只能是 void 或 Future<T> / CompletableFuture<T>。

本場景使用 void 即可,狀態(tài)通過數(shù)據(jù)庫字段通知前端。

異步方法中的事務(wù)

@Async 方法運行在新線程中,@Transactional 的事務(wù)上下文不會從調(diào)用方傳播過來。如果異步方法內(nèi)需要事務(wù),需要在異步方法本身上加 @Transactional。

SecurityContext(Shiro/Spring Security)不傳播

異步線程中拿不到調(diào)用方的登錄用戶信息,如需使用,需在調(diào)用前手動傳入,或通過參數(shù)傳遞。

前端配合改造

去掉 generateSpeech 成功回調(diào)里調(diào)用 updateCdGenStatus 的邏輯,改為輪詢查詢接口:

// 調(diào)用生成講稿接口后,定時輪詢狀態(tài)
async function generateSpeech(params) {
  await api.generateSpeech(params);  // 立即返回

  // 輪詢,每 3 秒檢查一次
  const timer = setInterval(async () => {
    const res = await api.queryCourseDetail({ id: params.courseDetailId, classId: params.classId });
    const status = res.result.cdGenStatus;
    if (status === '2') {
      clearInterval(timer);
      // 生成成功,刷新頁面
    } else if (status === '0') {
      clearInterval(timer);
      // 生成失敗,提示用戶重試
    }
  }, 3000);
}

總結(jié)

改造點方式
開啟 Spring 異步@Configuration 類上加 @EnableAsync
配置專用線程池@Bean 注冊 ThreadPoolTaskExecutor
方法異步化Service 實現(xiàn)方法上加 @Async("poolName")
狀態(tài)管理內(nèi)聚try 塊末尾更新成功狀態(tài),catch 中回滾失敗狀態(tài)
前端感知進(jìn)度去掉二次狀態(tài)更新調(diào)用,改為輪詢查詢接口

到此這篇關(guān)于深入詳解SpringBoot中接口異步化實戰(zhàn)指南的文章就介紹到這了,更多相關(guān)SpringBoot接口異步化內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringBoot 文件或圖片上傳與下載功能的實現(xiàn)

    SpringBoot 文件或圖片上傳與下載功能的實現(xiàn)

    這篇文章主要介紹了SpringBoot 文件或圖片上傳與下載功能的實現(xiàn),本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-02-02
  • Spring加載properties文件的方法

    Spring加載properties文件的方法

    這篇文章主要為大家詳細(xì)介紹了Spring加載properties文件的兩種方法,一是通過xml方式,另一種方式是通過注解方式,感興趣的小伙伴們可以參考一下
    2016-06-06
  • IDEA提示 add *** to custom tags問題及解決

    IDEA提示 add *** to custom tags問題及解決

    文章介紹了如何在文檔注釋中添加自定義注解(@xxx),并提供了添加和刪除注解的方法,總結(jié)了個人經(jīng)驗,希望對大家有所幫助
    2024-12-12
  • Spring Boot詳細(xì)打印啟動時異常堆棧信息詳析

    Spring Boot詳細(xì)打印啟動時異常堆棧信息詳析

    這篇文章主要給大家介紹了關(guān)于Spring Boot詳細(xì)打印啟動時異常堆棧信息的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用Spring Boot具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-10-10
  • Java轉(zhuǎn)換流(InputStreamReader/OutputStreamWriter)的使用

    Java轉(zhuǎn)換流(InputStreamReader/OutputStreamWriter)的使用

    本文主要介紹了Java轉(zhuǎn)換流(InputStreamReader/OutputStreamWriter)的使用,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-01-01
  • springboot實現(xiàn)增加黑名單和白名單功能

    springboot實現(xiàn)增加黑名單和白名單功能

    本文主要介紹了springboot實現(xiàn)增加黑名單和白名單功能,就是單純的實現(xiàn)filter,然后注冊到springboot里面,在filter里面進(jìn)行黑白名單的篩選,感興趣的可以了解一下
    2024-05-05
  • IDEA 單元測試報錯:Class not found:xxxx springboot的解決

    IDEA 單元測試報錯:Class not found:xxxx springb

    這篇文章主要介紹了IDEA 單元測試報錯:Class not found:xxxx springboot的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-01-01
  • Java后端Tomcat實現(xiàn)WebSocket實例教程

    Java后端Tomcat實現(xiàn)WebSocket實例教程

    WebSocket protocol 是HTML5一種新的協(xié)議。它實現(xiàn)了瀏覽器與服務(wù)器全雙工通信(full-duplex)。一開始的握手需要借助HTTP請求完成握手。本文給大家介紹Java后端Tomcat實現(xiàn)WebSocket實例教程,感興趣的朋友一起學(xué)習(xí)吧
    2016-05-05
  • Maven配置阿里云倉庫/國內(nèi)鏡像的詳細(xì)步驟

    Maven配置阿里云倉庫/國內(nèi)鏡像的詳細(xì)步驟

    在國內(nèi)使用Maven時,很多時候會遇到下載依賴較慢的問題,主要是因為Maven的默認(rèn)中央倉庫位于國外,網(wǎng)絡(luò)延遲較高,為了解決這個問題,我們可以配置國內(nèi)的Maven鏡像源,如阿里云提供的鏡像,在這篇博客中,我們將詳細(xì)介紹如何配置Maven使用阿里云倉庫,需要的朋友可以參考下
    2025-04-04
  • Java Bean與Map轉(zhuǎn)換的幾種方式

    Java Bean與Map轉(zhuǎn)換的幾種方式

    Java Bean與Map轉(zhuǎn)換的幾種方式,包括反射,內(nèi)省,cglib,huTool,cglib動態(tài)代理,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2025-10-10

最新評論

纳雍县| 安新县| 花垣县| 津市市| 勐海县| 宁津县| 金华市| 东乌珠穆沁旗| 沁源县| 尖扎县| 洪湖市| 铜陵市| 壶关县| 海城市| 毕节市| 定日县| 宁乡县| 麻阳| 南安市| 铜川市| 浙江省| 福贡县| 辽阳县| 青岛市| 广安市| 玛沁县| 白河县| 榆社县| 应城市| 张家口市| 鹤壁市| 怀化市| 紫金县| 开江县| 德安县| 萍乡市| 开封县| 宜黄县| 昭苏县| 周至县| 灌南县|