一、先來看一個常見的異常
org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/x-www-form-urlencoded;charset=UTF-8' not supported
前端代碼:
$.ajax({
type:"post",
url:"/test",
data:JSON.stringify({id:1,name:"小明",gender:true}),
success:function (result) {
console.log(result);
}
});
後端代碼:
@ResponseBody
@RequestMapping("/test")
public Object testJson(@RequestBody User user){
System.out.println(user);
return user;
}
前後端用json字符串做數據交互。一運行就報了上面的異常了。
先說一下解決方法:
ajax中加上一個鍵值對:contentType:"application/json" 就行了。
原因:前端用 JSON.stringify({id:1,name:"小明",gender:true}) 將一個js對象轉換成了json字符串,後端通過@RequestBody註解表示要解析json字符串(相當於fastJson來解析json字符串)並賦值給User對象,我們發送的是http請求,後端在解析請求參數時並不是直接解析內容,若是post請求的話,他會先檢查HTTP請求的Content-type屬性值,根據這個屬性值來判斷請求體中的數據格式。前端我們發的ajax請求默認的contentType屬性值爲:application/x-www-form-urlencoded;charset=UTF-8,這個contentType表示的數據格式是鍵值對格式。所以我後端需要json格式的數據,你給我傳遞個鍵值對格式,我肯定說不支持啊。
所以我們用contentType:"application/json"來改變http請求,表示我發送的數據是json格式的,後端就可以識別了唄。
二、深入研究一下,從根本上解決這個參數傳遞問題
1、請求的數據格式的區別
- 因爲content-Type是用來表示請求體的類型的,默認值爲默認爲application/x-www-form-urlencoded; charset=UTF-8,這個稱爲MIME類型。get請求沒有請求體,所以就沒有content-Type屬性;post請求有請求體,所以就會有content-Type屬性。
- form表單的默認MIME類型也是application/x-www-form-urlencoded,即enctype="application/x-www-form-urlencoded",如果是文件上傳則enctype="multipart/form-data"
- 鍵值對格式:name=www&url=www&checked=true&pId=6
常見場景
1)form表單默認MIME類型時
2)serialize()方法
3)ajax中的js對象(根據ajax文檔顯示,最終js對象在發送時會被轉化成鍵值對格式)
4)get請求
5)FormData對象
4.Json格式:{"name":"www","url":"www","checked":true,"pId":6}
data:JSON.stringify({name:name,url:url,checked:checked,pId:pId}), //將js對象轉換成json字符串格式
contentType:"application/json" //設置請求的MIME類型爲application/json格式,即json格式
5.請求體的區別:Form data 和Request Payload
1、當post請求的content-Type屬性的值爲application/x-www-form-urlencoded; charset=UTF-8時,數據封裝在Form data中,鍵值對格式
2、當post請求的content-Type屬性的值爲application/json或text/plain時,數據封裝在Request Payload中,json格式
2、獲取請求參數(總結一下)
鍵值對格式
1、只要保證請求的參數名和處理器方法的形參名稱一致,自動綁定成功。
2、獲取單個請求參數
1)@RequestParam註解:獲取一個請求參數,並賦值給一個形參
屬性
@RequestParam(value="password",required=false,defaultValue="0") int password
required:設置屬性是否爲必須的,默認爲true。可以設置其值爲false,即當沒有該屬性時也不會報錯。
defaultValue:當required=false時使用,設置請求參數的默認值,不能單獨使用。
2)@PathVariable 註解:針對rest風格的url,可以將url的佔位符參數,綁定到處理器方法的入參處
<a href="/springmvc/testPathvariable/12/tom">testPathvariable</a>
@RequestMapping("/testPathvariable/{id}/{name}")
public String testPathVariable(@PathVariable("id") Integer id,@PathVariable("name") String name) {
System.out.println(id);
return "success";
}
3)@RequestHeader註解:獲取請求頭中的參數。
如:@RequestHeader(value="Accept-Language") 這是獲取請求頭中Accept-Language屬性的值。
4)@CookieValue註解:獲取cookie中某個鍵值對的值。
@CookieValue("JSESSIONID")獲取JSESSIONID屬性的值。
3、獲取多個請求參數
使用POJO(普通的Java類)作爲參數:按照請求參數名(name屬性名)和POJO屬性名進行自動匹配,自動通過setter方法爲該對象填充屬性值,且支持級聯屬性。
json格式
1.@RequestBody User user(推薦)
用實體類接收,json的key要和實體類屬性一致。
2.@RequestBody Map<String,Object> map(次推薦)
用map接收,json的key要和map的key一致
3.@RequestBody String str (這樣是將整個json字符串賦值給str,不推薦)
用字符串接收,然後在自己解析json字符串
ok,結束,喫飯去。