手寫Tomcat(二)—Tomcat簡化模型架構

一、 Tomcat架構

Tomcat的主要角色是 servlet容器,提供一個解釋器,能夠解析并執行JavaScript Object Notation (JON)腳本(后更改為Servlet),并將請求傳送到指定的服務器(如JavaBean)。因此,它是Servlet處理請求、與客戶端通信(RESTful API)以及處理服務器端業務邏輯的關鍵組件。

1.1 HttpServletRequest

HttpServletRequest類在模型中充當?HTTP請求的元數據載體,是連接網絡層(Connector)與業務層(Servlet)的橋梁。?

public class HttpServletRequest {private String url;public String method;public String getUrl() {return url;}public void setUrl(String url) {this.url = url;}public String getMethod() {return method;}public void setMethod(String method) {this.method = method;}
}
  • URL路徑:標識客戶端請求的資源位置(如/login)。

  • HTTP方法:明確操作類型(GET獲取、POST提交),用于路由到Servlet的正確處理邏輯。

與實際 Tomcat 實現的差異

簡化實現實際 Tomcat 的 HttpServletRequest
僅包含urlmethod字段包含完整的請求信息(頭、參數、會話、Cookie等)
直接通過Setter注入數據數據由Tomcat底層協議解析器自動填充
無協議規范校驗(如方法合法性)嚴格校驗HTTP協議規范(如方法名有效性)
無線程安全控制每個請求獨立實例,天然線程安全

1.2?HttpServletResponse

HttpServletResponse類在模型中充當?響應數據的輸出通道,是業務邏輯(Servlet)與網絡層(Connector)之間的橋梁。?

核心思想

  • 數據輸出本質:所有響應最終通過底層OutputStream發送字節流。

  • 分層設計:業務層無需關心網絡細節,只需操作抽象響應對象。

  • 協議封裝:實際Tomcat隱藏了HTTP協議拼接的復雜性。

public class HttpServletResponse {//用于持有輸出流,通過此流將數據發送到客戶端private OutputStream outputStream; //接收一個OutputStream(通常來自服務器Socket連接),以便后續寫入響應內容。public HttpServletResponse(OutputStream outputStream){this.outputStream = outputStream;}  //將字符串轉換為字節數組并寫入輸出流。public void write(String context) throws IOException {outputStream.write(context.getBytes());}
}

1. 響應數據輸出通道

????????持有輸出流:通過構造函數接收底層網絡輸出流(通常來自Tomcat的Connector模塊),直接操作字節流。

????????數據寫入write()方法將字符串轉換為字節寫入流,完成響應體的發送。

2. 在請求處理流程中的角色

????????Connector階段:由連接器創建實例,并注入與客戶端Socket關聯的OutputStream

????????Container階段:傳遞到Servlet的service()方法,供業務邏輯生成響應內容。

3. 基礎協議支持

????????僅處理響應體:直接寫入原始字節流,但未包含HTTP協議頭(如狀態碼、Content-Type)。

與實際 Tomcat 實現的差異

簡化實現實際 Tomcat 的 HttpServletResponse
僅支持直接寫入響應體支持自動管理狀態碼、響應頭、Cookies等
無編碼控制(默認平臺編碼)提供setCharacterEncoding()setContentType()方法
無緩沖機制(直接寫Socket流)內置緩沖區(BufferedOutputStream)提升性能
無重定向/轉發支持支持sendRedirect()forward()方法
無錯誤處理機制可調用sendError()返回標準錯誤頁面

1.3 servlet接口

servlet接口在模型中定義了?請求處理的唯一入口,是Tomcat將網絡層(Connector)與業務邏輯(開發者代碼)解耦的核心設計。?

核心思想

  • 面向接口編程:Tomcat通過接口調用開發者代碼,降低耦合度。

  • 請求-響應范式:所有Web交互抽象為request輸入和response輸出。

  • 容器管理:Servlet實例的創建、調用、銷毀由Tomcat控制,開發者聚焦業務邏輯。

public interface servlet {public void service(HttpServletRequest request, HttpServletResponse response);
}

1. 業務邏輯的統一入口

  • 請求處理抽象化:所有具體業務邏輯(如用戶登錄、數據查詢)必須實現service()方法,Tomcat通過此方法將控制權交給開發者。

  • 協議無關性:開發者無需關心HTTP協議的解析細節(如報文拆分、狀態碼生成),只需操作requestresponse對象。

2. 在Tomcat處理流程中的角色

  • Container階段調用:當Tomcat完成URL匹配并確定目標Servlet后,調用其service()方法。

  • 流程控制樞紐:通過service()方法,開發者可以:

    • 讀取請求參數(request.getParameter())。

    • 處理業務數據(如訪問數據庫)。

    • 生成響應內容(response.write())。

3. 設計模式體現

  • 模板方法模式:實際Servlet實現類(如HttpServlet)通過重寫service()或具體方法(doGet()/doPost())定義行為。

  • 控制反轉(IoC):Tomcat容器控制Servlet生命周期及方法調用,開發者僅需實現接口。

與實際?javax.servlet.Servlet?接口的差異

簡化實現實際 Servlet 接口
僅定義service()方法包含init()destroy()等生命周期方法
無配置參數支持可通過ServletConfig獲取初始化參數
直接處理HTTP協議通常繼承HttpServlet抽象類,實現doGet()等方法
無線程安全約束規范明確Servlet實例默認單例多線程調用,需開發者自行保證線程安全

1.4 HttpServlet

HttpServlet類在模型中實現了?HTTP方法的路由分發,是Tomcat將協議細節與業務邏輯分離的關鍵設計。?

核心思想

  • 職責分離:協議處理(方法路由)與業務邏輯(doXxx())解耦。

  • 擴展性:通過覆蓋特定方法支持新功能,無需修改框架代碼。

  • 規范化:統一Servlet實現模式,降低開發者學習成本。

public abstract class HttpServlet implements servlet{//doGet方法public void doGet(HttpServletRequest request,HttpServletResponse response){}//doPost方法public void doPost(HttpServletRequest request,HttpServletResponse response){}//根據請求方式判斷調用的方法@Overridepublic void service(HttpServletRequest request, HttpServletResponse response) {if(request.getMethod().equals("GET")){doGet(request,response);}else if(request.getMethod().equals("POST")){doPost(request,response);}}
}

核心作用?

1. HTTP方法的路由分發

  • 請求方法解耦:將不同HTTP方法(GET/POST)的處理邏輯分離到獨立方法(doGet()/doPost()),避免在service()中堆積條件判斷

  • 開發者友好性:子類只需覆蓋關注的方法(如doGet()),無需重寫整個service()

2. 在Tomcat處理流程中的角色

  • 容器調用入口:Tomcat調用service()方法后,自動根據請求方法觸發對應的doXxx()

  • 模板方法模式:定義算法骨架(方法路由),具體步驟由子類實現。

3. 規范擴展性

  • 支持新HTTP方法:通過擴展service()方法(如添加doPut()),兼容更多HTTP方法。

  • 統一錯誤處理:可集中處理未實現的方法(如返回405狀態碼)。

與實際?HttpServlet?的差異

簡化實現實際 javax.servlet.http.HttpServlet
僅支持GET/POST方法支持所有HTTP方法(PUT/DELETE/HEAD等)
無HTTP協議版本處理區分HTTP/1.0和HTTP/1.1的語義差異
無默認錯誤響應自動返回405 Method Not Allowed?或?400 Bad Request
無線程安全提示明確說明Servlet實例需線程安全

1.5 SearchClassUtil

用于獲得某一個包下所有類的路徑

public class SearchClassUtil {public static List<String> classPaths = new ArrayList<>();public static List<String> searchClass(){//需要掃描的包名String basePath = "com.qcby.myweb";//將獲取到的包名轉換為路徑String classPath = SearchClassUtil.class.getResource("/").getPath();basePath = basePath.replace(".", File.separator);String searchPath = classPath + basePath;doPath(new File(searchPath),classPath);//得到指定包下所有類的絕對路徑,利用絕對路徑和Java反射機制得到類對象return classPaths;}/*** 該方法會得到所有的類,將類的絕對路徑你寫入到classPaths中* file*/private static void doPath(File file, String classpath) {if(file.isDirectory()){File[] files = file.listFiles();for(File f1:files){doPath(f1,classpath);}}else{if(file.getName().endsWith(".class")){String path = file.getPath().replace(classpath.replace("/","\\").replaceFirst("\\\\",""),"").replace("\\",".").replace(".class","");classPaths.add(path);}}}public static void main(String[] args) {List<String> classes = SearchClassUtil.searchClass();for(String s:classes){System.out.println(s);}}
}

運行結果

1.6 ResponseUtil

/*** 設置響應頭*/
public class ResponseUtil {public  static  final String responseHeader200 = "HTTP/1.1 200 \r\n"+"Content-Type:text/html\r\n"+"\r\n";public static String getResponseHeader404(){return "HTTP/1.1 404 \r\n"+"Content-Type:text/html\r\n"+"\r\n" + "404";}public static String getResponseHeader200(String context){return "HTTP/1.1 200\r\n"+"Content-Type:text/html\r\n"+"\r\n" + context;}}

1.7 XWServlet

核心目標:替代傳統的?web.xml?配置文件,通過聲明式編程將 Servlet 的 URL 映射路徑直接綁定到類上。?

  • URL 路徑映射:通過?url?屬性指定 Servlet 處理的請求路徑(如?/user)。

  • 自動化注冊:Tomcat 啟動時自動掃描帶有該注解的類,并將其注冊到容器中。

  • 零配置開發:開發者無需編寫?web.xml,直接在代碼中聲明路由規則。

@Target(ElementType.TYPE)       //僅允許標注在類或接口上
@Retention(RetentionPolicy.RUNTIME)  //確保注解在運行時可通過反射獲取,這是Tomcat動態注冊 Servlet 的前提
public @interface XWServlet {String url() default "";   //指定 Servlet 的訪問路徑,默認值為空字符串(需開發者顯式配置)
}

1.8 TomcatRoute

public class TomcatRoute {public static HashMap<String, HttpServlet> map = new HashMap<>();static {List<String> paths = PackageUtil.getClassName("com.qcby.myweb");for(String path:paths){try {Class clazz = Class.forName(path);HttpServlet a = (HttpServlet) clazz.getDeclaredConstructor().newInstance();XWServlet xwServlet = (XWServlet) clazz.getDeclaredAnnotation(XWServlet.class);map.put(xwServlet.url(),a);} catch (Exception e) {e.printStackTrace();}}}
}

通過?PackageUtil獲取com.qcby.myweb包下的所有類路徑,并通過反射創建類對象,通過XWServlet 獲取類的url,將url及其對應的類對象放入到HashMap中。

1.9 MyTomcat

public class MyTomcat {static HashMap<String,HttpServlet> map = TomcatRoute.map;public static void dispatch(HttpServletRequest request,HttpServletResponse response){HttpServlet servlet = map.get(request.getUrl());if(servlet != null){servlet.service(request,response);}}public static void start() throws IOException {System.out.println("服務器啟動");ServerSocket serverSocket = new ServerSocket(8083);while (true){Socket socket = serverSocket.accept();InputStream inputStream = socket.getInputStream();HttpServletRequest request = new HttpServletRequest();BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));String str = reader.readLine();request.setMethod(str.split(" ")[0]);request.setUrl(str.split(" ")[1]);OutputStream outputStream = socket.getOutputStream();HttpServletResponse response = new HttpServletResponse(outputStream);dispatch(request,response);}}public static void main(String[] args) throws IOException {start();}
}

1.9.1?dispatch?

public static void dispatch(HttpServletRequest request,HttpServletResponse response){HttpServlet servlet = map.get(request.getUrl());if(servlet != null){servlet.service(request,response);}
}

通過request中的url信息查找 其對應的類對象,若存在,則調用service方式。

1.9.2?Socket

在Tomcat中,Socket(套接字)是實現網絡通信的核心組件,主要用于處理客戶端與服務器之間的數據傳輸。?

數據從客戶端到Tomcat的傳遞

  1. 客戶端發起請求
    客戶端通過瀏覽器發送HTTP請求,數據經操作系統封裝為TCP/IP數據包,通過網卡傳輸到目標服務器。

  2. 網卡接收數據
    服務器的網卡接收到物理信號后,將其轉換為二進制數據流,傳遞給操作系統內核。

  3. Socket監聽與處理
    Tomcat的Connector組件通過Endpoint(如NioEndpoint)監聽指定端口,接受Socket連接。操作系統將數據流交給Tomcat的Socket實例,由Processor解析HTTP協議并生成Request對象。? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?注:每個需要網絡的進程都要申請端口號,有些端口號是被明確占用的,如Mysql的端口號是3306,HTTP的端口號是8080

  4. Servlet容器處理
    解析后的請求通過Adapter轉換為ServletRequest,由Servlet容器(如EngineHostContext)處理業務邏輯,生成響應數據。

  5. 響應返回客戶端
    響應數據通過Socket的輸出流發送回客戶端,經操作系統協議棧封裝后,由網卡轉換為物理信號傳輸到客戶端。

         System.out.println("服務器啟動..."); //1.定義ServerSocket對象進行服務器的端口注冊ServerSocket serverSocket = new ServerSocket(8080); //端口號用于區分不同的進程while (true){//2.監聽客戶端的Socket連接程序Socket socket = serverSocket.accept();  //accept()--》用于阻塞監聽,沒有程序訪問時,停止執行,直到有程序訪問時,繼續執行下一步//3.從socket對象當中獲取到一個字節輸入流對象InputStream iStream = socket.getInputStream();HttpServletRequest request = new HttpServletRequest();BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));String str = reader.readLine();request.setMethod(str.split(" ")[0]);request.setUrl(str.split(" ")[1]);OutputStream outputStream = socket.getOutputStream();HttpServletResponse response = new HttpServletResponse(outputStream);dispatch(request,response);}

代碼逐行解析?

1. 接受客戶端連接

Socket socket = serverSocket.accept();

阻塞等待客戶端連接,返回代表該連接的Socket對象。這是建立TCP通信的第一步。

Tomcat對應實現:
Tomcat的Connector組件(如NioEndpoint)負責監聽端口,使用NIO多路復用或BIO模型處理連接,而非簡單阻塞式accept()。實際會通過線程池高效管理連接。

2. 獲取輸入流

InputStream inputStream = socket.getInputStream();

獲取與客戶端Socket關聯的輸入流,用于讀取HTTP請求的原始字節數據。

Tomcat對應實現:
Tomcat的CoyoteAdapter會解析輸入流,將其封裝為org.apache.coyote.Request對象,處理協議細節(如HTTP頭、Chunked編碼)。

3. 創建請求對象

HttpServletRequest request = new HttpServletRequest();

實例化一個自定義的請求對象,用于承載解析后的請求信息(如URL、方法)。

Tomcat對應實現:
實際創建的是org.apache.catalina.connector.Request對象,包含完整的請求信息(參數、Session、頭信息等),由容器自動填充數據。

4. 包裝緩沖讀取器

BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));

將字節流轉換為字符流,便于按行讀取請求內容。

潛在問題:
直接使用BufferedReader可能無法正確處理二進制數據(如圖片上傳)。Tomcat底層使用ByteBuffer進行高效二進制解析。

5. 讀取請求行

String str = reader.readLine();

讀取HTTP請求的第一行(即請求行),格式為方法 URI 協議版本,例如:
GET /index.html HTTP/1.1

Tomcat對應實現:
通過Http11Processor解析請求行,嚴格校驗協議合規性(如方法名合法性),并提取完整URI和協議版本。

6. 解析HTTP方法與URL

request.setMethod(str.split(" ")[0]); ?// 如"GET"
request.setUrl(str.split(" ")[1]); ? ? // 如"/aa.java"

從請求行中提取HTTP方法和請求路徑,填充到請求對象中。

簡化問題:

未處理URI中的查詢參數(如/user?id=1中的id=1)。

未解析協議版本(如HTTP/1.1與HTTP/2差異)。

未處理可能的異常格式(如空路徑或非法方法)。

7. 獲取輸出流

OutputStream outputStream = socket.getOutputStream();

獲取與客戶端Socket關聯的輸出流,用于向客戶端發送響應數據。

Tomcat對應實現:
輸出流會被包裝為org.apache.coyote.Response,支持緩沖、分塊傳輸(chunked encoding)和自動壓縮(如gzip)。

8. 創建響應對象

HttpServletResponse response = new HttpServletResponse(outputStream);

實例化自定義響應對象,關聯輸出流以便寫入響應內容。

Tomcat對應實現:
實際創建的是org.apache.catalina.connector.Response對象,管理狀態碼、響應頭和內容編碼。

9. 分發請求

dispatch(request, response);

將請求和響應對象傳遞給調度器,執行后續處理(如路由到Servlet或靜態資源)。

Tomcat對應實現:

容器層級路由:依次通過Engine→Host→Context→Wrapper,匹配對應的Servlet。

過濾器鏈執行:在調用Servlet前,執行所有匹配的Filter。

Servlet生命周期:調用service()方法,處理業務邏輯。

請求處理全流程圖示

客戶端│▼
Socket.accept()            // 建立連接│▼
InputStream → 解析請求行    // 讀取HTTP請求基礎信息│▼
創建Request/Response對象   // 封裝協議數據│▼
dispatch() → 路由到Servlet // 業務邏輯處理│▼
OutputStream → 返回響應     // 發送HTTP響應

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

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

相關文章

Android 網絡全棧攻略(五)—— 從 OkHttp 攔截器來看 HTTP 協議二

上一篇我們介紹了 OkHttp 的責任鏈以及第一個內置攔截器 —— 重試與重定向攔截器。本篇我們將剩余四個攔截器的解析做完。 1、橋接攔截器 BridgeInterceptor 作為請求準備和實際發送之間的橋梁&#xff0c;自動處理 HTTP 請求頭等繁瑣工作。比如設置請求內容長度&#xff0c…

JDBC-java操作數據庫

1.基本結構&#xff1a; package com.atguigu.servlets;import java.sql.Connection; import java.sql.DriverManager; import java.sql.Statement;public class JDBCemo {public static void main(String[] args) throws Exception{String url "jdbc:mysql:///mysql&qu…

七彩喜適老化改造:讓每個空間成為長者尊嚴的守護者

隨著我國老齡化進程的加速&#xff0c;居家養老逐漸成為老年人首選的生活方式。 為了讓老年人能夠在熟悉的環境中安享晚年&#xff0c;適老化改造應運而生。 七彩喜作為居家養老服務的創新者&#xff0c;致力于通過科學設計和人性化改造&#xff0c;為老年人提供安全、舒適、…

【動態規劃】5 從一次函數出發推導斜率優化dp

背景 基于例題《任務安排》逐步推導進行斜率優化。 引入 例題&#xff1a;P2365 任務安排 考慮動態規劃。使用 d p i , j dp_{i,j} dpi,j? 表示前 i i i 個任務分了 j j j 段的最小費用。 顯然&#xff0c;有 d p i , j min ? k 1 i ? 1 ( d p i , j , d p k , j…

MySQL中實現大數據量的快速插入

一、SQL語句優化? 1. ?批量插入代替單條插入? ?單條插入會頻繁觸發事務提交和日志寫入&#xff0c;效率極低。?批量插入通過合并多條數據為一條SQL語句&#xff0c;減少網絡傳輸和SQL解析開銷。 -- 低效寫法&#xff1a;逐條插入 INSERT INTO table (col1, col2) VALUE…

C++23中std::span和std::basic_string_view可平凡復制提案解析

文章目錄 一、引言二、相關概念解釋2.1 平凡復制&#xff08;Trivially Copyable&#xff09;2.2 std::span2.3 std::basic_string_view 三、std::span和std::basic_string_view的應用場景3.1 std::span的應用場景3.2 std::basic_string_view的應用場景 四、P2251R1提案對std::…

廣東省省考備考(第十八天5.23)—言語:語句填空題(聽課后強化訓練)

錯題 解析 橫線出現在文段中間&#xff0c;需結合上下文內容進行分析。文段開篇指出逃離北上廣深的話題時而出現&#xff0c;一些人離開大城市回到小城市。隨后通過轉折詞“但”引出橫線內容&#xff0c;且結合橫線后人才傾向于向更發達的地方流動的內容&#xff0c;橫線處應體…

持續更新 ,GPT-4o 風格提示詞案例大全!附使用方式

本文匯集了各類4o風格提示詞的精選案例&#xff0c;從基礎指令到復雜任務&#xff0c;從創意寫作到專業領域&#xff0c;為您提供全方位的參考和靈感。我們將持續更新這份案例集&#xff0c;確保您始終能夠獲取最新、最有效的提示詞技巧。 讓我們一起探索如何通過精心設計的提…

創建型:建造者模式

目錄 1、核心思想 2、實現方式 2.1 模式結構 2.2 工作流程 2.3 實現案例 2.4 變體&#xff1a;鏈式建造者&#xff08;常見于多參數對象&#xff0c;無需指揮者&#xff09; 3、優缺點分析 4、適用場景 1、核心思想 目的&#xff1a;將復雜對象的構建過程與其表示分離…

力扣-長度最小的子數組

1.題目描述 2.題目鏈接 LCR 008. 長度最小的子數組 - 力扣&#xff08;LeetCode&#xff09; 3.題目分析 這道題目我們使用的也是雙指針。我們可以定義兩個指針都指向數組第一個元素&#xff0c;然后使用right指針遍歷原數組&#xff0c;計算left指針到right指針之間的所有元…

JAVA開發工具延長方案

親測穩定的延長方案與避坑指南 真的搞不懂了&#xff0c;說點專業的術語竟然成了 QINQUAN。那就直接點&#xff0c;把這個方案帶給需要的開發者。 延長工具直通車 保姆級教程 延長方案https://mp.weixin.qq.com/s/uajM2Y9Vz6TnolzcLur_bw還是讓大家看看&#xff0c;發什么會被…

SpringAI開發SSE傳輸協議的MCP Server

SpringAI 訪問地址&#xff1a;Spring AI ? Spring AI?是一個面向人工智能工程的應用框架&#xff0c;由Spring團隊推出&#xff0c;旨在將AI能力集成到Java應用中。Spring AI的核心是解決AI集成的根本挑戰&#xff0c;即將企業數據和API與AI模型連接起來?。 MCP…

JAVA動態生成類

在java的加載過程一般都是要預先定義java類,然后通過經過加載->連接->初始化三步。連接過程又可分為三步:驗證->準備->解析。初始化的類是不允許修改。但是在日常的工作中有時候需要動態生成類,那第這種情況怎么辦呢? 可以這么處理: 1、先定義一個空的類,僅…

深入解析Java微服務架構:Spring Boot與Spring Cloud的整合實踐

深入解析Java微服務架構&#xff1a;Spring Boot與Spring Cloud的整合實踐 引言 隨著云計算和分布式系統的快速發展&#xff0c;微服務架構已成為現代軟件開發的主流模式。Java作為企業級應用開發的核心語言&#xff0c;結合Spring Boot和Spring Cloud&#xff0c;為開發者提…

03_基礎篇-NumPy(下):深度學習中的常用操作

03_基礎篇-NumPy&#xff08;下&#xff09;&#xff1a;深度學習中的常用操作 通過上節課的學習&#xff0c;我們已經對NumPy數組有了一定的了解&#xff0c;正所謂實踐出真知&#xff0c;今天我們就以一個圖像分類的項目為例&#xff0c;看看NumPy的在實際項目中都有哪些重要…

時鐘識別項目報告(深度學習、計算機視覺)

深度學習方式 一、模型架構 本模型采用雙任務學習框架&#xff0c;基于經典殘差網絡實現時鐘圖像的小時和分鐘同步識別。 主干網絡 使用預訓練的ResNet18作為特征提取器&#xff0c;移除原分類層&#xff08;fc層&#xff09;&#xff0c;保留全局平均池化后的512維特征向量。…

openai-whisper-asr-webservice接入dify

openai-whisper-asr-webservice提供的asr的api其實并不兼容openai的api&#xff0c;所以在dify中是不能直接添加到語音轉文字的模型中&#xff0c;對比了下兩個api的傳參情況&#xff0c;其實只要改動一處&#xff0c;就能支持&#xff1a; openai兼容的asr調用中formdata中音頻…

解鎖MySQL性能調優:高級SQL技巧實戰指南

高級SQL技巧&#xff1a;解鎖MySQL性能調優的終極指南 開篇 當前&#xff0c;隨著業務系統的復雜化和數據量的爆炸式增長&#xff0c;數據庫性能調優成為了技術人員面臨的核心挑戰之一。尤其是在高并發、大數據量的場景下&#xff0c;SQL 查詢的性能直接影響到整個系統的響應…

JavaScript 性能優化實戰指南

JavaScript 性能優化實戰指南 前言 隨著前端應用復雜度提升&#xff0c;JavaScript 性能瓶頸日益突出。高效的性能優化不僅能提升用戶體驗&#xff0c;還能增強系統穩定性和可維護性。本文系統梳理了 JavaScript 性能優化的核心思路、常見場景和實戰案例&#xff0c;結合代碼…

服務器磁盤按陣列劃分為哪幾類

以下是服務器磁盤陣列&#xff08;RAID&#xff09;的詳細分類及技術解析&#xff0c;基于現行行業標準與實踐應用&#xff1a; 一、主流RAID級別分類 1. ?RAID 0&#xff08;條帶化&#xff09;? ?技術原理?&#xff1a;數據分塊后并行寫入多塊磁盤&#xff0c;無…