澤西島的 @FormDataParam 與 @FormParam
一、簡介
Jersey 是一個功能齊全的開源框架,用於使用 Java 開發 Web 服務和用戶端。透過使用 Jersey,我們可以建立支援全套 HTTP 功能的強大 Web 應用程式。
在本文中,我們將了解 Jersey 的兩個特定功能: @FormDataParam
和@FormParam
註解。雖然這兩個註釋本質上相似,但它們有顯著差異,如下所示。
2. 背景
客戶端和伺服器之間交換資料的方式有很多種。最受歡迎的兩種是 XML 和 JSON,但它們並不是唯一的選擇。
表單編碼資料是在客戶端和伺服器之間發送資料時格式化資料的另一種方式,特別是當客戶端是網頁時。這是因為 HTML 可以輕鬆定義具有各種輸入(文字、複選框、下拉式清單等)的表單並將該資料傳回遠端伺服器。
這就是@FormDataParam
與@FormParam
註釋的用武之地。它們都用於處理 Jersey 伺服器應用程式中的表單數據,但有一些重要的區別。
現在我們了解了這兩種註釋的背景,讓我們來看看如何使用每種註釋以及它們的一些差異。
3.使用@FormParam
簡而言之,只要 API 需要 URL 編碼數據,我們就使用@FormParam
註解。讓我們來看一個只有文字欄位的簡單 HTML 表單:
<form method="post" action="/example1">
<input name="first_name" type="text">
<input name="last_name" type="text">
<input name="age" type="text">
<input type="submit">
</form>
此表單有三個欄位:名字、姓氏和年齡。它還使用 HTTP POST
方法將表單資料傳送到位於/example1
的 URL。
要使用 Jersey 處理此表單,我們將在伺服器應用程式中定義以下端點:
@POST
@Path("/example1")
public String example1(
@FormParam("first_name") String firstName,
@FormParam("last_name") String lastName,
@FormParam("age") String age)
{
// process form data
}
請注意,我們對 HTML 表單中的每個欄位都使用了註解。無論表單有多少字段或什麼類型的字段,其工作原理都是相同的。透過使用@FormParam
註釋,Jersey 將每個欄位的值綁定到相應的方法參數中。
實際上,表單編碼資料與MIME 類型application/x-www-form-urlencoded
相關。在底層,網頁瀏覽器和我們的服務之間發送的資料如下所示:
first_name=john&last_name=smith&age=42
這種方法的好處是資料易於處理,因為它只涉及文字而不涉及二進位資料。此外,此方法可以使用 HTTP GET
動詞來運作,因為字串可以作為 URL 中的查詢參數傳遞。但是,透過 URL 傳遞表單資料時我們應該小心,因為它可能包含敏感資料。
4.使用@FormDataParam
相較之下, @FormDataParam
註解更加靈活,可以處理文字和二進位資料的任意組合。實際上,這對於使用 HTML 表單上傳文件之類的事情非常有用。
讓我們看一下使用@FormDataParam
註解的範例表單。首先,我們必須先將jersey-media-multipart
模組從Maven Central匯入到我們的專案中:
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-multipart</artifactId>
<version>3.1.3</version>
</dependency>
現在,讓我們在上面建立的 HTML 表單中新增一個文件上傳欄位:
<form method="post" action="/example2" enctype="multipart/form-data >
<input name="first_name" type="text">
<input name="last_name" type="text">
<input name="age" type="text">
<input name="photo" type="file">
<input type="submit">
</form>
請注意,我們現在在表單元素中指定multipart/form-data
的編碼類型。這是必要的,以便網頁瀏覽器以我們的服務期望的格式發送資料。
接下來,在我們的應用程式中,我們將建立以下端點來處理來自此表單的資料:
@POST
@Path("/example2")
public String example2(
@FormDataParam("first_name") String firstName,
@FormDataParam("last_name") String lastName,
@FormDataParam("age") String age,
@FormDataParam("photo") InputStream photo)
{
// handle form data
}
請注意,每個表單欄位現在都使用@FormDataParam
註解。我們也使用InputStream
作為處理二進位資料的參數類型。
與前面的範例不同,前面的範例將每個欄位及其值組合成一個字串,而本範例將這些欄位組合成多個部分。每個部分都由唯一的標記分隔,讓 Jersey 輕鬆識別每個參數並將每個部分綁定到相應的方法參數。
例如,從此表單發送到我們服務的原始訊息可能如下所示:
------WebKitFormBoundarytCyB57mkvJedAHFx
Content-Disposition: form-data; name="first_name"
John
------WebKitFormBoundarytCyB57mkvJedAHFx
Content-Disposition: form-data; name="last_name"
Smith
------WebKitFormBoundarytCyB57mkvJedAHFx
Content-Disposition: form-data; name="age"
42
------WebKitFormBoundarytCyB57mkvJedAHFx
Content-Disposition: form-data; name="photo"; filename="john-smith-profile.jpeg"
Content-Type: image/jpeg
------WebKitFormBoundarytCyB57mkvJedAHFx--
這種方法的主要好處是我們可以一起發送文字和二進位資料。然而,與使用傳統的表單編碼資料相比,也有一些缺點。
首先,我們只能POST
**這種類型的**HTTP POST 動詞。這是因為二進位資料無法編碼並沿著 URL 字串傳遞。其次,有效載荷的大小要大得多。正如我們在上面的範例中看到的,定義分隔符號和標題所需的附加文字比正常的表單編碼資料增加了相當多的大小。
5. 結論
在本文中,我們研究了 Jersey 庫中的兩個不同的註釋: @FormParam
和@FormDataParam
。這兩個註釋都處理應用程式中的表單數據,但正如我們所見,它們的用途截然不同。
當發送表單編碼資料時, @FormParam
效果更好。這可以使用GET
或POST
動詞,但只能包含文字欄位。另一方面, @FormDataParam
註釋處理多部分資料。這可以包括文字和二進制數據,但僅適用於POST
動詞。
最後,本文中的所有程式碼範例都位於GitHub 上。