使用SSE解決獲取狀態不一致問題

使用SSE解決獲取狀態不一致問題

  • 1. 問題描述
  • 2. SSE介紹
    • 2.1 SSE 的工作原理
    • 2.2 SSE 的事件格式規范
    • 2.3 SSE與其他技術對比
    • 2.4 SSE 的優缺點
  • 3. 實戰代碼

1. 問題描述

目前做的一個功能是上傳多個文件,這個上傳文件是整體功能的一部分,文件在上傳的過程中需要輪詢文件上傳的狀態的接口,還有要調用整個任務狀態的接口,因為我們的Mysql是單例的,有多個大文件上傳的時候會出現任務狀態不一致的問題,經過調研有WebSocket與SSE兩種方式,但是我只需要把信息推給前端,所以使用個更輕量的SSE。

2. SSE介紹

SSE(Server-Sent Events) 是 HTML5 標準中的一項技術,它允許服務器通過單向連接持續地將數據推送給客戶端(通常是瀏覽器)。

  • 與傳統的 HTTP 請求響應不同,SSE 是一種服務器主動推送數據的機制。
  • 與 WebSocket 不同,它是單向通信:服務器 -> 客戶端。

SSE 使用標準的 HTTP 協議 和 文本/event-stream 格式,通常用于實時消息推送,如股票行情、社交動態通知、在線狀態更新等。

2.1 SSE 的工作原理

  1. 客戶端通過普通的 HTTP 請求發起連接:
GET /events HTTP/1.1
Accept: text/event-stream
  1. 服務器響應:
HTTP/1.1 200 OK
Content-Type: text/event-stream
Cache-Control: no-cache
Connection: keep-alive
  1. 事件流
event: message
id: 123
data: 這是要推送的數據
  1. 客戶端自動處理每一條數據,并在連接斷開時自動重連。

2.2 SSE 的事件格式規范

每條消息由一組字段組成,字段以冒號: 分隔,每條消息之間由兩個換行符 \n\n 分隔:
在這里插入圖片描述

示例:

id: 1001
event: update
data: {"progress": 50}

2.3 SSE與其他技術對比

在這里插入圖片描述

2.4 SSE 的優缺點

? 優點:

  • 使用標準 HTTP 協議,兼容性好;
  • 實現簡單,開發成本低;
  • 支持自動重連機制;
  • 支持事件類型、多行數據等;
  • 適用于需要實時更新、但無需客戶端發送大量消息的場景。

? 缺點:

  • 只支持單向通信;
  • 不支持二進制數據;
  • 不支持所有瀏覽器(如 IE);
  • 有并發連接數限制(部分瀏覽器每個域名默認最大連接數限制);
  • 需配置好心跳機制、防止代理服務器中斷連接。

3. 實戰代碼

@GetMapping("/file-upload-status")
@Operation(summary = "文件上傳狀態SSE")
public SseEmitter fileUploadStatus(@RequestParam("taskCode") String taskCode,@RequestHeader(value = "Last-Event-ID", required = false) String lastEventId) {
log.info("文件上傳狀態SSE, 請求參數: {}, Last-Event-ID: {}", taskCode, lastEventId);try {return dataConfigService.fileUploadStatus(taskCode, lastEventId);
} catch (Exception e) {log.error("文件上傳狀態SSE,失敗,錯誤信息:{}", e.getMessage());throw e;}
}/*** 用于存儲每個任務對應的 SseEmitter 實例。* key 為任務唯一標識 taskCode,value 為與該任務關聯的 SseEmitter。* 使用 ConcurrentHashMap 是為了支持多線程環境下的并發讀寫,確保線程安全。* <p>* 場景:* - 客戶端發起 SSE 連接時,將對應的 SseEmitter 存入此 Map。* - 后臺定時任務或上傳進度更新時可以通過 taskCode 拿到對應的 emitter 推送數據。* - 當連接斷開(如超時、關閉、出錯)時,從 Map 中移除對應的 emitter,避免內存泄漏。*/private final Map<String, SseEmitter> emitterMap = new ConcurrentHashMap<>();/*** 定時任務線程池,用于定期推送每個任務的上傳狀態到前端客戶端(通過 SseEmitter)。* 使用 Runtime.getRuntime().availableProcessors() 獲取當前機器的可用處理器核心數,* 并以此設置線程池大小,合理利用系統資源。* <p>* 特點:* - ScheduledExecutorService 支持定時或周期性任務調度,適合做周期性狀態推送。* - 使用線程池而不是單線程可以支持多個任務并發狀態推送。* - 可根據系統并發量和任務復雜度調整線程池大小。*/private final ScheduledExecutorService scheduledExecutorService =Executors.newScheduledThreadPool(Runtime.getRuntime().availableProcessors());/*** 緩存最近一次推送的狀態(用于斷線續傳)*/private final Map<String, DataFileUploadStatusVO> lastEventDataMap = new ConcurrentHashMap<>();
@Overridepublic SseEmitter fileUploadStatus(String taskCode, String lastEventId) {// 檢查任務代碼是否為空if (StringUtils.isBlank(taskCode)) {throw new ServiceException(400, "請求參數不能為空");}// 創建 SseEmitter 實例,設置超時時間為 1 小時(單位:毫秒)SseEmitter emitter = new SseEmitter(60 * 60 * 1000L);// 將當前任務的 emitter 注冊到全局 emitterMap 中,用于后續狀態推送emitterMap.put(taskCode, emitter);// 定義清理邏輯(連接關閉時自動移除 emitter,避免內存泄漏)Runnable cleanup = () -> {emitterMap.remove(taskCode);lastEventDataMap.remove(taskCode);};// 注冊回調:客戶端主動關閉連接時調用emitter.onCompletion(cleanup);// 注冊回調:連接超時后自動關閉并清理emitter.onTimeout(cleanup);// 注冊回調:出現異常時進行日志記錄并清理資源emitter.onError(e -> {log.error("文件上傳狀態SSE 錯誤,taskCode:{}, 錯誤信息:{}", taskCode, e.getMessage(), e);cleanup.run();});// 嘗試斷點續傳(只在客戶端提供 Last-Event-ID 的情況下)if (StringUtils.isNotBlank(lastEventId)) {DataFileUploadStatusVO lastData = lastEventDataMap.get(taskCode);if (lastData != null) {try {emitter.send(SseEmitter.event().id(lastEventId).name("upload-status").reconnectTime(5000L).data(lastData, MediaType.APPLICATION_JSON));log.info("文件上傳狀態SSE,斷點續傳成功,taskCode:{}, lastEventId:{}, 數據:{}", taskCode, lastEventId,JSON.toJSONString(lastData));} catch (IOException e) {log.error("文件上傳狀態SSE,斷點續傳失敗,taskCode:{}, 錯誤:{}", taskCode, e.getMessage(), e);}}}// 創建一個原子容器用于持有定時任務引用,以便后續取消任務AtomicReference<ScheduledFuture<?>> futureRef = new AtomicReference<>();// 啟動定時任務ScheduledFuture<?> future = scheduledExecutorService.scheduleAtFixedRate(() -> {try {// 從全局映射中獲取當前連接的 emitter,若為空說明連接已關閉,停止執行SseEmitter currentEmitter = emitterMap.get(taskCode);if (currentEmitter == null) {return;}// 查詢文件上傳狀態List<DataConfigRespVO> dataConfigList = getDataConfigList(taskCode);// 查詢任務信息TaskRespVO taskRespVO = taskService.getTask(taskCode);// 將數據庫實體轉換為狀態對象列表List<DataFileUploadStatusVO.FileStatus> fileStatusList = dataConfigList.stream().map(item -> {DataFileUploadStatusVO.FileStatus fileStatus = new DataFileUploadStatusVO.FileStatus();fileStatus.setId(item.getId());fileStatus.setCode(item.getCode());fileStatus.setImportMethod(item.getImportMethod());fileStatus.setFilename(item.getFilename());fileStatus.setFileUrl(item.getFileUrl());fileStatus.setSize(item.getSize());fileStatus.setUploadStatusCode(item.getUploadStatusCode());return fileStatus;}).collect(Collectors.toList());// 構建完整狀態返回對象DataFileUploadStatusVO statusVO = new DataFileUploadStatusVO();statusVO.setTaskCode(taskCode);statusVO.setCurrentTime(TimeUtil.getCurrentTime());statusVO.setFileStatusList(fileStatusList);statusVO.setName(taskRespVO.getName());statusVO.setDataType(taskRespVO.getDataType());statusVO.setDataTypeStr(taskRespVO.getDataTypeStr());statusVO.setImportType(taskRespVO.getImportType());statusVO.setCurrentLinkCode(taskRespVO.getCurrentLinkCode());statusVO.setCurrentLink(taskRespVO.getCurrentLink());statusVO.setCurrentLinkStatusCode(taskRespVO.getCurrentLinkStatusCode());statusVO.setCurrentLinkStatus(taskRespVO.getCurrentLinkStatus());String eventId = String.valueOf(System.currentTimeMillis());// 推送狀態try {// 設置狀態statusVO.setFinished(fileUploadFished(statusVO));// 保存最后一次推送的數據,用于斷線續傳lastEventDataMap.put(taskCode, statusVO);currentEmitter.send(SseEmitter.event()// 事件 ID,供斷線續傳.id(eventId)// 事件名.name("upload-status")// 告訴客戶端:斷線后5秒再重連.reconnectTime(5000L)// 推送數據為 JSON.data(statusVO, MediaType.APPLICATION_JSON));log.info("文件上傳狀態SSE,當前時間:{},taskCode:{},推送數據:{}", TimeUtil.getCurrentTime(), taskCode,JSON.toJSONString(statusVO));} catch (IOException ioException) {// 客戶端斷開連接或傳輸異常,主動清理資源并中止定時任務log.error("文件上傳狀態SSE,錯誤:{},taskCode:{}", ioException.getMessage(), taskCode);currentEmitter.completeWithError(ioException);cleanup.run();futureRef.get().cancel(true);return;}// 判斷任務是否完成if (fileUploadFished(statusVO)) {// 設置任務完成statusVO.setFinished(true);currentEmitter.send(SseEmitter.event().name("upload-status").data(statusVO, MediaType.APPLICATION_JSON));// 主動關閉連接currentEmitter.complete();// 清理資源并取消定時任務cleanup.run();futureRef.get().cancel(true);log.info("文件上傳狀態SSE,任務已完成,taskCode:{},當前時間:{},emitterMap:{},大小:{}", taskCode,TimeUtil.getCurrentTime(), JSON.toJSONString(emitterMap), emitterMap.size());}} catch (Exception e) {log.error("文件上傳狀態SSE, SSE推送失敗,taskCode:{},錯誤信息:{}", taskCode, e.getMessage(), e);SseEmitter failedEmitter = emitterMap.get(taskCode);if (failedEmitter != null) {failedEmitter.completeWithError(e);}cleanup.run();futureRef.get().cancel(true);}// 每2秒執行一次}, 0, 2, TimeUnit.SECONDS);// 記錄定時任務引用futureRef.set(future);// 返回 emitter 給前端,保持連接return emitter;}
event:upload-status
data:{"finished":false,"taskCode":"366d1b2c760f4afd8b709e64c188a27c","currentTime":"2025-06-06 09:53:27","fileStatusList":[{"id":3922,"code":"64d9c1ab4abc441280abb61bba72a611","importMethod":{"code":1,"desc":"文件導入"},"filename":"新聞文本1.txt","fileUrl":"data-config/file/64d9c1ab4abc441280abb61bba72a611_新聞文本1.txt","tableName":null,"fieldName":null,"createTime":null,"introduction":null,"size":"1.39 KB","includeHeader":null,"csvSeparator":null,"uploadStatusCode":2},{"id":3923,"code":"33735f65a0b940a996ded37ff4066299","importMethod":{"code":1,"desc":"文件導入"},"filename":"英文文本.txt","fileUrl":"data-config/file/33735f65a0b940a996ded37ff4066299_英文文本.txt","tableName":null,"fieldName":null,"createTime":null,"introduction":null,"size":"1.77 KB","includeHeader":null,"csvSeparator":null,"uploadStatusCode":2},{"id":3924,"code":"e7c06f1da1a34e4fb8ee46eeac6f9f2e","importMethod":{"code":1,"desc":"文件導入"},"filename":"新聞文本.txt","fileUrl":"data-config/file/e7c06f1da1a34e4fb8ee46eeac6f9f2e_新聞文本.txt","tableName":null,"fieldName":null,"createTime":null,"introduction":null,"size":"2.84 MB","includeHeader":null,"csvSeparator":null,"uploadStatusCode":1}],"name":"測試文件上傳123","dataType":2,"dataTypeStr":"非結構化數據","importType":"file","currentLinkCode":2,"currentLink":"數據配置","currentLinkStatusCode":1,"currentLinkStatus":"執行中"}event:upload-status
data:{"finished":false,"taskCode":"366d1b2c760f4afd8b709e64c188a27c","currentTime":"2025-06-06 09:53:29","fileStatusList":[{"id":3922,"code":"64d9c1ab4abc441280abb61bba72a611","importMethod":{"code":1,"desc":"文件導入"},"filename":"新聞文本1.txt","fileUrl":"data-config/file/64d9c1ab4abc441280abb61bba72a611_新聞文本1.txt","tableName":null,"fieldName":null,"createTime":null,"introduction":null,"size":"1.39 KB","includeHeader":null,"csvSeparator":null,"uploadStatusCode":2},{"id":3923,"code":"33735f65a0b940a996ded37ff4066299","importMethod":{"code":1,"desc":"文件導入"},"filename":"英文文本.txt","fileUrl":"data-config/file/33735f65a0b940a996ded37ff4066299_英文文本.txt","tableName":null,"fieldName":null,"createTime":null,"introduction":null,"size":"1.77 KB","includeHeader":null,"csvSeparator":null,"uploadStatusCode":2},{"id":3924,"code":"e7c06f1da1a34e4fb8ee46eeac6f9f2e","importMethod":{"code":1,"desc":"文件導入"},"filename":"新聞文本.txt","fileUrl":"data-config/file/e7c06f1da1a34e4fb8ee46eeac6f9f2e_新聞文本.txt","tableName":null,"fieldName":null,"createTime":null,"introduction":null,"size":"2.84 MB","includeHeader":null,"csvSeparator":null,"uploadStatusCode":1}],"name":"測試文件上傳123","dataType":2,"dataTypeStr":"非結構化數據","importType":"file","currentLinkCode":2,"currentLink":"數據配置","currentLinkStatusCode":1,"currentLinkStatus":"執行中"}event:upload-status
data:{"finished":false,"taskCode":"366d1b2c760f4afd8b709e64c188a27c","currentTime":"2025-06-06 09:53:31","fileStatusList":[{"id":3922,"code":"64d9c1ab4abc441280abb61bba72a611","importMethod":{"code":1,"desc":"文件導入"},"filename":"新聞文本1.txt","fileUrl":"data-config/file/64d9c1ab4abc441280abb61bba72a611_新聞文本1.txt","tableName":null,"fieldName":null,"createTime":null,"introduction":null,"size":"1.39 KB","includeHeader":null,"csvSeparator":null,"uploadStatusCode":2},{"id":3923,"code":"33735f65a0b940a996ded37ff4066299","importMethod":{"code":1,"desc":"文件導入"},"filename":"英文文本.txt","fileUrl":"data-config/file/33735f65a0b940a996ded37ff4066299_英文文本.txt","tableName":null,"fieldName":null,"createTime":null,"introduction":null,"size":"1.77 KB","includeHeader":null,"csvSeparator":null,"uploadStatusCode":2},{"id":3924,"code":"e7c06f1da1a34e4fb8ee46eeac6f9f2e","importMethod":{"code":1,"desc":"文件導入"},"filename":"新聞文本.txt","fileUrl":"data-config/file/e7c06f1da1a34e4fb8ee46eeac6f9f2e_新聞文本.txt","tableName":null,"fieldName":null,"createTime":null,"introduction":null,"size":"2.84 MB","includeHeader":null,"csvSeparator":null,"uploadStatusCode":1}],"name":"測試文件上傳123","dataType":2,"dataTypeStr":"非結構化數據","importType":"file","currentLinkCode":2,"currentLink":"數據配置","currentLinkStatusCode":1,"currentLinkStatus":"執行中"}event:upload-status
data:{"finished":false,"taskCode":"366d1b2c760f4afd8b709e64c188a27c","currentTime":"2025-06-06 09:53:33","fileStatusList":[{"id":3922,"code":"64d9c1ab4abc441280abb61bba72a611","importMethod":{"code":1,"desc":"文件導入"},"filename":"新聞文本1.txt","fileUrl":"data-config/file/64d9c1ab4abc441280abb61bba72a611_新聞文本1.txt","tableName":null,"fieldName":null,"createTime":null,"introduction":null,"size":"1.39 KB","includeHeader":null,"csvSeparator":null,"uploadStatusCode":2},{"id":3923,"code":"33735f65a0b940a996ded37ff4066299","importMethod":{"code":1,"desc":"文件導入"},"filename":"英文文本.txt","fileUrl":"data-config/file/33735f65a0b940a996ded37ff4066299_英文文本.txt","tableName":null,"fieldName":null,"createTime":null,"introduction":null,"size":"1.77 KB","includeHeader":null,"csvSeparator":null,"uploadStatusCode":2},{"id":3924,"code":"e7c06f1da1a34e4fb8ee46eeac6f9f2e","importMethod":{"code":1,"desc":"文件導入"},"filename":"新聞文本.txt","fileUrl":"data-config/file/e7c06f1da1a34e4fb8ee46eeac6f9f2e_新聞文本.txt","tableName":null,"fieldName":null,"createTime":null,"introduction":null,"size":"2.84 MB","includeHeader":null,"csvSeparator":null,"uploadStatusCode":1}],"name":"測試文件上傳123","dataType":2,"dataTypeStr":"非結構化數據","importType":"file","currentLinkCode":2,"currentLink":"數據配置","currentLinkStatusCode":1,"currentLinkStatus":"執行中"}event:upload-status
data:{"finished":true,"taskCode":"366d1b2c760f4afd8b709e64c188a27c","currentTime":"2025-06-06 09:53:35","fileStatusList":[{"id":3922,"code":"64d9c1ab4abc441280abb61bba72a611","importMethod":{"code":1,"desc":"文件導入"},"filename":"新聞文本1.txt","fileUrl":"data-config/file/64d9c1ab4abc441280abb61bba72a611_新聞文本1.txt","tableName":null,"fieldName":null,"createTime":null,"introduction":null,"size":"1.39 KB","includeHeader":null,"csvSeparator":null,"uploadStatusCode":2},{"id":3923,"code":"33735f65a0b940a996ded37ff4066299","importMethod":{"code":1,"desc":"文件導入"},"filename":"英文文本.txt","fileUrl":"data-config/file/33735f65a0b940a996ded37ff4066299_英文文本.txt","tableName":null,"fieldName":null,"createTime":null,"introduction":null,"size":"1.77 KB","includeHeader":null,"csvSeparator":null,"uploadStatusCode":2},{"id":3924,"code":"e7c06f1da1a34e4fb8ee46eeac6f9f2e","importMethod":{"code":1,"desc":"文件導入"},"filename":"新聞文本.txt","fileUrl":"data-config/file/e7c06f1da1a34e4fb8ee46eeac6f9f2e_新聞文本.txt","tableName":null,"fieldName":null,"createTime":null,"introduction":null,"size":"2.84 MB","includeHeader":null,"csvSeparator":null,"uploadStatusCode":2}],"name":"測試文件上傳123","dataType":2,"dataTypeStr":"非結構化數據","importType":"file","currentLinkCode":2,"currentLink":"數據配置","currentLinkStatusCode":2,"currentLinkStatus":"已完成"}event:upload-status
data:{"finished":true,"taskCode":"366d1b2c760f4afd8b709e64c188a27c","currentTime":"2025-06-06 09:53:35","fileStatusList":[{"id":3922,"code":"64d9c1ab4abc441280abb61bba72a611","importMethod":{"code":1,"desc":"文件導入"},"filename":"新聞文本1.txt","fileUrl":"data-config/file/64d9c1ab4abc441280abb61bba72a611_新聞文本1.txt","tableName":null,"fieldName":null,"createTime":null,"introduction":null,"size":"1.39 KB","includeHeader":null,"csvSeparator":null,"uploadStatusCode":2},{"id":3923,"code":"33735f65a0b940a996ded37ff4066299","importMethod":{"code":1,"desc":"文件導入"},"filename":"英文文本.txt","fileUrl":"data-config/file/33735f65a0b940a996ded37ff4066299_英文文本.txt","tableName":null,"fieldName":null,"createTime":null,"introduction":null,"size":"1.77 KB","includeHeader":null,"csvSeparator":null,"uploadStatusCode":2},{"id":3924,"code":"e7c06f1da1a34e4fb8ee46eeac6f9f2e","importMethod":{"code":1,"desc":"文件導入"},"filename":"新聞文本.txt","fileUrl":"data-config/file/e7c06f1da1a34e4fb8ee46eeac6f9f2e_新聞文本.txt","tableName":null,"fieldName":null,"createTime":null,"introduction":null,"size":"2.84 MB","includeHeader":null,"csvSeparator":null,"uploadStatusCode":2}],"name":"測試文件上傳123","dataType":2,"dataTypeStr":"非結構化數據","importType":"file","currentLinkCode":2,"currentLink":"數據配置","currentLinkStatusCode":2,"currentLinkStatus":"已完成"}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/86048.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/86048.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/86048.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

華為×小鵬戰略合作:破局智能駕駛深水區的商業邏輯深度解析

當中國智能電動車競爭進入下半場&#xff0c;頭部玩家的合縱連橫正在重構產業格局。華為與小鵬汽車近日官宣的“戰略合作”&#xff0c;表面看是技術互補的常規操作&#xff0c;實則暗藏改寫行業游戲規則的深層商業邏輯。 一、技術破壁&#xff1a;從“單點突破”到“全棧協同”…

Tailwind CSS 實戰:基于 Kooboo 構建 AI 對話框頁面(六):圖片上傳交互功能

在 《Tailwind CSS 實戰&#xff1a;基于 Kooboo 構建 AI 對話框頁面&#xff08;五&#xff09;》 中&#xff0c;完成了語音交互功能的優化。本文作為該系列教程的第六篇&#xff0c;將聚焦于圖片上傳功能的開發。通過集成圖片上傳與預覽能力&#xff0c;我們將進一步完善 AI…

40. 自動化異步測試開發之編寫異步業務函數、測試函數和測試類(類寫法)

40. 自動化異步測試開發之編寫異步業務函數、測試函數和測試類&#xff08;類寫法&#xff09; 一、類結構設計解析 1.1 基類設計 class Base:async_driver None # &#x1f697; 存儲瀏覽器驅動實例async def get(self, url: str http://secure.smartbearsoftware.com/.…

面向開發者的提示詞工程④——文本推斷(Inferring)

文章目錄 前言一、情感&#xff08;正向/負向&#xff09;二、識別情感類型三、識別憤怒四、從客戶評論中提取產品和公司名稱五、一次完成多項任務 前言 面向開發者的提示詞工程——導讀 在這節課中&#xff0c;你將從產品評論和新聞文章中推斷情感和主題。 舉了個商品評論的例…

java day15 (數據庫)

進入數據庫的學習 DB 因為數據太多了&#xff0c;方便統一管理的軟件 操作就不用改代碼了&#xff0c;直接改數據庫則可&#xff1b; 命令就是sql語句 這些都是關系型數據庫&#xff0c;sql可以控制全部&#xff0c;至于具體的環境我以前就有安裝過了&#xff1b; 理解&am…

國標GB28181設備管理軟件EasyGBS遠程視頻監控方案助力高效安全運營

一、方案背景? 在商業快速擴張的背景下&#xff0c;連鎖店門店數量激增&#xff0c;分布范圍廣。但傳統人工巡檢、電話匯報等管理方式效率低下&#xff0c;存在信息滯后、管理盲區&#xff0c;難以掌握店鋪運營情況&#xff0c;影響企業效率與安全。網絡遠程視頻監控系統可有…

Python 字典(dict)的高級用法與技巧

今天我們繼續深入講解 Python 字典的 高級用法與技巧&#xff0c;包括&#xff1a; defaultdict&#xff1a;帶默認值的字典Counter&#xff1a;快速統計工具字典排序&#xff1a;按鍵或值排序合并字典&#xff08;傳統方式和 Python 3.9 新語法&#xff09;嵌套字典的安全訪問…

動靜態庫的使用(Linux)

1.庫 通俗來說&#xff0c;庫就是現有的&#xff0c;可復用的代碼&#xff0c;例如&#xff1a;在C/C語言編譯時&#xff0c;就需要依賴相關的C/C標準庫。本質上來說庫是一種可執行代碼的二進制形式&#xff0c;可以被操作系統載入內存執行。通常我們可以在windows下看到一些后…

R2ec: 構建具有推理能力的大型推薦模型,顯著提示推薦系統性能!!

摘要&#xff1a;大型推薦模型通過編碼或項目生成將大型語言模型&#xff08;LLMs&#xff09;擴展為強大的推薦工具&#xff0c;而近期在LLM推理方面的突破也同步激發了在推薦領域探索推理的動機。目前的研究通常將LLMs定位為外部推理模塊&#xff0c;以提供輔助性思考來增強傳…

【Java后端基礎 005】ThreadLocal-線程數據共享和安全

&#x1f4da;博客主頁&#xff1a;代碼探秘者 ?專欄&#xff1a;文章正在持續更新ing… ?C語言/C&#xff1a;C&#xff08;詳細版&#xff09; 數據結構&#xff09; 十大排序算法 ?Java基礎&#xff1a;JavaSE基礎 面向對象大合集 JavaSE進階 Java版數據結構JDK新特性…

Tesseract配置參數詳解及適用場景(PyTesseract進行OCR)

在使用 PyTesseract 進行 OCR 時&#xff0c;合理配置參數是提高識別準確率的關鍵。以下是 Tesseract 常用參數的詳細解釋和適用場景。 一、關鍵參數 &#xff08;1&#xff09;頁面分割模式&#xff08;Page Segmentation Mode, --psm&#xff09; 控制 Tesseract 如何分析…

【Zephyr 系列 12】BLE + NVS + 低功耗融合實戰:打造可配置藍牙信標系統

??關鍵詞:Zephyr、BLE 廣播、信標、NVS 參數、低功耗、狀態機、周期喚醒 ??適合人群:希望實現 BLE 信標類產品(定位標簽、資產管理)的開發者 ??預計篇幅:約 5200+ 字 ?? 項目目標 構建一個可廣泛應用于資產標簽、定位信標、設備標識等場景的藍牙廣播模塊,具備:…

圖解瀏覽器多進程渲染:從DNS到GPU合成的完整旅程

目錄 瀏覽器進程架構的演化 進程和線程關系圖示 進程&#xff08;Process&#xff09; 線程&#xff08;Thread&#xff09; 協程&#xff08;Coroutine&#xff09; 進程&線程&協程核心對比 單進程和多進程瀏覽器 單進程瀏覽器?編輯 單進程瀏覽器存在的問題…

Lombok 的 @Data 注解失效,未生成 getter/setter 方法引發的HTTP 406 錯誤

HTTP 狀態碼 406 (Not Acceptable) 和 500 (Internal Server Error) 是兩類完全不同的錯誤&#xff0c;它們的含義、原因和解決方法都有顯著區別。以下是詳細對比&#xff1a; 1. HTTP 406 (Not Acceptable) 含義&#xff1a; 客戶端請求的內容類型與服務器支持的內容類型不匹…

C# 類和繼承(抽象成員)

抽象成員 抽象成員是指設計為被覆寫的函數成員。抽象成員有以下特征。 必須是一個函數成員。也就是說&#xff0c;字段和常量不能為抽象成員。必須用abstract修飾符標記。不能有實現代碼塊。抽象成員的代碼用分號表示。 例如&#xff0c;下面取自一個類定義的代碼聲明了兩個抽…

基于JWT+SpringSecurity整合一個單點認證授權機制

基于 JWT Spring Security 的授權認證機制&#xff0c;在整體架構設計上體現了高度的安全性與靈活性。其在整合框架中的應用&#xff0c;充分展示了模塊化、可擴展性和高效鑒權的設計理念&#xff0c;為開發者提供了一種值得借鑒的安全架構模式。 1.SpringSecurity概念理解 …

HarmonyOS運動開發:如何用mpchart繪制運動配速圖表

##鴻蒙核心技術##運動開發##Sensor Service Kit&#xff08;傳感器服務&#xff09;# 前言 在運動類應用中&#xff0c;運動數據的可視化是提升用戶體驗的重要環節。通過直觀的圖表展示運動過程中的關鍵數據&#xff0c;如配速、距離、卡路里消耗等&#xff0c;用戶可以更清晰…

Git 切換到舊提交,同時保證當前修改不丟失

在 Git 中&#xff0c;可以通過以下幾種方式切換到之前的提交&#xff0c;同時保留當前的修改 1. 使用 git checkout 創建臨時分離頭指針&#xff08;推薦用于查看代碼&#xff09; git checkout <commit-hash>這會讓你進入"分離頭指針"狀態&#xff0c;你可…

東芝Toshiba DP-4528AG打印機信息

東芝 Toshiba DP 4528AG 是一款黑白激光數碼復合機&#xff1a; 類型&#xff1a;激光數碼復合機&#xff0c;涵蓋復印、打印、掃描、傳真功能&#xff0c;能滿足辦公室多樣化的文檔處理需求。速度類型&#xff1a;中速&#xff0c;黑白復印和打印速度可達 45 頁 / 分鐘&#…

Qt生成日志與以及捕獲崩潰文件(mingw64位,winDbg)————附帶詳細解說

文章目錄 Qt生成日志與以及報錯文件(mingw64位&#xff0c;winDbg)0 背景與結果0.1 背景0.2 結果1 WinDbg1.1 安裝1.2 使用 2 編寫代碼2.1 ccrashstack類2.2 編寫輸出捕獲異常的dmp文件2.2 編寫輸出日志文件2.3 調用生成日志和dmp文件 參考 Qt生成日志與以及報錯文件(mingw64位…