SpringMVC學習筆記:Ajax與Controller的引數互動
jQuery.ajax( options )中重要引數設定
jQuery.ajax( options ) : 通過 HTTP 請求載入遠端資料。通過jQuery.ajax與SpringMVC的Controller互動時候,需要關注以下幾個引數(一個典型的ajax請求程式碼如下):
$.ajax({
type: "POST",
url: "$!{_index}/buAuth/save4",
data:JSON.stringify(dataObj) ,
contentType: "application/json; charset=utf-8" ,
dataType: "json",
success: function (response, ifo) {}
});
- contentType
引數型別:String
說明:(預設: “application/x-www-form-urlencoded”) 傳送資訊至伺服器時內容編碼型別。預設值適合大多數應用場合。告訴伺服器從瀏覽器提交過來的資料格式。
例如:我們提交資料時假如使用了 JSON2.js 中方法 JSON.stringify(obj) 格式化為json字串後,再預設提交就會報錯。這個時候就需要指定提交的內容格式為:”application/json”。 - data
引數型別:Object,String
說明:傳送到伺服器的資料。若data資料型別為JavaScript物件或陣列,Jquery在提交之前自動呼叫JQuery.param()方法把要傳送的資料編碼成為”application/x-www-form- urlencoded”格式的資料(即 name=value&name1=value1),此時引數為Object並且必須為 Key/Value 格式;如果為陣列,jQuery 將自動為不同值對應同一個名稱。如 {foo:[“bar1”, “bar2”]} 轉換為 ‘&foo=bar1&foo=bar2’;
若data資料型別為String型別,則直接預設該資料已經按照”application/x-www-form-urlencoded”格式編碼完成,不再轉換。 - dataType
引數型別:String
說明:預期伺服器返回的資料型別。設定HttpHeader中“Accept”域的內容,告訴伺服器瀏覽器可以想要返回的資料格式型別,同時JQuery也會根據該型別對返回的資料進行處理。如果不指定,jQuery 將自動根據 HTTP 包 MIME 資訊返回 responseXML 或 responseText,並作為回撥函式引數傳遞,可用值:
“xml”: 返回 XML 文件,可用 jQuery 處理。
“html”: 返回純文字 HTML 資訊;包含 script 元素。
“script”: 返回純文字 JavaScript 程式碼。不會自動快取結果。
“json”: 返回 JSON 資料 。JQuery將返回的字串格式資料自動轉化為Javascript物件,便於直接使用obj.property格式訪問。若沒有指定該選項,即使返回的是JSON格式的字串,JQuery也不會自動轉換。
“jsonp”: JSONP 格式。使用 JSONP 形式呼叫函式時,如 “myurl?callback=?” jQuery 將自動替換 ? 為正確的函式名,以執行回撥函式。
Controller中接受引數
- 普通方式傳遞引數
@RequestMapping(value = "buAuth/save")
@ResponseBody
public String save(Integer id){
System.out.println(id);
return "SUCCESS";
}
採用這種方式接受引數,其底層實現原理類似於request. getParameter()獲得引數,注意:如果位址列/buAuth/save上面沒有傳遞引數,當id為Integer的時候值為null,那麼當id為int型的時候會報錯.
當採用位址列為/buAuth/save?id=10的訪問方式時候,引數附加在Url的後面,此時Controller中有三種接收方式
1.String save (@RequestParam(value=”userid”)Integer id),這樣會把位址列引數名為userid的值賦給引數id,如果用位址列上的引數名為id,則接收不到
2. String save (@RequestParam Integer id),這種情況下預設會把id作為引數名來進行接收賦值
3.String save (Integer id),這種情況下也會預設把id作為引數名來進行接收賦值
注:如果引數前面加上@RequestParam註解,如果位址列上面沒有加上該註解的引數,例如:id,那麼會報404錯誤,找不到該路徑。
當採用Ajax請求方式時候,需設定兩兩處(1)設定contentType的引數值為:application/x-www-form-urlencoded(該值即為預設值,也可以不設定);(2)請求引數data必須為JS物件。此時由上文Ajax引數說明可知jQuery自動呼叫JQuery.param()方法把要傳送的資料組織成類似於application/x-www-form-urlencoded(即name=value&name1=value1),然後在Controller中SpringMVC框架自動把對應的值注入到與之對應的引數中。採用Ajax的方式舉例如下:
$.ajax({
type: "POST",
url: "$!{_index}/buAuth/save",
data: {buAuth:JSON.stringify(dataObj),menuIds:menu_ids},
dataType: "json",
success: function(data){ }
});
或
$.post("$!{_index}/buAuth/save",{buAuth:JSON.stringify(dataObj),menuIds:menu_ids},function(result){});
@RequestMapping(value = "buAuth/save")
@ResponseBody
public String save(String buAuth,String menuIds){
try {
//需要呼叫函式把字串轉化為對應的Bean
BuAuth buAuthBean = JSON.parseObject(buAuth, BuAuth.class);
System.out.println(menuIds);
}catch (Exception e){
System.out.println(e.getMessage());
}
return "SUCCESS";
}
注:(1)可以採用這種方式傳遞多個物件,把每個物件在前端轉換為JSON字串對映到Controller對應的方法引數上,然後在函式體裡分別進行解析獲得到不同的物件,從而達到傳遞多個物件的效果。
(2)當Controller的方法引數為實體類時,採用這種方式同樣能夠自動注入到引數的實體類中,此時的注入過程類似於struts2中的Model,舉例如下:
$.ajax({
type: "POST",
url: "$!{_index}/buAuth/save2",
data: dataObj,//dataObj必須為js物件,例如:{menuType:"POP",busiScope:"12,11,89"}
dataType: "json",
success: function(data){}
});
@RequestMapping(value = "buAuth/save2")
@ResponseBody
public String save2(BuAuth buAuth){
return "SUCCESS";
}
- @RequestBody註釋進行引數傳遞
@RequestMapping(value = "buAuth/save1")
@ResponseBody
public String save1(@RequestBody BuAuth buAuth){
return "SUCCESS";
}
採用@RequestBody標註的引數,SpringMVC框架底層能夠自動完成JSON字串轉對應的Bean並注入到方法引數中,主要是通過使用HandlerAdapter 配置的HttpMessageConverters來解析post data body,然後繫結到相應的bean上的。此時Ajax傳送的data值必須為Json字串,如果Controller中需要對映到自定義Bean物件上上,則必須設定Ajax的contentType為application/json(或application/xml)。這種方式完整舉例如下:
$.ajax({
type: "POST",
url: "$!{_index}/buAuth/save1",
data:JSON.stringify(dataObj) ,//傳遞引數必須是Json字串
contentType: "application/json; charset=utf-8",//必須宣告contentType為application/json,否則後臺使用@RequestBody標註的話無法解析引數
dataType: "json",
success: function (response, info) {}
});
@RequestMapping(value = "buAuth/save1")
@ResponseBody
public String save1(@RequestBody BuAuth buAuth){
return "SUCCESS";
}
注:(1)此時前端直接用$.post()
直接請求會有問題,ContentType預設是application/x-www-form-urlencoded
。需要使用$.ajaxSetup()標示下ContentType為application/json(或application/xml)。
$.ajaxSetup({ContentType:" application/json"});
$.post("$!{_index}/buAuth/save",{buAuth:JSON.stringify(dataObj),menuIds:menu_ids},function(result){});
(2)可以使用@ResponseBody傳遞陣列,如下舉例(做為整理直接引用其他部落格例子)
var saveDataAry=[];
var data1={"userName":"test","address":"gz"};
var data2={"userName":"ququ","address":"gr"};
saveDataAry.push(data1);
saveDataAry.push(data2);
$.ajax({
type:"POST",
url:"user/saveUser",
dataType:"json",
contentType:"application/json",
data:JSON.stringify(saveData),
success:function(data){ }
});
@RequestMapping(value = "saveUser", method = {RequestMethod.POST }})
@ResponseBody
public void saveUser(@RequestBody List<User> users) {
userService.batchSave(users);
}
(3)Controller中的同一個方法只能使用@ResponseBody標記一個引數。也即是說無法直接通過該方法同時傳遞多個物件,不過可以間接通過設定一箇中間pojo物件(設定不同的屬性)來達到傳遞多個物件的效果。舉例如下:
var buAuthPage = {
buAuth : data,
menuInfo : {code:"100"}
};
$.ajax({
type: "POST",
url: "$!{_index}/buAuth/save5",
data: JSON.stringify(buAuthPage),
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(data){
}
});
public class BuAuthPage {
BuAuth buAuth;
MenuInfo menuInfo;
public BuAuth getBuAuth() {
return buAuth;
}
public void setBuAuth(BuAuth buAuth) {
this.buAuth = buAuth;
}
public MenuInfo getMenuInfo() {
return menuInfo;
}
public void setMenuInfo(MenuInfo menuInfo) {
this.menuInfo = menuInfo;
}
}
@RequestMapping(value = "buAuth/save5")
@ResponseBody
public String save5(@RequestBody BuAuthPage buAuthPage){
return "SUCCESS";
}