HTTP协议--applicationx-www-form-urlencoded-multipartform-data和payload

最近接触了一些REST接口开发,然后了解了一下HTTP协议的内容,其中遇到了一些POST请求中的Content-Type类型的问题,这里做个记录。

事情是这样的:ajax请求一个接口(POST,数据是json类型的),但是Web服务获取不到POST内容(基于springMVC,接收参数用的是RequestBody)。

OK,google一下,发现是Content-Type设置的问题,那我们了解一下Content-Type和其中的POST body的关系吧。

首先我们的方法是POST,payload指的就是我们POST的具体内容,这个内容可以是任何形式(图片、音频、字符串),内容的格式由Content-Type决定。

如果设置了Content-Type是application/x-www-form-urlencoded的话,那么我们POST实体的键值对就会转换为

...&参数名=参数值&...

这种样子,如图:

wwwurlencode

事实上,这种请求如果换成GET方法,那么就相当于把这些键值对拼接在url后面,效果是一样的。

对于大多数网络请求,这样的形式已经够了,那么为什么还要存在multipart/form-data呢?

因为如果这些参数的字符是非字母和数字的话(比如中文),那么这些拼接的参数会转换为%HH(H表示16进制数),这样一来,如果POST的数据量比较大,那么拼接的参数每个字符会转换为3个字节,大大增加了传输的数据大小。

所以我们又有了multipart/form-data。

我们使用multipart/form-data来请求一下,报文如图:

formdata

可以看到,POST实体的内容根据键值对个数分为了N份,每一部分被WebKitFormBoundaryk9aaokH8kA4j4eld分割,事实上,每一部分都是一个MIME块,指定了MIME数据:Content-Disposition: form-data; name=”key222” value222,我猜想这样一块块的形式就可以让每一块都可以是一个不同的类型,估计也是multipart的由来吧。

到这里两种类型就清楚了,对于RESTFUL接口来说,一般我们有需要POST传输一个json字符串,那么ajax就需要指定Content-Type为application/json,然后传输过来的数据应该是普通的字符串类型,可以使用JSON.stringfy(大概是这个方法)把js中的json数据类型转换为普通的字符串。
web端就可以用@RequestBody直接把字符串转换为javabean。

写完收工~