做web開發的前后端同學對於postman這個工具一定不會陌生。在圖示位置中,Body里我們可以看到有幾個選項,其中常用的有form-data,x-www-form-urlencoded,raw,binary,它們具體對應的分別是multipart/form-data,application/x-www-from-urlencoded,text/plain,application/octet-stream這四種模式。
首先multipart/form-data是用以支持向服務器發送二進制數據的一種文本類型。1995年,ietf 出台了 rfc1867,也就是《RFC 1867 -Form-based File Upload in HTML》,用以支持文件上傳。它是HTML表單中的enctype類型之一(其它還包括application/x-www-from-urlencoded,text/plain),即表單數據編碼的一種方式。
使用這種方式上傳上傳數據時,必須先要定義一個boundary,用於隔離不同的鍵值對,而這個鍵值對的值可以是文本,也可以是文件。這在實際使用中比單純地上傳文本或者只能上傳一個文件(如:Content-Type:application/octet-stream)的模式要方便很多。如圖所示,postman中采用了form-data,設置了一個文本的key1以及一個文件的key2,可以看右側HTTP報文的內容:
不同的框架對於這個類型的處理也是做了很好地支持。如Java中各種框架中Multipart打頭的類基本都是處理這種相關內容的。理解了multipart/form-data,其實也就可以很好地理解application/x-www-from-urlencoded和application/octet-stream這兩種類型了。下面這張圖展示了選擇application/x-www-from-urlencoded時(注意中文的處理):
可以看到,參數這里已經通過URLEncode進行了轉碼,在參數配置欄中也可以看到VALUE欄下只能填寫純文本,無法選擇文件。再看binary這種方式,可以看到它里面沒有KEY-VALUE輸入框,有一個Select File選項,並且只有一個。所以這里就能看出來multipart和binary,x-www-form-urlencoded之間的區別與聯系。大家可以在一個SpringBoot(或者SpringMVC)的Controller中,在response里填寫如下內容,然后看看從瀏覽器訪問這個接口時會發生什么:
... String rfc5987FileName = RFC5987StringUtils.rfc5987_encode(fileName); response.setContentType("application/octet-stream"); response.setHeader("Content-Disposition", "attachment;filename=\"" + rfc5987FileName + "\";filename*=utf-8''" + rfc5987FileName);
並從中體會application/octet-stream的用法。
另外,raw對應的是Content-Type中的純文本,text/plain,如圖所示:
-------------------------------------------------------------------------------------
可以發現,postman的Body下這幾個選項其實都跟http協議中的Content-Type有關,那么我們在此也對這個內容做個擴展。
Content-Type表示媒體類型信息,有了這個信息,服務器和客戶端的瀏覽器就能夠更好地進行內容適配。這里給出一個詳細的media types說明地址:https://www.iana.org/assignments/media-types/media-types.xhtml
其中常見的格式有:
application/json,application/x-www-form-urlencoded,multipart/form-data,application/octet-stream,text/plain...
postman中把這些內容基本上都覆蓋了。
這個協議中,“/”之前的內容表示主協議,之后的內容表示子協議,經常還會在這之后加上參數如charset。類型的格式如下:
格式:type/subtype(;parameter)?type 示例:Content-Type:text/html;charset:utf-8;
-------------------------------------------------------------------------------------
另外,在SpringBoot/SpringMVC中,@RequestMapping中幾個重要的屬性,這里說明一下:
- String[] value/path: 這倆是相同的,也很好理解,表示路徑;
- String name: 自定義一個name屬性,官方說明可以通過使用Spring jsp tag包里面的mvcUrl,來生成jsp到Controller的鏈接(默認是類大寫字符+#+方法名來構建的)。
@Controller @ResponseBody @RequestMapping(name = "AdminController") class BlogController { @RequestMapping(name="BlogComments", path="blog/{blog}/comments/{page}") public List<Comment> listBlogComments(@PathVariable Blog blog, @PathVariable Long page) { ... } }
在JSP中,可以通過如下方式獲取到URL:
<%@ taglib uri="http://www.springframework.org/tags" prefix="s" %>
<a href="${s:mvcUrl('AdminController#BlogComments').arg("1","123").build()}">Get Person</a>
- RequestMethod[] method: 如果不進行設置,默認是支持所有類型的RequestMethod。
- String[] params: 篩選params,只有滿足了條件的key/value出現,才會執行這個方法。可以使用key=value判斷,也可以使用key!=value的形式來判斷。這個在類型和方法級別都是支持的。
- String[] headers: 篩選headers,只有滿足了條件的key/value出現,才會執行這個方法。可以使用key=value判斷,也可以使用key!=value的形式來判斷,甚至支持通配符*。這個在類型和方法級別都是支持的。
RequestMapping(value = "/something", headers = "content-type=text/*")
此時只有滿足headers條件的請求才會被正確執行。
- String[] consumes: 針對Content-Type進行請求過濾。必須滿足這里設置的過濾條件,這個請求才會被執行。如:
consumes="text/plain" consumes={"text/plain","application/*"} consumes="!text/plain"
- String[] produces: 針對Accept進行請求過濾。必須滿足條件,這個請求才會被執行。如:
produces="text/plain" produces={"text/plain","application/*"} produces="!text/plain"