解鎖HTTP:從理論到實戰的奇妙之旅

目錄

  • 一、HTTP 協議基礎入門
    • 1.1 HTTP 協議是什么
    • 1.2 HTTP 協議的特點
    • 1.3 HTTP 請求與響應的結構
  • 二、HTTP 應用場景大揭秘
    • 2.1 網頁瀏覽
    • 2.2 API 調用
    • 2.3 文件傳輸
    • 2.4 內容分發網絡(CDN)
    • 2.5 流媒體服務
  • 三、HTTP 應用實例深度剖析
    • 3.1 使用 JavaScript 的 fetch 發起 HTTP 請求
    • 3.2 XMLHttpRequest 的使用
    • 3.3 Python 中使用 requests 庫
    • 3.4 Java 中的 HttpURLConnection
  • 四、HTTP 應用中的常見問題與解決方案
    • 4.1 跨域問題
    • 4.2 HTTP 緩存策略
    • 4.3 性能優化
  • 五、總結與展望
    • 5.1 知識回顧
    • 5.2 未來展望


一、HTTP 協議基礎入門

在當今數字化時代,網絡已經成為人們生活和工作中不可或缺的一部分。而 HTTP 協議作為網絡通信的重要基石,扮演著舉足輕重的角色。無論是我們日常瀏覽網頁、使用手機 APP,還是進行在線購物、觀看視頻等操作,背后都離不開 HTTP 協議的支持。它就像是網絡世界的 “交通規則”,確保了客戶端(如瀏覽器、手機 APP 等)與服務器之間能夠準確、高效地進行數據傳輸。下面,讓我們深入了解 HTTP 協議的基礎知識。

1.1 HTTP 協議是什么

HTTP,即超文本傳輸協議(HyperText Transfer Protocol) ,是一種用于在客戶端和服務器之間傳輸超文本數據的應用層協議。它基于請求 - 響應模型,客戶端向服務器發送請求,服務器接收請求后進行處理,并返回相應的響應。HTTP 協議的主要作用是定義了客戶端和服務器之間通信的規則和格式,使得不同的客戶端和服務器能夠相互理解和交互。

例如,當我們在瀏覽器中輸入一個網址并按下回車鍵時,瀏覽器會作為客戶端向對應的服務器發送 HTTP 請求,請求獲取該網址對應的網頁資源。服務器接收到請求后,會查找并返回該網頁的內容,瀏覽器再將接收到的內容進行解析和渲染,最終呈現出我們看到的網頁。

1.2 HTTP 協議的特點

  • 無連接:在 HTTP/1.x 中,每個請求都會建立一個新的連接,響應之后立即關閉該連接。這意味著每次請求都需要經歷 TCP 連接的建立和拆除過程,會帶來一定的開銷。不過,從 HTTP/1.1 開始引入了持久連接(keep - alive),允許在一個 TCP 連接上進行多個請求和響應,減少了連接建立的次數,提高了傳輸效率 。例如,當我們訪問一個包含多個圖片和腳本的網頁時,如果使用 HTTP/1.1 的持久連接,瀏覽器可以在同一個連接上依次請求這些資源,而不需要為每個資源都重新建立連接。
  • 媒體獨立:HTTP 協議允許傳輸任意類型的數據對象,只要客戶端和服務器能夠理解數據的類型。通過在請求頭或響應頭中使用 Content - Type 字段來標識數據的類型,比如常見的 “text/html” 表示 HTML 頁面,“application/json” 表示 JSON 數據,“image/jpeg” 表示 JPEG 圖片等。這使得 HTTP 協議非常靈活,可以適應各種不同類型的應用場景,無論是傳輸網頁、數據文件還是多媒體內容。
  • 無狀態:HTTP 協議本身是無狀態的,即服務器不會記住客戶端的請求狀態。每個請求都是獨立的,服務器無法區分不同請求是否來自同一個客戶端,也不會保留之前請求的任何信息。這一特點使得服務器的實現相對簡單,不需要維護大量的狀態信息,但也給一些需要保持用戶狀態的應用帶來了挑戰,比如用戶登錄、購物車等功能。為了解決這個問題,通常會使用 Cookie、Session 等技術來保存用戶狀態信息。例如,當用戶登錄一個網站時,服務器會生成一個 Session ID,并將其通過 Cookie 發送給客戶端,客戶端在后續的請求中都會帶上這個 Cookie,服務器就可以根據 Session ID 來識別用戶并維護其狀態。

1.3 HTTP 請求與響應的結構

  • HTTP 請求:一個完整的 HTTP 請求主要由請求行、請求頭部和請求體組成。
    • 請求行:包含請求方法、請求 URL 和 HTTP 版本。常見的請求方法有 GET、POST、PUT、DELETE 等。GET 方法通常用于獲取資源,它會將請求參數附加在 URL 后面,以 “? 參數名 1 = 參數值 1 & 參數名 2 = 參數值 2” 的形式呈現,例如 “https://example.com/search?keyword=apple&page=1”;POST 方法一般用于向服務器提交數據,比如用戶注冊、登錄時提交表單數據,請求參數會放在請求體中,相對 GET 方法更安全,因為參數不會暴露在 URL 中。
    • 請求頭部:是一系列的鍵值對,用于向服務器傳遞額外的信息,比如客戶端的類型(User - Agent)、接受的響應內容類型(Accept)、是否支持壓縮(Accept - Encoding)等。例如,“User - Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36” 表示客戶端是運行在 Windows 10 系統上的 Chrome 瀏覽器。
    • 請求體:并不是所有請求都有請求體,通常在 POST、PUT 等需要向服務器提交數據的請求方法中才會出現。請求體中包含了客戶端發送給服務器的具體數據,比如表單數據、JSON 格式的數據等。
  • HTTP 響應:HTTP 響應同樣由狀態行、響應頭部和響應體組成。
    • 狀態行:包含 HTTP 版本、狀態碼和狀態描述。狀態碼是一個三位數字,用于表示請求的處理結果。常見的狀態碼有 200(表示請求成功,服務器已成功處理請求并返回了相應的資源)、404(表示請求的資源未找到,通常是 URL 輸入錯誤或者資源已被刪除)、500(表示服務器內部錯誤,可能是服務器端的代碼出現異常等原因) 。例如,“HTTP/1.1 200 OK” 表示使用 HTTP/1.1 協議,請求成功。
    • 響應頭部:也是一系列鍵值對,用于向客戶端提供關于響應的額外信息,比如響應內容的類型(Content - Type)、內容長度(Content - Length)、緩存控制(Cache - Control)等。例如,“Content - Type: application/json; charset=utf - 8” 表示響應內容是 JSON 格式,字符編碼為 UTF - 8。
    • 響應體:包含了服務器返回給客戶端的實際數據,比如網頁的 HTML 代碼、JSON 格式的數據、圖片文件的二進制數據等。當我們在瀏覽器中訪問一個網頁時,服務器返回的 HTML 代碼就包含在響應體中,瀏覽器會解析響應體中的內容并將其渲染成可視化的網頁。

二、HTTP 應用場景大揭秘

HTTP 協議憑借其簡單、靈活的特性,在眾多領域得到了廣泛的應用,成為了互聯網通信的重要基礎。下面我們將深入探討 HTTP 在網頁瀏覽、API 調用、文件傳輸、內容分發網絡以及流媒體服務等多個關鍵場景中的具體應用。

2.1 網頁瀏覽

網頁瀏覽是 HTTP 協議最為人熟知的應用場景。當我們在瀏覽器的地址欄中輸入一個網址并按下回車鍵時,一系列復雜而有序的操作便會在幕后悄然展開。

  1. DNS 解析:瀏覽器首先需要將我們輸入的域名(如www.example.com)解析為對應的 IP 地址。這一過程由域名系統(DNS)完成,DNS 就像是互聯網的地址簿,它能夠將人類可讀的域名轉換為計算機能夠理解的 IP 地址。瀏覽器會先檢查本地緩存中是否有該域名對應的 IP 地址,如果沒有,則會向本地 DNS 服務器發送查詢請求。本地 DNS 服務器可能會從其緩存中返回結果,若緩存中沒有,它會繼續向上級 DNS 服務器查詢,直至找到對應的 IP 地址并返回給瀏覽器。
  2. 建立 TCP 連接:在獲取到服務器的 IP 地址后,瀏覽器會與服務器建立 TCP 連接。TCP 連接的建立需要經過三次握手,這一過程確保了客戶端和服務器之間的通信通道是可靠的。瀏覽器會向服務器發送一個 SYN(同步)包,服務器收到后返回一個 SYN + ACK(同步確認)包,最后瀏覽器再發送一個 ACK(確認)包,至此 TCP 連接建立成功。
  3. 發送 HTTP 請求:TCP 連接建立后,瀏覽器會構建一個 HTTP 請求報文并發送給服務器。HTTP 請求報文包含請求行、請求頭部和請求體(對于 GET 請求,通常沒有請求體)。請求行中包含請求方法(如 GET、POST 等)、請求的 URL 以及 HTTP 版本。例如,一個常見的 GET 請求行可能是 “GET /index.html HTTP/1.1”,表示請求獲取服務器上的 index.html 頁面,使用的是 HTTP/1.1 協議。請求頭部則包含了各種額外的信息,如 User - Agent(用于標識瀏覽器類型和版本)、Accept(告訴服務器客戶端能夠接受的響應內容類型)等。
  4. 服務器處理請求并返回響應:服務器接收到 HTTP 請求后,會根據請求的內容進行處理。如果請求的是一個靜態網頁,服務器會直接從文件系統中讀取該網頁的內容;如果是動態網頁,服務器可能需要調用后端的應用程序(如 PHP、Java 等)來生成相應的內容。處理完成后,服務器會構建一個 HTTP 響應報文返回給瀏覽器。響應報文同樣包含狀態行、響應頭部和響應體。狀態行中的狀態碼表示請求的處理結果,如 200 表示請求成功,404 表示請求的資源未找到。響應頭部包含了關于響應的各種信息,如 Content - Type(指定響應內容的類型,如 text/html 表示 HTML 頁面)、Content - Length(響應內容的長度)等。響應體則包含了服務器返回的實際數據,即我們請求的網頁內容。
  5. 瀏覽器解析和渲染頁面:瀏覽器接收到 HTTP 響應后,會首先解析響應頭部,獲取相關信息。然后,根據 Content - Type 字段確定響應體的內容類型,如果是 HTML 頁面,瀏覽器會開始解析 HTML 代碼,構建文檔對象模型(DOM)樹。在解析 HTML 的過程中,如果遇到引用的外部資源(如 CSS 文件、JavaScript 文件、圖片等),瀏覽器會再次發送 HTTP 請求去獲取這些資源。獲取到 CSS 文件后,瀏覽器會構建 CSS 對象模型(CSSOM)樹,將 DOM 樹和 CSSOM 樹結合起來,形成渲染樹。最后,瀏覽器根據渲染樹來繪制頁面,將網頁呈現給用戶。

2.2 API 調用

在當今的軟件開發中,API(應用程序編程接口)調用是 HTTP 協議的另一個重要應用場景。特別是在 RESTful API 架構風格中,HTTP 協議被廣泛用于客戶端與服務器之間的數據交互。

  1. RESTful API 概述:RESTful API 是一種基于 HTTP 協議的、遵循 REST(表述性狀態轉移)架構風格的 Web 服務接口。它將網絡上的資源抽象為一個個的 URL,通過 HTTP 的不同方法(GET、POST、PUT、DELETE 等)來對這些資源進行操作。例如,一個獲取用戶信息的 RESTful API 可能是 “GET /users/123”,表示獲取 ID 為 123 的用戶信息;而 “POST /users” 則可能用于創建一個新用戶,請求體中包含新用戶的相關信息。
  2. HTTP 方法在 API 調用中的應用
    • GET:主要用于獲取資源。例如,客戶端可以通過發送 GET 請求到 “https://api.example.com/products” 來獲取所有產品的列表,服務器會返回包含產品信息的 JSON 或 XML 格式的數據。GET 請求的參數通常附加在 URL 后面,以查詢字符串的形式出現,如 “https://api.example.com/products?category=electronics&page=1”,表示獲取電子產品類別下第一頁的產品列表。
    • POST:常用于向服務器提交數據,創建新的資源。比如在用戶注冊時,客戶端會將用戶填寫的注冊信息(用戶名、密碼、郵箱等)以 JSON 或表單數據的形式放在請求體中,通過 POST 請求發送到 “https://api.example.com/register”,服務器接收到請求后會根據這些數據在數據庫中創建一個新的用戶記錄。
    • PUT:用于更新資源。例如,當需要更新用戶 ID 為 123 的用戶信息時,客戶端可以發送一個 PUT 請求到 “https://api.example.com/users/123”,請求體中包含更新后的用戶信息,服務器會根據這些信息對數據庫中相應的用戶記錄進行更新。
    • DELETE:用于刪除資源。客戶端發送 DELETE 請求到 “https://api.example.com/products/456”,服務器就會刪除 ID 為 456 的產品記錄。
  3. API 調用的流程:客戶端首先根據需求構建 HTTP 請求,設置正確的請求方法、URL、請求頭部和請求體(如果需要)。然后,將請求發送到服務器。服務器接收到請求后,會對請求進行驗證和處理,根據請求的內容執行相應的業務邏輯,如查詢數據庫、調用其他服務等。處理完成后,服務器會返回一個 HTTP 響應,響應中包含狀態碼、響應頭部和響應體。客戶端接收到響應后,會根據狀態碼判斷請求是否成功,如果成功,會解析響應體中的數據進行后續處理;如果失敗,會根據狀態碼和響應體中的錯誤信息進行相應的錯誤處理。例如,當客戶端調用一個獲取用戶信息的 API 時,如果服務器返回狀態碼 200,客戶端會解析響應體中的用戶信息并展示給用戶;如果返回 401(未授權),客戶端可能會提示用戶需要重新登錄。

2.3 文件傳輸

HTTP 協議也廣泛應用于文件的上傳和下載場景,為用戶提供了便捷的文件傳輸方式。

  1. 文件下載
    • 設置響應頭:當服務器需要向客戶端提供文件下載時,首先要設置正確的 HTTP 響應頭。其中,Content - Type 字段用于指定文件的類型,比如 “application/pdf” 表示 PDF 文件,“image/jpeg” 表示 JPEG 圖片。Content - Disposition 字段則用于指定文件的下載方式和文件名,通常設置為 “attachment; filename=“example.pdf””,這樣瀏覽器會將文件作為附件下載,并將文件名命名為 example.pdf。
    • 發送文件數據:服務器設置好響應頭后,會將文件數據以流的形式發送給客戶端。例如,在 Node.js 中,可以使用以下代碼實現文件下載:
const express = require('express');
const app = express();
const fs = require('fs');app.get('/download', function (req, res) {const file = 'example.pdf';const filePath = './' + file;res.setHeader('Content-Type', 'application/pdf');res.setHeader('Content-Disposition', 'attachment; filename=\"' + file + '\"');const fileStream = fs.createReadStream(filePath);fileStream.pipe(res);
});app.listen(3000, function () {console.log('Server running on port 3000');
});

客戶端在瀏覽器中訪問 “http://localhost:3000/download” 時,就會觸發文件下載。

  1. 文件上傳
    • HTML 表單上傳:最常見的文件上傳方式是通過 HTML 表單。在 HTML 表單中,設置 enctype 屬性為 “multipart/form - data”,表示以多部分表單數據的形式提交表單,這樣就可以包含文件數據。例如:
<form action="/upload" method="post" enctype="multipart/form - data"><input type="file" name="fileToUpload"><input type="submit" value="Upload File">
</form>

當用戶選擇文件并點擊提交按鈕后,瀏覽器會將文件數據以及表單中的其他數據一起發送到服務器指定的 “/upload” 路徑。

  • 服務器端處理:服務器端需要使用相應的編程語言和框架來處理文件上傳請求。以 Node.js 和 Express 框架為例,可以使用 multer 中間件來處理文件上傳:
const express = require('express');
const app = express();
const multer = require('multer');const storage = multer.diskStorage({destination: function (req, file, cb) {cb(null, 'uploads/');},filename: function (req, file, cb) {cb(null, Date.now() + '-' + file.originalname);}
});const upload = multer({ storage: storage });app.post('/upload', upload.single('fileToUpload'), function (req, res) {res.send('File uploaded successfully!');
});app.listen(3000, function () {console.log('Server running on port 3000');
});

上述代碼中,multer 中間件將上傳的文件存儲到服務器的 “uploads/” 目錄下,并為文件重新命名以避免文件名沖突。

2.4 內容分發網絡(CDN)

內容分發網絡(CDN)是一種通過在多個地理位置分布緩存節點,將內容快速分發到用戶附近的技術,HTTP 協議在其中扮演著關鍵角色。

  1. CDN 的工作原理
    • 用戶請求:當用戶在瀏覽器中請求一個網頁或其他內容時,首先會進行 DNS 解析。由于 CDN 的介入,DNS 服務器會根據 CDN 的智能負載均衡策略,返回距離用戶最近的 CDN 緩存服務器的 IP 地址。
    • 緩存服務器響應:用戶的請求被定向到 CDN 緩存服務器后,緩存服務器會檢查本地是否有用戶請求的內容。如果有,直接將內容返回給用戶;如果沒有,緩存服務器會向源服務器發送 HTTP 請求,獲取內容。
    • 內容更新與緩存:緩存服務器從源服務器獲取到內容后,會將內容存儲到本地緩存中,以便后續有相同請求時可以直接從本地返回,同時將內容返回給用戶。這樣,當下一個用戶請求相同內容時,就可以從該緩存服務器快速獲取,減少了數據傳輸的延遲和源服務器的壓力。
  2. CDN 的優勢
    • 提高訪問速度:通過將內容緩存到離用戶更近的節點,大大減少了數據傳輸的距離和時間,提高了內容的加載速度。例如,對于一個全球訪問的網站,位于不同地區的用戶都可以從離自己最近的 CDN 節點獲取內容,避免了跨地區、跨網絡的長距離傳輸。
    • 減輕源服務器壓力:大量的用戶請求由 CDN 緩存服務器處理,只有當緩存服務器沒有請求的內容時才會回源到源服務器,從而減輕了源服務器的負載,使其能夠更好地處理核心業務邏輯。
    • 增強網絡穩定性:CDN 具有多個緩存節點,即使某個節點出現故障,其他節點仍然可以提供服務,提高了網絡服務的可用性和穩定性。例如,在突發流量情況下,CDN 可以通過負載均衡將請求分配到不同的節點,確保服務的正常運行。

2.5 流媒體服務

在視頻、音頻流服務中,HTTP 協議同樣發揮著重要作用,為用戶提供流暢的媒體播放體驗。

  1. HTTP Live Streaming(HLS)技術:這是一種基于 HTTP 協議的流媒體傳輸技術,由蘋果公司開發,廣泛應用于視頻點播和直播服務。HLS 的核心原理是將媒體流分割成一系列小的.ts(MPEG - 2 Transport Stream)格式的文件片段,并通過一個.m3u8 格式的播放列表文件來索引這些片段。
    • 工作流程:首先,視頻內容會被編碼為多個不同質量(不同分辨率、比特率)的流,然后每個流被分割成多個小的.ts 文件,每個.ts 文件通常包含幾秒鐘的媒體內容。接著,會生成一個主.m3u8 播放列表文件,該文件列出了不同質量流的子.m3u8 文件的位置。每個子.m3u8 文件則列出了對應質量流的.ts 文件的順序和位置。客戶端請求主.m3u8 文件后,會根據當前網絡狀況選擇合適質量的子.m3u8 文件,然后按照順序逐個請求對應的.ts 文件進行播放。例如,當網絡帶寬充足時,客戶端會選擇高分辨率、高比特率的流進行播放;當網絡帶寬變差時,會自動切換到低分辨率、低比特率的流,以保證播放的流暢性。
    • 優勢:HLS 的優勢在于其廣泛的兼容性,幾乎所有的 Web 瀏覽器和移動設備都支持 HLS 播放。同時,它利用了 HTTP 協議的特性,無需專門的流媒體服務器,降低了部署成本,并且可以方便地穿越防火墻和 NAT(網絡地址轉換)設備。
  2. HTTP Range 請求:在流媒體播放中,為了實現更高效的播放和斷點續傳功能,HTTP 協議中的 Range 請求起到了重要作用。客戶端可以通過在 HTTP 請求頭中添加 Range 字段,指定請求媒體文件的某個字節范圍。例如,“Range: bytes=0 - 1023” 表示請求文件的第 0 字節到第 1023 字節的內容。服務器接收到帶有 Range 請求的 HTTP 請求后,會根據請求的字節范圍返回相應的數據片段,并在響應頭中添加 Content - Range 字段,告知客戶端返回的數據范圍。這樣,客戶端就可以實現按需加載媒體內容,在網絡不穩定或播放中斷后能夠從上次中斷的位置繼續播放,提升了用戶的觀看體驗。

三、HTTP 應用實例深度剖析

了解了 HTTP 協議的基礎知識以及其豐富的應用場景后,接下來讓我們通過具體的代碼示例,深入探究 HTTP 在不同編程場景下的實際應用。

3.1 使用 JavaScript 的 fetch 發起 HTTP 請求

在現代 Web 開發中,fetch API 是 JavaScript 中用于發起 HTTP 請求的常用方式,它提供了一種更簡潔、靈活的接口,相比傳統的 XMLHttpRequest 對象,fetch API 的語法更加直觀,并且支持 Promise,使得異步操作的處理更加方便。
發送 GET 請求

fetch('https://api.example.com/data').then(response => {if (!response.ok) {throw new Error('Network response was not ok');}return response.json();}).then(data => {console.log('Data:', data);}).catch(error => {console.error('Error:', error);});

解釋:

  • fetch(‘https://api.example.com/data’):這行代碼發起一個 GET 請求到指定的 URL。fetch 函數返回一個 Promise 對象,該 Promise 會在請求完成后被 resolve,其結果是一個 Response 對象。
  • if (!response.ok):檢查響應狀態碼,如果狀態碼不是 200 - 299 之間的成功狀態碼,response.ok會返回 false,此時拋出一個錯誤,提示網絡響應不正常。
  • return response.json():如果響應狀態正常,將響應數據解析為 JSON 格式,并返回一個新的 Promise,該 Promise 會在解析完成后被 resolve,其結果是解析后的 JSON 數據。
  • console.log(‘Data:’, data):在成功獲取并解析 JSON 數據后,將數據打印到控制臺。
  • catch(error => console.error(‘Error:’, error)):捕獲請求過程中可能出現的任何錯誤,并將錯誤信息打印到控制臺。

發送 POST 請求

const url = 'https://api.example.com/submit';
const data = {name: 'John',age: 30
};fetch(url, {method: 'POST',headers: {'Content-Type': 'application/json'},body: JSON.stringify(data)
}).then(response => {if (!response.ok) {throw new Error('Network response was not ok');}return response.json();}).then(data => {console.log('Response:', data);}).catch(error => {console.error('Error:', error);});

解釋:

  • const url = ‘https://api.example.com/submit’;:指定 POST 請求的目標 URL。
  • const data = { name: ‘John’, age: 30 };:定義要發送的數據,這里是一個包含姓名和年齡的對象。
  • fetch(url, {… }):發起 POST 請求,第二個參數是一個配置對象,用于設置請求的各種屬性。
  • method: ‘POST’:明確指定請求方法為 POST。
  • headers: {‘Content-Type’: ‘application/json’}:設置請求頭,Content-Type為application/json表示發送的數據是 JSON 格式。
  • body: JSON.stringify(data):將數據對象轉換為 JSON 字符串,并作為請求體發送。

后續的then和catch部分與 GET 請求類似,用于處理響應和錯誤。

3.2 XMLHttpRequest 的使用

XMLHttpRequest 是早期 JavaScript 中用于發送 HTTP 請求的主要方式,雖然現在 fetch API 更為常用,但了解 XMLHttpRequest 的使用方法仍然很有必要,特別是在處理一些兼容性問題時。

function sendRequest() {const xhr = new XMLHttpRequest();const url = 'https://api.example.com/data';xhr.open('GET', url, true);xhr.onreadystatechange = function () {if (xhr.readyState === 4) {if (xhr.status === 200) {console.log('Response:', xhr.responseText);} else {console.error('Error:', xhr.statusText);}}};xhr.send();
}sendRequest();

解釋:

  • const xhr = new XMLHttpRequest();:創建一個 XMLHttpRequest 對象實例。
  • xhr.open(‘GET’, url, true);:初始化請求,設置請求方法為 GET,請求 URL 為https://api.example.com/data,并設置為異步請求(第三個參數為true表示異步)。
  • xhr.onreadystatechange:這是一個事件處理函數,每當xhr.readyState狀態發生變化時都會觸發。readyState有 5 個可能的值:0(未初始化)、1(已初始化)、2(已發送)、3(接收數據)、4(完成)。
  • if (xhr.readyState === 4):當readyState為 4 時,表示請求已完成。
  • if (xhr.status === 200):檢查響應狀態碼,如果狀態碼為 200,表示請求成功,將響應數據(xhr.responseText)打印到控制臺;否則,打印錯誤信息(xhr.statusText)。
  • xhr.send();:發送請求。

3.3 Python 中使用 requests 庫

Python 的 requests 庫是一個功能強大且易于使用的 HTTP 客戶端庫,它大大簡化了發送 HTTP 請求的過程,使得 Python 開發者能夠方便地與 Web 服務進行交互。
發送 GET 請求

import requestsurl = 'https://api.example.com/data'
response = requests.get(url)if response.status_code == 200:data = response.json()print('Data:', data)
else:print('Request failed with status code:', response.status_code)

解釋:

  • import requests:導入 requests 庫。
  • url = ‘https://api.example.com/data’:指定請求的 URL。
  • response = requests.get(url):使用requests.get方法發送 GET 請求,并將響應對象賦值給response。
  • if response.status_code == 200:檢查響應狀態碼,如果狀態碼為 200,表示請求成功。
  • data = response.json():如果請求成功,將響應內容解析為 JSON 格式的數據。
  • print(‘Data:’, data):打印解析后的數據。
  • 否則,打印請求失敗的狀態碼。

發送 POST 請求

import requestsurl = 'https://api.example.com/submit'
data = {'name': 'John','age': 30
}response = requests.post(url, json=data)if response.status_code == 200:result = response.json()print('Response:', result)
else:print('Request failed with status code:', response.status_code)

解釋:

  • url = ‘https://api.example.com/submit’:指定 POST 請求的 URL。
  • data = {‘name’: ‘John’, ‘age’: 30}:定義要發送的數據,這里是一個字典。
  • response = requests.post(url, json=data):使用requests.post方法發送 POST 請求,json=data表示將數據以 JSON 格式發送。

后續的狀態碼檢查和響應處理與 GET 請求類似。

3.4 Java 中的 HttpURLConnection

在 Java 中,HttpURLConnection是一個用于發送 HTTP 請求和接收 HTTP 響應的類,它是 Java 標準庫的一部分,提供了對 HTTP 協議的基本支持。

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;public class HttpExample {public static void main(String[] args) {// 發送GET請求sendGetRequest();// 發送POST請求sendPostRequest();}private static void sendGetRequest() {try {URL url = new URL("https://api.example.com/data");HttpURLConnection connection = (HttpURLConnection) url.openConnection();connection.setRequestMethod("GET");int responseCode = connection.getResponseCode();if (responseCode == HttpURLConnection.HTTP_OK) {BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));String inputLine;StringBuilder response = new StringBuilder();while ((inputLine = in.readLine()) != null) {response.append(inputLine);}in.close();System.out.println("GET Response: " + response.toString());} else {System.out.println("GET Request failed with response code: " + responseCode);}connection.disconnect();} catch (IOException e) {e.printStackTrace();}}private static void sendPostRequest() {try {URL url = new URL("https://api.example.com/submit");HttpURLConnection connection = (HttpURLConnection) url.openConnection();connection.setRequestMethod("POST");connection.setDoOutput(true);String postData = "name=John&age=30";OutputStream outputStream = connection.getOutputStream();outputStream.write(postData.getBytes());outputStream.flush();outputStream.close();int responseCode = connection.getResponseCode();if (responseCode == HttpURLConnection.HTTP_OK) {BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));String inputLine;StringBuilder response = new StringBuilder();while ((inputLine = in.readLine()) != null) {response.append(inputLine);}in.close();System.out.println("POST Response: " + response.toString());} else {System.out.println("POST Request failed with response code: " + responseCode);}connection.disconnect();} catch (IOException e) {e.printStackTrace();}}
}

解釋:

  • 發送 GET 請求
    • URL url = new URL(“https://api.example.com/data”);:創建一個 URL 對象,指定請求的地址。
    • HttpURLConnection connection = (HttpURLConnection) url.openConnection();:打開與指定 URL 的連接,并將其轉換為HttpURLConnection對象。
    • connection.setRequestMethod(“GET”);:設置請求方法為 GET。
    • int responseCode = connection.getResponseCode();:獲取響應狀態碼。
    • 如果狀態碼為HttpURLConnection.HTTP_OK(即 200),則通過BufferedReader讀取響應內容,并將其打印出來;否則,打印請求失敗的狀態碼。
    • 最后,斷開連接。

發送 POST 請求
- 與 GET 請求類似,先創建 URL 和HttpURLConnection對象,并設置請求方法為 POST。
- connection.setDoOutput(true);:表示要向服務器輸出數據。
- String postData = “name=John&age=30”;:定義要發送的 POST 數據,這里是一個表單格式的數據。
- 通過OutputStream將數據寫入連接,并進行刷新和關閉操作。
- 后續的響應處理與 GET 請求相同。

四、HTTP 應用中的常見問題與解決方案

在 HTTP 應用的開發和使用過程中,不可避免地會遇到各種問題,這些問題可能會影響應用的性能、穩定性和用戶體驗。下面我們將探討一些 HTTP 應用中常見的問題,并給出相應的解決方案。

4.1 跨域問題

  • 跨域的概念:跨域是指瀏覽器試圖從一個源(協議、域名、端口)去請求另一個不同源的資源時所發生的情況。例如,當一個網頁的域名為http://example.com,而它試圖請求http://another.com的資源時,就會出現跨域問題。這是因為瀏覽器的同源策略限制,同源策略是瀏覽器的一種安全機制,它要求網頁只能與相同源的服務器進行交互,以防止惡意網站竊取用戶數據 。例如,一個惡意網站可能試圖通過 JavaScript 代碼讀取用戶在銀行網站上的敏感信息,如果沒有同源策略,這種攻擊就很容易實現。
  • 產生原因:同源策略的存在導致了跨域問題的產生。瀏覽器認為不同源的請求可能存在安全風險,因此默認情況下會阻止跨域請求。具體來說,當協議、域名或端口中的任何一個不同時,就會被視為跨域。例如,http://example.com和https://example.com(協議不同)、http://example.com和http://www.example.com(域名不同,雖然看似只是多了www,但在瀏覽器看來是不同的域名)、http://example.com:80和http://example.com:8080(端口不同)之間的請求都會觸發跨域問題。
  • 常見解決方案
    • CORS(跨域資源共享):這是一種 W3C 標準,通過在服務器端設置特定的響應頭來允許跨域請求。例如,在 Node.js 的 Express 框架中,可以使用如下代碼設置 CORS:
const express = require('express');
const app = express();
app.use((req, res, next) => {res.setHeader('Access-Control-Allow-Origin', '*');//允許所有源訪問,也可以指定具體的源,如'http://allowed.com'res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');//允許的請求方法res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');//允許的請求頭next();
});
// 其他路由和處理邏輯
app.listen(3000, () => {console.log('Server running on port 3000');
});

CORS 分為簡單請求和復雜請求,簡單請求(如 GET、POST 請求且請求頭不超出特定范圍)瀏覽器會直接發送請求,服務器返回帶有Access-Control-Allow-Origin等響應頭的響應,瀏覽器判斷是否允許訪問;復雜請求(如 PUT、DELETE 請求或 Content-Type 為 application/json 等)瀏覽器會先發送一個預檢請求(OPTIONS 請求),詢問服務器當前域名是否在許可名單中以及可以使用哪些 HTTP 動詞和頭信息字段,服務器返回允許的信息后,瀏覽器才會發送正式請求。

  • JSONP(JSON with Padding):利用<script>標簽不受同源策略限制的特點來實現跨域請求。它只能發送 GET 請求,其原理是在頁面中動態創建一個<script>標簽,將請求的 URL 作為<script>標簽的src屬性值,服務器返回的數據會包裹在一個指定的回調函數中。例如:
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8">
</head><body><script>function handleResponse(data) {console.log('Received data:', data);}</script><script src="https://api.example.com/data?callback=handleResponse"></script>
</body></html>

服務器接收到請求后,會返回類似handleResponse({ “key”: “value” });這樣的內容,瀏覽器解析<script>標簽時會執行這個回調函數,從而實現數據的接收和處理。

4.2 HTTP 緩存策略

  • 強緩存:強緩存是指瀏覽器在緩存有效期內直接從本地緩存中讀取資源,而不向服務器發送請求。它主要通過 HTTP 頭部的Expires和Cache-Control來控制。
    • Expires:是 HTTP/1.0 的規范,用于表示資源的過期時間,值是一個絕對時間,由服務器端返回。例如,Expires: Thu, 15 Apr 2024 12:00:00 GMT表示資源在這個時間之后過期。瀏覽器在下次請求該資源時,會對比當前時間和Expires指定的時間,如果當前時間在過期時間之前,則直接使用本地緩存。但它的缺點是依賴客戶端和服務器的時間同步,如果時間不一致,可能會導致緩存命中誤差。
    • Cache-Control:是 HTTP/1.1 的規范,使用相對時間格式,優先級高于Expires。常見的指令有max-age(指定資源的最大緩存時間,單位為秒)、no-cache(每次請求都需要向服務器驗證,并非不緩存)、no-store(不緩存,每次都從服務器獲取)等。例如,Cache-Control: max-age=3600表示資源可以在客戶端緩存 1 小時,在這 1 小時內瀏覽器再次請求該資源時,直接從本地緩存讀取,不會向服務器發送請求。
  • 協商緩存:當瀏覽器沒有命中強緩存時,會向服務器發送請求,驗證協商緩存是否命中。如果緩存命中,服務器返回 304 狀態碼,瀏覽器繼續使用本地緩存;如果未命中,服務器返回新的資源。協商緩存通過 HTTP 頭部的Last-Modified和ETag來控制。
    • Last-Modified:表示資源的最后修改時間,由服務器返回。瀏覽器在第一次請求資源時,服務器會在響應頭中包含Last-Modified字段,如Last-Modified: Wed, 14 Apr 2024 10:00:00 GMT。瀏覽器下次請求時,會在請求頭中帶上If-Modified-Since字段,其值為上次服務器返回的Last-Modified時間,服務器接收到請求后,對比If-Modified-Since和資源的實際最后修改時間,如果時間一致,說明資源未被修改,返回 304 狀態碼,瀏覽器使用本地緩存;如果不一致,返回新的資源。
    • ETag:是資源的唯一標識符,由服務器生成并返回。當資源發生變化時,ETag也會改變。它彌補了Last-Modified的一些不足,比如文件內容未改變但修改時間可能因其他原因改變,或者修改時間的精度有限(秒級)。瀏覽器第一次請求資源時,服務器返回ETag,如ETag: “123abc”,下次請求時,瀏覽器在請求頭中帶上If-None-Match字段,值為上次服務器返回的ETag,服務器對比If-None-Match和當前資源的ETag,如果一致,返回 304 狀態碼,否則返回新的資源。
  • 相關 HTTP 頭部的設置:在服務器端設置合適的 HTTP 頭部來控制緩存策略非常重要。例如,在 Node.js 的 Express 框架中,可以這樣設置:
const express = require('express');
const app = express();
app.get('/data', (req, res) => {// 設置強緩存,緩存1小時res.setHeader('Cache-Control', 'public, max-age=3600');// 設置協商緩存,假設生成的ETag為"123abc"res.setHeader('ETag', '123abc');// 返回數據res.send('Some data');
});
app.listen(3000, () => {console.log('Server running on port 3000');
});

4.3 性能優化

  • 減少請求次數:HTTP 請求會帶來一定的開銷,包括建立 TCP 連接、傳輸請求和響應數據等,減少請求次數可以顯著提高應用性能。
    • 合并文件:將多個 CSS 文件合并成一個,多個 JavaScript 文件合并成一個。例如,在 Webpack 構建工具中,可以通過配置將多個 JavaScript 模塊打包成一個文件,這樣在頁面加載時,只需要一個 HTTP 請求來獲取這個合并后的文件,而不是分別請求多個文件。
    • 使用雪碧圖(CSS Sprites):對于網頁中使用的多個小圖標,可以將它們合并成一張大圖片,然后通過 CSS 的background-position屬性來定位顯示不同的圖標。這樣可以將多個小圖標的請求合并為一個大圖片的請求,減少了 HTTP 請求數量。比如,將關閉圖標、菜單圖標、搜索圖標等合并成一張雪碧圖,在 CSS 中通過設置不同的background-position來顯示對應的圖標。
  • 壓縮數據:對 HTTP 傳輸的數據進行壓縮可以減小數據傳輸量,提高傳輸速度。
    • 啟用 Gzip 壓縮:服務器可以對響應數據進行 Gzip 壓縮,大多數瀏覽器都支持 Gzip 解壓。在 Node.js 的 Express 框架中,可以使用compression中間件來啟用 Gzip 壓縮:
const express = require('express');
const compression = require('compression');
const app = express();
app.use(compression());
// 其他路由和處理邏輯
app.listen(3000, () => {console.log('Server running on port 3000');
});

這樣,服務器在返回響應數據時,會先對數據進行 Gzip 壓縮,然后發送給瀏覽器,瀏覽器接收到壓縮數據后會自動解壓。

  • 圖片優化:對于圖片,可以采用合適的圖片格式(如 JPEG 適用于照片,PNG 適用于圖標和透明圖片,WebP 格式具有更好的壓縮比),并進行無損壓縮,去除圖片中的元數據、適度降低分辨率等,以減小圖片文件的大小 。例如,使用 ImageOptim 等工具對圖片進行優化,在保證圖片質量可接受的前提下,減小圖片的體積,從而減少圖片傳輸時的數據量。
  • 優化緩存策略:合理設置 HTTP 緩存策略,如前文所述的強緩存和協商緩存,可以減少不必要的請求,提高頁面加載速度。對于不經常變化的靜態資源,設置較長的緩存時間,讓瀏覽器可以多次使用本地緩存;對于動態資源,根據其變化頻率,合理設置緩存策略,避免緩存過期后頻繁請求服務器。例如,對于網站的 CSS 和 JavaScript 文件,如果內容更新不頻繁,可以設置較長的max-age值,如Cache-Control: max-age=86400(一天),這樣在一天內,用戶再次訪問網站時,瀏覽器可以直接從本地緩存讀取這些文件,無需向服務器請求。
  • 使用 CDN:CDN(內容分發網絡)通過在多個地理位置分布緩存節點,將內容緩存到離用戶更近的地方,用戶請求內容時可以從最近的 CDN 節點獲取,減少了數據傳輸的距離和時間。例如,將網站的圖片、CSS、JavaScript 等靜態資源部署到 CDN 上,當用戶訪問網站時,這些資源可以從離用戶最近的 CDN 節點快速加載,提高了頁面的加載速度,同時也減輕了源服務器的壓力 。許多大型互聯網公司都使用 CDN 來加速內容分發,如亞馬遜的 CloudFront、百度的 CDN 服務等。

五、總結與展望

HTTP 協議作為互聯網通信的基石,在現代網絡應用中扮演著舉足輕重的角色。通過對 HTTP 應用實例的深入探討,我們不僅對 HTTP 協議的工作原理和應用場景有了更全面的理解,還掌握了在實際開發中運用 HTTP 協議進行數據交互的方法,以及應對常見問題的策略。展望未來,隨著互聯網技術的不斷發展,HTTP 協議也將持續演進,為我們帶來更高效、更安全、更智能的網絡體驗。

5.1 知識回顧

HTTP 協議作為超文本傳輸協議,是互聯網應用層的核心協議之一,基于請求 - 響應模型實現客戶端與服務器之間的數據傳輸。它具有無連接、媒體獨立、無狀態等特點,這些特性使得 HTTP 協議簡單靈活,能夠適應各種復雜的網絡環境和應用需求 。一個完整的 HTTP 請求包含請求行、請求頭部和請求體,而 HTTP 響應則由狀態行、響應頭部和響應體組成。在實際應用中,我們通過不同的請求方法(如 GET、POST、PUT、DELETE 等)來實現對資源的獲取、創建、更新和刪除等操作。

HTTP 協議廣泛應用于網頁瀏覽、API 調用、文件傳輸、內容分發網絡(CDN)以及流媒體服務等多個領域。在網頁瀏覽中,瀏覽器通過 HTTP 協議與服務器進行交互,獲取網頁的 HTML、CSS、JavaScript 等資源,并將其渲染成用戶可見的頁面;在 API 調用場景中,HTTP 協議為客戶端與服務器之間的數據交互提供了標準的接口,使得不同的應用程序能夠方便地進行數據共享和業務協作;文件傳輸時,HTTP 協議支持文件的上傳和下載,滿足了用戶在不同設備之間傳輸數據的需求;CDN 利用 HTTP 協議將內容緩存到離用戶更近的節點,從而提高了內容的分發速度和用戶的訪問體驗;流媒體服務則借助 HTTP 協議實現了視頻和音頻的實時傳輸,讓用戶能夠流暢地觀看在線視頻和收聽在線音頻。

在 HTTP 應用過程中,我們也會遇到一些常見問題。比如跨域問題,由于瀏覽器的同源策略限制,不同源的請求會受到限制,我們可以通過 CORS(跨域資源共享)和 JSONP(JSON with Padding)等技術來解決;HTTP 緩存策略對于提高應用性能至關重要,強緩存和協商緩存的合理運用可以減少不必要的請求,提高頁面加載速度,我們需要根據資源的特性和更新頻率來設置合適的緩存頭;性能優化方面,減少請求次數(如合并文件、使用雪碧圖)、壓縮數據(啟用 Gzip 壓縮、優化圖片)、優化緩存策略以及使用 CDN 等方法都能夠顯著提升 HTTP 應用的性能,為用戶提供更流暢的體驗。

5.2 未來展望

隨著互聯網技術的飛速發展,HTTP 協議也在不斷演進以適應新的需求和挑戰。未來,HTTP 協議有望在以下幾個方面取得重要進展:

  • 性能提升:HTTP/3 協議基于 QUIC 協議,相比之前的版本,它在連接建立速度、傳輸效率和抗丟包能力等方面都有顯著提升。隨著 HTTP/3 的逐漸普及,用戶將能夠享受到更快的網頁加載速度和更穩定的網絡連接。例如,在移動網絡環境下,HTTP/3 能夠更好地應對網絡波動,減少視頻卡頓和加載時間,為用戶提供更流暢的在線視頻觀看體驗。
  • 安全性增強:隨著網絡安全威脅的日益增多,HTTP 協議將更加注重數據的加密和用戶身份的驗證。未來可能會引入更高級的加密算法和更完善的身份驗證機制,確保數據在傳輸過程中的安全性和完整性,防止用戶數據被竊取和篡改。比如,在電子商務和在線支付等場景中,更強大的安全機制可以有效保護用戶的敏感信息,提升用戶對在線交易的信任度。
  • 智能化與個性化:結合人工智能和大數據技術,HTTP 協議將實現更智能的請求處理和內容分發。服務器可以根據用戶的行為習慣、興趣偏好等數據,為用戶提供更加個性化的內容和服務。例如,在新聞資訊類應用中,服務器可以根據用戶的瀏覽歷史和點贊記錄,精準推送用戶感興趣的新聞內容,提高用戶的滿意度和使用粘性。
  • 與新技術融合:HTTP 協議將與 WebAssembly、WebSocket 等新技術進行深度融合。WebAssembly 允許在瀏覽器中高效運行二進制代碼,提升 Web 應用的性能和功能;WebSocket 則實現了全雙工通信,使得 Web 應用能夠實現實時交互。HTTP 與這些技術的結合,將為 Web 應用帶來更豐富的功能和更好的用戶體驗。比如,在在線游戲和實時協作辦公等場景中,WebSocket 與 HTTP 的協同工作可以實現實時的數據傳輸和交互,提高游戲的流暢性和辦公的效率。
  • 物聯網應用拓展:隨著物聯網的快速發展,越來越多的設備將接入互聯網。HTTP 協議作為一種廣泛應用的網絡協議,將在物聯網領域發揮重要作用,實現設備之間的數據交互和遠程控制。例如,智能家居設備可以通過 HTTP 協議與服務器進行通信,用戶可以通過手機應用遠程控制家中的智能電器,實現智能化的生活體驗。

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

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

相關文章

uvm_config_db examples

通過uvm_config_db類訪問的UVM配置數據庫,是在多個測試平臺組件之間傳遞不同對象的絕佳方式。 methods 有兩個主要函數用于從數據庫中放入和檢索項目,分別是 set() 和 get()。 static function void set ( uvm_component cntxt,string inst_name,string …

(C++)任務管理系統(文件存儲)(正式版)(迭代器)(list列表基礎教程)(STL基礎知識)

目錄 前言&#xff1a; 源代碼&#xff1a; 代碼解析&#xff1a; 一.頭文件和命名空間 1. #include - 輸入輸出功能2. #include - 鏈表容器3. #include - 字符串處理4. using namespace std; - 命名空間 可視化比喻&#xff1a;建造房子 &#x1f3e0; 二.menu()函數 …

Java 中的異步編程詳解

前言 在現代軟件開發中&#xff0c;異步編程&#xff08;Asynchronous Programming&#xff09; 已經成為構建高性能、高并發應用程序的關鍵技術之一。Java 作為一門廣泛應用于后端服務開發的語言&#xff0c;在其發展過程中不斷引入和優化異步編程的支持。從最初的 Thread 和…

MySQL邏輯刪除與唯一索引沖突解決

問題背景 在MySQL數據庫設計中&#xff0c;邏輯刪除&#xff08;軟刪除&#xff09;是一種常見的實踐&#xff0c;它通過設置標志位&#xff08;如is_delete&#xff09;來標記記錄被"刪除"&#xff0c;而不是實際刪除數據。然而&#xff0c;當表中存在唯一約束時&am…

php命名空間用正斜杠還是反斜杠?

在PHP中&#xff0c;命名空間使用反斜杠&#xff08;\&#xff09;作為分隔符&#xff0c;這是PHP語言規范明確規定的。反斜杠在命名空間中扮演路徑分隔的角色&#xff0c;用于區分不同層級的命名空間。 具體說明&#xff1a;語法規則 PHP命名空間使用反斜杠&#xff08;\&…

《從依賴糾纏到接口協作:ASP.NET Core注入式開發指南》

在C#的ASP.NET Core開發中&#xff0c;依賴注入絕非簡單的技術技巧&#xff0c;而是重構代碼關系的底層邏輯。它像一套隱形的神經網絡&#xff0c;讓程序模塊擺脫硬編碼的束縛&#xff0c;在運行時實現動態連接&#xff0c;從而為系統注入可測試、可進化的核心生命力。理解其深…

星云ERP本地環境搭建筆記

看到星云ERP兩個比較實用的功能&#xff0c;編號規則和打印模板&#xff0c;如下圖所示&#xff0c;于是本地跑起來學習學習。開發環境必備&#xff1a;1. JDK 1.82. MySQL 5.73. Redis 44. RabbitMQ 3.12.45. nodejs 206. pnpm 9.7.1 (npm install -g pnpm9.7.1)其他開發工具&…

RedisJSON 的 `JSON.ARRAPPEND`一行命令讓數組動態生長

1 、 為什么選擇 JSON.ARRAPPEND 在傳統的鍵值模型里&#xff0c;若要往數組尾部追加元素&#xff0c;通常需要 取→改→寫 三步&#xff1a; GET 整個 JSON&#xff1b;在應用層把元素 push 進數組&#xff1b;SET 回 Redis。 一條 JSON.ARRAPPEND 則可一次完成&#xff0c;具…

14:00開始面試,14:08就出來了,問的問題有點變態。。。

從小廠出來&#xff0c;沒想到在另一家公司又寄了。 到這家公司開始上班&#xff0c;加班是每天必不可少的&#xff0c;看在錢給的比較多的份上&#xff0c;就不太計較了。沒想到4月一紙通知&#xff0c;所有人不準加班&#xff0c;加班費不僅沒有了&#xff0c;薪資還要降40%…

Unity物理系統由淺入深第四節:物理約束求解與穩定性

Unity物理系統由淺入深第一節&#xff1a;Unity 物理系統基礎與應用 Unity物理系統由淺入深第二節&#xff1a;物理系統高級特性與優化 Unity物理系統由淺入深第三節&#xff1a;物理引擎底層原理剖析 Unity物理系統由淺入深第四節&#xff1a;物理約束求解與穩定性 物理引擎的…

深入淺出Kafka Consumer源碼解析:設計哲學與實現藝術

一、Kafka Consumer全景架構 1.1 核心組件交互圖 #mermaid-svg-JDEEOd2M5PzLkYa6 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-JDEEOd2M5PzLkYa6 .error-icon{fill:#552222;}#mermaid-svg-JDEEOd2M5PzLkYa6 .erro…

Matplotlib(一)- 數據可視化與Matplotlib

文章目錄一、數據可視化1. 數據可視化的概念2. 數據可視化流程3. 數據可視化目的4. 常見的可視化圖表4.1 折線圖4.2 柱形圖4.3 條形圖4.4 堆積圖4.4.1 堆積面積圖4.4.2 堆積柱形圖和堆積條形圖4.5 直方圖4.6 箱形圖4.7 餅圖4.8 散點圖4.9 氣泡圖4.10 誤差棒圖4.11 雷達圖二、Py…

傳輸層協議UDP原理

端口號回顧端口號的作用類似pid&#xff0c;用來標識進程的唯一性。只是為了與系統解耦&#xff0c;所以有了端口號。通過ip來確定唯一主機&#xff0c;再通過端口號找到指定的進程。就可以讓全網內唯一的兩個進程通信了。所以一個完整的報文至少要攜帶ip和端口號&#xff0c;i…

【牛客刷題】小紅的數字刪除

文章目錄 一、題目介紹1.1 題目描述1.2 輸入描述:1.3 輸出描述:1.4 示例11.5 示例2二、解題思路2.1 核心觀察2.2 關鍵問題處理三、算法實現四、算法分析4.1 算法流程圖4.2 為什么這么設計算法?4.3 算法復雜度五、模擬演練數據示例1: "103252"示例2: "333&quo…

《大數據技術原理與應用》實驗報告三 熟悉HBase常用操作

目 錄 一、實驗目的 二、實驗環境 三、實驗內容與完成情況 3.1 用Hadoop提供的HBase Shell命令完成以下任務 3.2 現有以下關系型數據庫中的表和數據&#xff0c;要求將其轉換為適合于HBase存儲的表并插入數據&#xff1a; 四、問題和解決方法 五、心得體會 一、實驗目的…

微服務初步入門

服務拆分原則 單一職責原則 單一職責原則原本是面向對象設計的一個基本原則&#xff0c;是指一個類應該專注于單一的功能&#xff0c;不要存在多于一個導致類變更的原因 在微服務架構中&#xff0c;是指一個微服務只負責一個功能或者業務領域&#xff0c;每個服務應該由清晰的定…

Liunx操作系統筆記5

用戶管理命令&#xff1a; useradd命令&#xff1a; useradd命令的功能是創建并設置用戶信息。使用useradd命令可以自動完成用戶信息、基本組、家目錄等的創建工作&#xff0c;并在創建過程中對用戶初始信息進行定制。語法格式:useradd 參數 用戶名常用參數: -M 不建立用…

spring-ai-alibaba 接入Tushare查詢股票行情

最近spring-ai-alibaba主干分支新增了對Tushare的支持&#xff0c;一起來看看如何使用簡單樣例老樣子&#xff0c;分三步進行&#xff1a;第一步&#xff1a;添加依賴<dependency><groupId>com.alibaba.cloud.ai</groupId><artifactId>spring-ai-aliba…

Java使用Langchai4j接入AI大模型的簡單使用(一)

一、LangChain4j 簡介 LangChain4j 是 Java 生態中的 LangChain 實現&#xff0c;是一個用于構建大語言模型(LLM)應用程序的框架。它提供了與各種LLM服務集成的能力&#xff0c;并簡化了構建復雜AI應用的過程。 LangChain4j官方文檔&#xff1a;Integrations | LangChain4j …

Linux —— A / 基礎指令

建議學習路徑&#xff1a;Linux系統與系統編程 ? Linux網絡和網絡編程 ? MySQL一、初識shell命令 1.1、關于 Linux 桌面很多同學的 Linux 啟動進?圖形化的桌?. 這個東西?家以后就可以忘記了。以后的工作中沒有機會使用圖形界面。思考: 為什么不使用圖形界面? 1.2、下…