知識庫 / HTTP Client-Side RSS 訂閱

RestTemplate 中 exchange()、postForEntity() 和 execute() 的區別

HTTP Client-Side,REST,Spring
HongKong
10
03:37 AM · Dec 06 ,2025

1. 引言

Spring 生態系統中,有一類名為 <em >RestTemplate</em> 的類。<strong >該實用類是一個高級類,用於發送 HTTP 消息並處理響應</strong>。

在本教程中,我們將探討 <em >RestTemplate</em> 類中 <em >exchange()</em >,postForEntity(), 和 <em >execute()</em > 方法之間的差異。

2. 什麼是 <em >RestTemplate</em>

正如上面提到的,<em >RestTemplate</em> 是 Spring Framework 中的一個實用類,它簡化了發送 HTTP 消息和處理響應的過程。<em >RestTemplate</em> 類非常適合編寫簡單的 HTTP 客户端,因為它提供了許多功能:

  • 支持所有標準 HTTP 動詞(GET、POST 等)
  • 能夠處理所有標準 MIME 類型(JSON、XML、表單編碼等)
  • 高層 API 允許我們與 Java 類一起工作,並避免複雜的序列化問題
  • 可定製,使用 `ClientHttpRequestInitializer` 和 `ClientHttpRequestInterceptor` 接口

2.1. 棄用警告

從 Spring Framework 5 版本開始,RestTemplate 類正逐漸被棄用

儘管它在 Spring Framework 6 中仍然存在,但維護者已明確表示此類的未來增強將不會進行。

僅接受 minor 的 bug 和安全修復,建議開發者使用 WebClient 代替。 此類具有更現代的 API,並支持同步、異步和流式使用案例。

3. 基本 RestTemplate 使用

RestTemplate 使得使用標準 HTTP 動詞變得輕鬆,它通過提供具有相應名稱的公共方法來實現這一點。

例如,要發送 GET 請求,我們可以使用許多具有 getFor 前綴的重載方法。 同樣,還有其他 HTTP 動詞(包括 POST、PUT、DELETE、HEAD 和 PATCH)的類似公共方法。

所有這些方法的結構幾乎完全相同。 它們本質上只需要關於 URL 的信息,以及請求和響應正文的表示形式。 諸如標頭之類的信息將自動為我們創建。

雖然這些高級方法使得編寫 HTTP 客户端非常容易,但現實世界並不總是完全符合 HTTP 規範。 在某些情況下,我們可能需要構建一個不完全符合任何特定動詞方法的 HTTP 請求

這就是為什麼 RestTemplate 提供了更通用的方法,包括粒度方法,我們將會在下一部分進行探討。

4. 使用 exchange()postForEntity()execute() 方法

雖然使用頂層動詞特定的方法在許多用例中都有效,但在某些情況下,我們可能需要對 RestTemplate 生成的 HTTP 請求進行更精細的控制。這時,exchange()execute() 方法就派上用場。

讓我們考慮一個 HTTP POST 請求示例,該請求允許我們在書數據庫中創建一個新條目。以下是一個 Java 類,封裝了我們請求正文所需的所有數據:

class Book {
  String title;
  String author;
  int yearPublished;
}

下面我們將使用 RestTemplate 這三種方法的變體發送此請求。

4.1. 使用 postForEntity() 方法

發送 POST 請求的首選和最簡單的方法是使用 postForEntity() 方法。 此方法僅需 URL 和請求主體,並會將響應主體解析為 ResponseEntity 對象

Book book = new Book(
  "Cruising Along with Java",
  "Venkat Subramaniam",
  2023);

 ResponseEntity<Book> response = restTemplate.postForEntity(
  "https://api.bookstore.com", 
  book, 
  Book.class);

在本示例中,我們創建了一個新的書對象,將其發送到服務器,並將響應解析為另一個書對象。值得注意的是,我們只需要提供遠程 URL、請求對象和用於響應的類。其他一切,包括 HTTP 頭部,都由 RestTemplate 自動構建。

4.2. 使用 exchange() 方法

以下是我們發送請求的一種方式是使用 exchange() 方法:

Book book = new Book(
  "Effective Java",
  "Joshua Bloch",
  2001);

HttpHeaders headers = new HttpHeaders();
headers.setBasicAuth("username", "password");

ResponseEntity<Book> response = restTemplate.exchange(
  "https://api.bookstore.com",
  HttpMethod.POST,
  new HttpEntity<>(book, headers),
  Book.class);

主要的區別在於,我們不再直接將普通的 Java 對象作為請求體傳遞,而是將其包裹在 HttpEntity 中。 這允許我們明確地為請求設置額外的 HTTP 頭部。

另一個顯著的區別是,exchange() 方法是通用的,這意味着它可以用於任何 HTTP 方法。 因此,請求方法的第二個參數必須指示用於請求的方法。

4.3. 使用 execute() 方法

通過使用 `execute()` 方法,我們可以最終發送我們的 POST 請求。此方法是最通用的,實際上它是 所有其他方法內部所使用的底層方法

以下是使用 `execute()` 方法發送 POST 請求的高級示例:

ResponseEntity<Book> response = restTemplate.execute(
    "https://api.bookstore.com",
    HttpMethod.POST,
    new RequestCallback() {
        @Override
        public void doWithRequest(ClientHttpRequest request) throws IOException {
            // manipulate request headers and body
        }
    },
    new ResponseExtractor<ResponseEntity<Book>>() {
        @Override
        public ResponseEntity<Book> extractData(ClientHttpResponse response) throws IOException {
            // manipulate response and return ResponseEntity
        }
    }
);

值得注意的是,即使我們仍然需要提供 URL 和 HTTP 方法,其他方面看起來差異很大。 這是因為 execute() 方法不直接處理請求和響應

相反,它賦予我們使用 RequestCallbackResponseExtractor 接口創建和修改請求和響應的能力。 主要優勢在於 這使我們對請求和響應對象擁有最大的控制權。 另一方面,我們的代碼變得不簡潔,並且我們失去了其他 RestTemplate 方法提供的許多自動功能

還值得注意的是,RestTemplate 提供了方便創建 RequestCallback 實例的方法。 該方法是 httpEntityCallback(),它具有兩種重載形式,可以幫助我們在使用 execute() 方法時減少編寫代碼量:

Book book = new Book(
  "Reactive Spring",
  "Josh Long",
  2020);
        
RequestCallback requestCallback1 = restTemplate.httpEntityCallback(book);
RequestCallback requestCallback2 = restTemplate.httpEntityCallback(book, Book.class);

同樣,<em>RestTemplate</em> 提供了快速創建 <em>ResponseExtractor</em> 實例的方法工廠。

ResponseExtractor<ResponseEntity<Book>> responseExtractor = restTemplate.responseEntityExtractor(Book.class);

當然,同時使用這兩種工廠方法將會抵消使用 execute() 方法的任何好處。如果我們選擇同時使用它們,我們最好直接使用特定動詞的方法或 exchange() 方法。

5. 結論

在本文中,我們探討了使用 <em >RestTemplate</em> 發送 HTTP POST 請求的三種不同方法。首先,我們看到了如何使用基於動詞的 <em >postForEntity()</em> 方法來創建簡潔明瞭的 HTTP 請求。然後,我們研究了兩種替代方法,<em >exchange()</em><em >execute()</em>,用於發送相同的請求。

儘管這三種方法都產生相同的結果,但它們各自具有優缺點。<em >postForEntity()</em> 方法導致代碼更少,但同時也意味着我們對生成的 HTTP 請求的控制力較弱。<em >exchange()</em><em >execute()</em> 方法則提供了更多的請求控制,但同時也使我們的代碼更冗長,並且依賴於 Spring 框架的自動功能較少。

user avatar
0 位用戶收藏了這個故事!
收藏

發佈 評論

Some HTML is okay.