HTTP Content-Type深入實踐

引子

HTTP是一種網(wǎng)絡(luò)應(yīng)用層傳輸協(xié)議极阅,協(xié)議就是約定梳猪。HTTP頭部字段Content-Type約定請求和響應(yīng)的HTTP body內(nèi)容編碼類型,客戶端和服務(wù)端根據(jù)HTTP頭部字段Content-Type正確解碼HTTP body內(nèi)容姻灶。
常見的HTTP頭部Content-Type:

  • application/x-www-form-urlencoded
  • multipart/form-data
  • application/json
  • application/xml

當然還有更多的類型红碑,比如請求html時是text/html名船,請求css時是text/css绰上,請求js時是text/javascript...
本文將深入實踐Content-Type對HTTP body內(nèi)容的解碼重要性,模擬發(fā)送HTTP頭部Content-Type:application/json渠驼,后端使用Spring boot+Java蜈块,前端使用html+javascript+css+jquery。
Content-Type和Content-Length焦不離孟迷扇,關(guān)于Content-Length可以參考拙作HTTP Content-Length深入實踐百揭。

HTTP Request Content-Type

前端使用Content-Type:"application/json"編碼HTTP請求內(nèi)容并提交給服務(wù)端,服務(wù)端使用Content-Type:"application/json"解碼HTTP請求內(nèi)容蜓席。下面實踐HTTP Request頭部Content-Type的作用器一。
后端Spring boot+Java代碼如下,Product類包含三個字段:id,name,price厨内,請自建并引入祈秕。

package com.demo.web.http;

import com.demo.domain.http.Product;
import com.google.common.collect.Maps;
import com.google.gson.Gson;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

@Controller
@RequestMapping("http")
public class ContentTypeController {
    @RequestMapping("/content-type-request")
    public String contentType4Request() {
        return "http/content-type-request";
    }

    @RequestMapping("content-type-request.json")
    @ResponseBody
    public void json4Request(@RequestBody List<Product> products, HttpServletResponse response) throws IOException {
        System.out.println(Arrays.deepToString(products.toArray()));
        response.getWriter().write("Add products success.");
    }
}

前端html+javascript+css+jquery代碼如下:

<!DOCTYPE HTML>
<html>
<head>
    <title>HTTP request Content-Type Demo</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <script src="http://code.jquery.com/jquery-1.11.3.min.js" type="text/javascript"></script>
</head>
<body>
<button type="button" onclick="addProducts();">向服務(wù)器發(fā)送json</button>
<p id="msg"></p>
<script>
    var products = new Array();
    products.push({
        id : 1,
        name : "iPhone 6 Plus",
        price : 4987.5
    });
    products.push({
        id : 2,
        name : "iPhone 7 Plus",
        price : 5987.5
    });
    function addProducts() {
        $.ajax({
            type: "POST",
            url: "content-type-request.json",
            data: JSON.stringify(products),
            contentType: "application/json",
            dataType: "text",
            success: function (result) {
                console.log(result);
                $("#msg").html(result);
            },
            error: function () {
                alert("error.");
            }
        });
    }
</script>
</body>
</html>

如圖1,點擊“向服務(wù)器發(fā)送json”按鈕雏胃,ajax請求頭部Content-Type:application/json请毛,ajax請求后端方法com.demo.web.http.ContentTypeController#json4Request,后端方法解碼HTTP請求內(nèi)容的products json字段丑掺,并打印出來获印。

圖1 HTTP request Content-Type:application/json

當把前端代碼的contentType: "application/json",注釋述雾,前端頁面報如下錯誤:

圖2 HTTP Request頭部Content-Type使用默認值

圖3 HTTP Request頭部Content-Type使用默認值

從圖2街州、圖3看,如果不明確指定HTTP Request頭部Content-Type玻孟,將使用application/x-www-form-urlencoded; charset=UTF-8作為默認值唆缴,后端方法com.demo.web.http.ContentTypeController#json4Request不能解碼Content-Type:application/x-www-form-urlencoded的HTTP Request body內(nèi)容,返回HTTP 415錯誤:不支持的媒體類型(Unsupported media type)黍翎。如下后端報錯信息也印證這點面徽,說明后端方法com.demo.web.http.ContentTypeController#json4Request只能解碼請求頭部Content-Type為application/json的HTTP Request body內(nèi)容。
2017-07-23 17:03:56.917 WARN 24723 --- [nio-8080-exec-2] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved exception caused by Handler execution: org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/x-www-form-urlencoded;charset=UTF-8' not supported

HTTP Response Content-Type

服務(wù)端使用Content-Type:"application/json"編碼HTTP響應(yīng)body內(nèi)容返回給前端,前端使用Content-Type:"application/json"解碼HTTP響應(yīng)body內(nèi)容趟紊。下面實踐HTTP Response頭部Content-Type的作用氮双。

情況1:服務(wù)端返回Response Content-Type:application/json,前端dataType不指定值

后端Spring boot+Java代碼如下:

package com.demo.web.http;

import com.google.common.collect.Maps;
import com.google.gson.Gson;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Map;

@Controller
@RequestMapping("http")
public class ContentTypeController {
    private final static Gson GSON = new Gson();
    @RequestMapping("/content-type-response")
    public String contentType4Response() {
        return "http/content-type-response";
    }

    @RequestMapping("content-type-response.json")
    @ResponseBody
    public void json4Response(HttpServletResponse response) throws IOException {
        Map<String, Object> map = Maps.newHashMap();
        map.put("name", "datou");
        response.setContentType("application/json;charset=utf-8");
        response.getWriter().write(GSON.toJson(map));
    }
}

前端html+javascript+css+jquery代碼如下:

<!DOCTYPE HTML>
<html>
<head>
    <title>HTTP response Content-Type Demo</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <script src="http://code.jquery.com/jquery-1.4.2.min.js" type="text/javascript"></script>
</head>
<body>
<p>Name: <span id="name"></span></p>
<button onclick="show()">show name</button>
<script>
    function show() {
        $.get("content-type-response.json", function (data) {
            console.log(data);
            $("#name").text(data.name);
        });
    }
</script>
</body>
</html>

如圖4霎匈,點擊“show name”按鈕戴差,ajax請求后端方法com.demo.web.http.ContentTypeController#json4Response,后端方法返回HTTP響應(yīng)頭部Content-Type:application/json铛嘱,前端$.get()方法在不指定dataType具體值的情況下解碼HTTP響應(yīng)body內(nèi)容暖释,data類型是Object,js獲取并展示data.name的內(nèi)容墨吓。

圖4 服務(wù)端返回Response Content-Type:application/json球匕,前端$.get() dataType不指定值

情況2:服務(wù)端不返回Response Content-Type:application/json,前端dataType指定值json

后端Spring boot+Java代碼注釋response.setContentType("application/json;charset=utf-8");
前端html+javascript+css+jquery代碼如下帖烘,前端dataType指定值"json":

<!DOCTYPE HTML>
<html>
<head>
    <title>HTTP response Content-Type Demo</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <script src="http://code.jquery.com/jquery-1.4.2.min.js" type="text/javascript"></script>
</head>
<body>
<p>Name: <span id="name"></span></p>
<button onclick="show()">show name</button>
<script>
    function show() {
        $.get("content-type-response.json", function (data) {
            console.log(data);
            $("#name").text(data.name);
        }, "json");
    }
</script>
</body>
</html>

如圖5亮曹,點擊“show name”按鈕,ajax請求后端方法com.demo.web.http.ContentTypeController#json4Response秘症,后端方法返回HTTP響應(yīng)沒有頭部字段Content-Type乾忱,前端$.get()指定dataType="json"解碼HTTP響應(yīng)body內(nèi)容,data類型是Object历极,js獲取并展示data.name的內(nèi)容窄瘟。

圖5 服務(wù)端不返回Response Content-Type:application/json,前端dataType指定值"json"

情況3:服務(wù)端不返回Response Content-Type:application/json趟卸,前端dataType不指定值"json"

后端Spring boot+Java代碼注釋response.setContentType("application/json;charset=utf-8");蹄葱。
前端html+javascript+css+jquery代碼如下,前端$.get()dataType不指定值"json"

<!DOCTYPE HTML>
<html>
<head>
    <title>HTTP response Content-Type Demo</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <script src="http://code.jquery.com/jquery-1.4.2.min.js" type="text/javascript"></script>
</head>
<body>
<p>Name: <span id="name"></span></p>
<button onclick="show()">show name</button>
<script>
    function show() {
        $.get("content-type-response.json", function (data) {
            console.log(data);
            $("#name").text(data.name);
        });
    }
</script>
</body>
</html>

如圖6锄列,點擊“show name”按鈕图云,ajax請求后端方法com.demo.web.http.ContentTypeController#json4Response,后端方法返回HTTP響應(yīng)不返回頭部字段Content-Type邻邮,前端$.get()在不指定dataType具體值為"json"的情況下不能解碼HTTP響應(yīng)body的json字符串竣况,data類型是String,js不能獲取data.name值筒严,所以展示的Name:為空丹泉。

圖6 服務(wù)端不返回Response Content-Type:application/json,前端dataType不指定值"json"

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末鸭蛙,一起剝皮案震驚了整個濱河市摹恨,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌娶视,老刑警劉巖晒哄,帶你破解...
    沈念sama閱讀 221,820評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件睁宰,死亡現(xiàn)場離奇詭異,居然都是意外死亡寝凌,警方通過查閱死者的電腦和手機柒傻,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,648評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來较木,“玉大人诅愚,你說我怎么就攤上這事〗儆常” “怎么了违孝?”我有些...
    開封第一講書人閱讀 168,324評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長泳赋。 經(jīng)常有香客問我雌桑,道長,這世上最難降的妖魔是什么祖今? 我笑而不...
    開封第一講書人閱讀 59,714評論 1 297
  • 正文 為了忘掉前任校坑,我火速辦了婚禮,結(jié)果婚禮上千诬,老公的妹妹穿的比我還像新娘耍目。我一直安慰自己,他們只是感情好徐绑,可當我...
    茶點故事閱讀 68,724評論 6 397
  • 文/花漫 我一把揭開白布邪驮。 她就那樣靜靜地躺著,像睡著了一般傲茄。 火紅的嫁衣襯著肌膚如雪毅访。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,328評論 1 310
  • 那天盘榨,我揣著相機與錄音喻粹,去河邊找鬼。 笑死草巡,一個胖子當著我的面吹牛守呜,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播山憨,決...
    沈念sama閱讀 40,897評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼查乒,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了萍歉?” 一聲冷哼從身側(cè)響起侣颂,我...
    開封第一講書人閱讀 39,804評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎枪孩,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,345評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡蔑舞,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,431評論 3 340
  • 正文 我和宋清朗相戀三年拒担,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片攻询。...
    茶點故事閱讀 40,561評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡从撼,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出钧栖,到底是詐尸還是另有隱情低零,我是刑警寧澤,帶...
    沈念sama閱讀 36,238評論 5 350
  • 正文 年R本政府宣布拯杠,位于F島的核電站掏婶,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏潭陪。R本人自食惡果不足惜雄妥,卻給世界環(huán)境...
    茶點故事閱讀 41,928評論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望依溯。 院中可真熱鬧老厌,春花似錦、人聲如沸黎炉。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,417評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽慷嗜。三九已至慈迈,卻和暖如春跳仿,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,528評論 1 272
  • 我被黑心中介騙來泰國打工聚假, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人快耿。 一個月前我還...
    沈念sama閱讀 48,983評論 3 376
  • 正文 我出身青樓糯彬,卻偏偏與公主長得像,于是被迫代替她去往敵國和親忿峻。 傳聞我的和親對象是個殘疾皇子薄啥,可洞房花燭夜當晚...
    茶點故事閱讀 45,573評論 2 359

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)逛尚,斷路器垄惧,智...
    卡卡羅2017閱讀 134,702評論 18 139
  • http頭部字段Content-Type約定請求和響應(yīng)的HTTP body內(nèi)容編碼類型,客戶端和服務(wù)端根據(jù)http...
    番薯大佬閱讀 2,298評論 1 1
  • 引子 HTTP頭部Content-Length用于描述HTTP消息實體的傳輸長度绰寞,瀏覽器對比Content-Len...
    大頭8086閱讀 26,189評論 1 6
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,298評論 25 707
  • 巖腳侗寨是其實是在一月份(二十六)去的 因著剛換了工作 一直沒時間更 今天閑下來了 想著該動動手了...
    公子段_閱讀 755評論 0 0