SpringMVC接受JSON參數(shù)詳解及常見錯誤總結(jié)

最近一段時間不想使用Session了涨享,想感受一下Token這樣比較安全缸废,穩(wěn)健的方式吟秩,順便寫一個統(tǒng)一的接口給瀏覽器還有APP咱扣。所以把一個練手項目的前臺全部改成Ajax了,跳轉(zhuǎn)再使用SpringMVC控制轉(zhuǎn)發(fā)涵防。對于傳輸JSON數(shù)據(jù)這邊有了更深的一些理解闹伪,分享出來,請大家指正壮池。

SpringMVC中我們可以選擇數(shù)種接受JSON的方式偏瓤,在說SpringMVC如何接受JSON之前,我們先聊聊什么是JSON椰憋。具體的定義我也不贅述了厅克,在JavaScript中我們經(jīng)常這樣定義JSON 對象

var jsonObject = {
"username":"admin",
"password":123
}

這種形式的我們叫它JSON對象,同時還有一個概念叫做JSON字符串橙依,字符串呢证舟,顧名思義硕旗,是由' '或者" "包裹起來的一個整體,我們稱之為字符串女责。我們知道字符串是可以直接輸出的漆枚,而對象不能直接輸出。所以在JavaScript中抵知,我們可以

//定義一個對象 jsonObject
var jsonObject = {
"username":"admin",
"password":123
};
alert(jsonObject);

此時墙基,會顯示[object Object]而不會輸出JSON對象的內(nèi)容,JavaScript向我們提供了兩個工具

JSON.parse()
用于將一個 JSON 字符串轉(zhuǎn)換為 JavaScript 對象刷喜。
JSON.stringify()
用于將 JavaScript 值轉(zhuǎn)換為 JSON 字符串残制。

所以當(dāng)我們輸入

alert(JSON.stringify(jsonObject));

就會顯示 {"username":"admin","password":123};

** 好了 對于JSON的講解就到這里了 下面我們說一說SpringMVC **

既然JSON有著上述兩種存在方式,那我們通過ajax向SpringMVC傳值的時候吱肌,我們該傳哪一種呢痘拆?
我們首先嘗試直接發(fā)送JSON對象

//定義json對象
            var username = $("#username").val();
            var password = $("#password").val();
            var json = {
                "username" : username,
                "password" : password
            };

// Jquery Ajax請求
$.ajax({
                url : "jsontest",
                type : "POST",
                async : true,
                data : json,
                dataType : 'json',
                success : function(data) {
                    if (data.userstatus === "success") {
                        $("#errorMsg").remove();
                    } else {
                        if ($("#errorMsg").length <= 0) {
                            $("form[name=loginForm]").append(errorMsg);
                        }
                    }
                }
            });

我們首先想想SpringMVC提供了什么給我們,有一個@RequestParam的注解氮墨,對于這個注解纺蛆,它的作用和我們Servlet中的request.getParameter是基本相同的。我們首先使用這個注解來獲取

    @RequestMapping("/jsontest")
    public void test(@RequestParam(value="username",required=true) String username,
    @RequestParam(value="password",required=true) String password){
        System.out.println("username: " + username);
        System.out.println("password: " + password);
    }

后臺成功輸出的我們的參數(shù)规揪,成功接受桥氏!

SpringMVC如此智能,如果我們?nèi)コ鼲RequestParam注解猛铅,直接將兩個值放入會有什么后果字支?

@RequestMapping("/jsontest")
    public void test(String username,String password){
        System.out.println("username: " + username);
        System.out.println("password: " + password);
    }

竟然同樣成功了,原理我這里就不多贅述了奸忽,有興趣的朋友們可以打斷點看看堕伪。

SpringMVC提供了一個@RequestBody,它是用來處理前臺定義發(fā)來的數(shù)據(jù)Content-Type: 不是application/x-www-form-urlencoded編碼的內(nèi)容栗菜,例如application/json, application/xml等欠雌;
細(xì)心的朋友們或許發(fā)現(xiàn)了,在之前的Ajax中疙筹,我們沒有定義Content-type的類型富俄,Jquery默認(rèn)使用application/x-www-form-urlencoded類型。那么意思就是SpringMVC的@RequestParam注解而咆,Servlet的request.getParameter是可以接受到以這種格式傳輸?shù)腏SON對象的霍比。

為什么呢!暴备?GET請求想必大家都不陌生悠瞬,它將參數(shù)以url?username="admin"&password=123這種方式發(fā)送到服務(wù)器,并且request.getParameter可以接收到這種參數(shù),我們在瀏覽器地址欄上也可以看到這一點浅妆。而我們Ajax使用的POST玛痊,并且發(fā)送的是JSON對象,那么后臺是如何獲取到的呢狂打?答案就在于這個Content-Type x-www-form-urlencoded的編碼方式把JSON數(shù)據(jù)轉(zhuǎn)換成一個字串,(username="admin"&password=123)然后把這個字串添加到url后面,用?分割混弥,(是不是和GET方法很像)趴乡,提交方式為POST時候,瀏覽器把數(shù)據(jù)封裝到HTTP BODY中蝗拿,然后發(fā)送到服務(wù)器晾捏。所以并不會顯示在URL上。(這段可能有點繞口哀托,希望大家用心理解一下惦辛。)
終于說完了,長吐一口氣仓手。所以說我們使用@RequestBody注解的時候胖齐,前臺的Content-Type必須要改為application/json,如果沒有更改嗽冒,前臺會報錯415(Unsupported Media Type)呀伙。后臺日志就會報錯Content type 'application/x-www-form-urlencoded;charset=UTF-8' not supported,這些錯誤Eclipse下Tomcat是不會顯示錯誤信息的添坊,只有使用了日志才會顯示剿另,如何配置日志大家可以看我上一篇文章。接下來我們正確配置一下,上面說到了 Content-Type需要更改,同時我們的data也要更改了贬蛙,這種注解方式只接受JSON字符串而不是JSON對象

$.ajax({
                url : "jsontest",
                type : "POST",
                async : true,
                contentType : "application/json",
                data : JSON.stringify(json),
                dataType : 'json',
                success : function(data) {
                    if (data.userstatus === "success") {
                        $("#errorMsg").remove();
                    } else {
                        if ($("#errorMsg").length <= 0) {
                            $("form[name=loginForm]").append(errorMsg);
                        }
                    }
                }
            });

后臺也更改一下雨女,json其實可以理解為鍵值對嘛,所以我們用Map接收阳准,然后對字符串或者其他數(shù)據(jù)類型進(jìn)行進(jìn)一步處理氛堕。

    @RequestMapping("/jsontest")
    public void test(@RequestBody(required=true) Map<String,Object> map  ){
        String username = map.get("username").toString();
        String password = map.get("password").toString();
        System.out.println("username: " + username);
        System.out.println("password: " + password);
    }

同時,我又想起了神奇的SpringMVC溺职,所以我決定去掉注解試試岔擂,好的,果斷被爆了一個空指針錯誤...嘗試就此打住浪耘。
SpringMVC還提供了參數(shù)直接和POJO綁定的方法乱灵,我們來嘗試一下。前臺一樣七冲,就不貼出來了阱佛。

@RequestMapping("/jsontest")
    public void test(@RequestBody User user  ){
        String username = user.getUsername();
        String password = user.getPassword();
        System.out.println("username: " + username);
        System.out.println("password: " + password);
    }

OK,這次是可以取到值的隘谣,我個人對于登錄這類小數(shù)據(jù)量的上傳來說不太喜歡這種方法,User里面的變量很多抒蚜,我只用了其中兩個,沒有必要去創(chuàng)建一個User對象耘戚,一般數(shù)據(jù)量小的時候我還是比較喜歡使用單獨取值出來的嗡髓。我們再想一想,如果是在上傳JSON對象的情況下收津,我們可不可以綁定POJO呢饿这,答案是可以的,不要使用@RequestParam注解撞秋,否則會報Required User parameter 'user' is not present錯誤长捧。到此講解基本結(jié)束了,下面來總結(jié)一下吻贿。

  • 我們首先說了JSON對象和JSON字符串
  • 然后說了SpringMVC接受兩種兩種JSON格式的時候串结,前端ContentType的設(shè)定,和后端是否使用注解接受舅列,還提到了一點Servlet肌割。
  • 當(dāng)Ajax以application/x-www-form-urlencoded格式上傳即使用JSON對象,后臺需要使用@RequestParam 或者Servlet獲取帐要。 當(dāng)Ajax以application/json格式上傳即使用JSON字符串声功,后臺需要使用@RquestBody獲取。

這是我實驗了一天的一些總結(jié)宠叼,希望可以幫助到大家先巴,如果有錯誤,請各位海涵并指正冒冬。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末伸蚯,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子简烤,更是在濱河造成了極大的恐慌剂邮,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,816評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件横侦,死亡現(xiàn)場離奇詭異挥萌,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)枉侧,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,729評論 3 385
  • 文/潘曉璐 我一進(jìn)店門引瀑,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人榨馁,你說我怎么就攤上這事憨栽。” “怎么了?”我有些...
    開封第一講書人閱讀 158,300評論 0 348
  • 文/不壞的土叔 我叫張陵屑柔,是天一觀的道長屡萤。 經(jīng)常有香客問我,道長掸宛,這世上最難降的妖魔是什么死陆? 我笑而不...
    開封第一講書人閱讀 56,780評論 1 285
  • 正文 為了忘掉前任,我火速辦了婚禮唧瘾,結(jié)果婚禮上翔曲,老公的妹妹穿的比我還像新娘。我一直安慰自己劈愚,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,890評論 6 385
  • 文/花漫 我一把揭開白布闻妓。 她就那樣靜靜地躺著菌羽,像睡著了一般。 火紅的嫁衣襯著肌膚如雪由缆。 梳的紋絲不亂的頭發(fā)上注祖,一...
    開封第一講書人閱讀 50,084評論 1 291
  • 那天,我揣著相機(jī)與錄音均唉,去河邊找鬼是晨。 笑死,一個胖子當(dāng)著我的面吹牛舔箭,可吹牛的內(nèi)容都是我干的罩缴。 我是一名探鬼主播,決...
    沈念sama閱讀 39,151評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼层扶,長吁一口氣:“原來是場噩夢啊……” “哼箫章!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起镜会,我...
    開封第一講書人閱讀 37,912評論 0 268
  • 序言:老撾萬榮一對情侶失蹤檬寂,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后戳表,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體桶至,經(jīng)...
    沈念sama閱讀 44,355評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,666評論 2 327
  • 正文 我和宋清朗相戀三年匾旭,在試婚紗的時候發(fā)現(xiàn)自己被綠了镣屹。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,809評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡价涝,死狀恐怖野瘦,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤鞭光,帶...
    沈念sama閱讀 34,504評論 4 334
  • 正文 年R本政府宣布吏廉,位于F島的核電站,受9級特大地震影響惰许,放射性物質(zhì)發(fā)生泄漏席覆。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 40,150評論 3 317
  • 文/蒙蒙 一汹买、第九天 我趴在偏房一處隱蔽的房頂上張望佩伤。 院中可真熱鬧,春花似錦晦毙、人聲如沸生巡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽孤荣。三九已至,卻和暖如春须揣,著一層夾襖步出監(jiān)牢的瞬間盐股,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,121評論 1 267
  • 我被黑心中介騙來泰國打工耻卡, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留疯汁,地道東北人。 一個月前我還...
    沈念sama閱讀 46,628評論 2 362
  • 正文 我出身青樓卵酪,卻偏偏與公主長得像幌蚊,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子溃卡,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,724評論 2 351

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