在項目上用到了批量刪除與批量更改狀態,前臺使用了EasyUI的DataGrid,用到了批量更改數據狀態功能。java
在前臺能夠獲取每條數據的ID,可是如何經過數組方式傳遞給後臺?jquery
目前有兩種方式可行:ajax
方式一:json
前臺代碼:api
// 方式一 var _list = {}; for (var i = 0; i < checkedRow.length; i++) { _list["selectedIDs[" + i + "]"] = checkedRow[i].ID; } $.ajax({ url: '@Url.Action("SetCallBackStatus")', //data: { "selectedIDs": _list }, data: _list, dataType: "json", type: "POST", //traditional: true, success: function (responseJSON) { // your logic alert('Ok'); } });
注意:數組
一、_list 是一個對象瀏覽器
二、_list中的屬性須要結合後臺參數名稱,例如」selectedIDs「,組合成相似:selectedIDs[0],selectedIDs[1]...等Request.Paramsapp
這裏是最重要的,不然後臺認不出來。這種方式也能夠傳遞自定義類的數組。組合方式就是selectedIDs[0].FirstName,selectedIDs[0].LastName,selectedIDs[1].FirstName,selectedIDs[1].LastName...框架
三、ajax的data參數直接指定爲_listpost
後臺代碼:
public ActionResult SetCallBackStatus(List<int> selectedIDs){ string result = "ok"; string errMsg = ""; return this.JsonFormat(new { result = result, errMsg = errMsg }); }
方式二:
前臺代碼:
var _list = []; for (var i = 0; i < checkedRow.length; i++) { _list[i] = checkedRow[i].ID; } $.ajax({ url: '@Url.Action("SetCallBackStatus")', data: { "selectedIDs": _list }, //data: _list, dataType: "json", type: "POST", traditional: true, //使用該屬性放置深度序列化 success: function (responseJSON) { // your logic alert('Ok'); } }); 或者使用post var url = '@Url.Action("SetCallBackStatus")'; var data = { "selectedIDs": _list }; //$.param(data,true)不會深度解析參數,返回一個字符串,字符串這種格式:"x=1&y=2&xx=3&xx=4",和GET方式在url後拼接請求參數是同樣的 $.post(url ,$.param(data,true),function(data){ var obj=eval('('+data+')'); console.info('success'); });
注意:
一、_list 是一個數組。
二、ajax參數中data爲{「selectedIDs」:_list}//傳遞的參數selectedIDs爲一個數組
三、這種方式比較重要的 traditional:true,或者將 _list參數轉換一下$.param(_list,true)。這裏其實就是將_list做爲傳統的方式傳遞給後臺。JQUERY默認是作了轉換的,自動在參數後面追加了」[]「。
如:
$.param(object,trad) 參數說明 object:必需。規定要序列化的數組或對象。 trad:可選。布爾值,指定是否使用參數序列化的傳統樣式 有時候提交參數中有數組,設置這個可選項就顯得十分必要了。 var obj = { title: "test", arr:[1,2,3] }; $.param(obj,true) --->>title=test&arr=1&arr=2&arr=3 $.param(obj) --->>title=test&arr%5B%5D=1&arr%5B%5D=2&arr%5B%5D=3
後臺代碼:
同方式一
下面以實際中的例子來講明:
data是一個對象,裏面有一個object對象,object的屬性typeMaskValues爲一個數組,有三個元素在數組中
發送請求方式:
var data={"id":row.id}; for (var key in row) { if (!$.isArray(row[key]) && !$.isFunction(row[key]) && (typeof row[key]) == "object") { continue; } data["object."+key]=row[key]; } var param = JSON.stringify(data); var param2 = $.param(data); var param3 = $.param(data,true); debugger; $.post(url,data,function(data){ }); $.post(url,param,function(data){ console.info(111); }); $.post(url,param2,function(data){ console.info(222); }); $.post(url,param3,function(data){ console.info(222); }); $.ajax({ url: url, data: data, dataType: "json", type: "POST", // traditional: true, //使用該屬性放置深度序列化 success: function (responseJSON) { console.info(333); } }); $.ajax({ url: url, data: data, dataType: "json", type: "POST", traditional: true, //使用該屬性放置深度序列化 success: function (responseJSON) { console.info(444); } });
1. JSON.Stringify()處理後返回字符串:
var param = JSON.stringify(data);
由於data爲一個對象,因此在轉化爲JSON字符串的時候以"{}"包裹,裏面的數組格式爲:"xx":["1","2"]
JSON字符串開始:
JSON字符串裏面的數組:
2. $.param 處理後的格式爲字符串,該字符串的式樣爲get請求在後面拼接多個參數的方式同樣,
var param2 = $.param(data);
字符串開始:
裏面的數組:
3.$.param 處理後的格式爲字符串,該字符串的式樣爲get請求在後面拼接多個參數的方式同樣,
var param3 = $.param(data,true);
字符串開始:
裏面的數組:
POST方式向後臺傳遞參數:
1. $.post(url,data,function(data){});
控制檯的參數傳遞:
2. $.post(url,param,function(data){})
3.$.post(url,param2,function(data){});
4.$.post(url,param3,function(data){
console.info(222);
});
5.$.ajax({
url: url,
data: data,
dataType: "json",
type: "POST",
// traditional: true, //使用該屬性放置深度序列化
success: function (responseJSON) {
console.info(333);
}
});
6.$.ajax({
url: url,
data: data,
dataType: "json",
type: "POST",
traditional: true, //使用該屬性放置深度序列化
success: function (responseJSON) {
console.info(444);
}
});
針對自定義的類,也能夠經過方式一jquery ajax傳遞給後臺
例如:
// 自定義Person類 public class Person { public string FirstName { get; set; } public string LastName { get; set; } }
// 後臺Action public ActionResult SetCallBackStatus(List<Person> selectedIDs) { string result = "ok"; string errMsg = ""; return this.JsonFormat(new { result = result, errMsg = errMsg }); }
此時前臺js能夠這樣寫:
var _list = {}; for (var i = 0; i < checkedRow.length; i++) { _list["selectedIDs[" + i + "].FirstName"] = checkedRow[i].FirstName; _list["selectedIDs[" + i + "].LastName"] = checkedRow[i].LastName; } $.ajax({ url: '@Url.Action("SetCallBackStatus")', //data: { "selectedIDs": _list }, data: _list, dataType: "json", type: "POST", //traditional: true, success: function (responseJSON) { // your logic alert('Ok'); } });
jQuery ajax的traditional參數的做用
通常的,可能有些人在一個參數有多個值的狀況下,可能以某個字符分隔的形式傳遞,好比頁面上有多個checkbox:
$.ajax{
url:"xxxx",
data:{
p: "123,456,789"
}
}
而後後臺獲取參數後再分隔,這種作法有很大弊端,試問若是某一個參數值中出現了分隔符所使用的字符,會出現什麼狀況呢?固然後臺獲取的參數將與實際狀況不符.
這時我想到了將上述代碼寫成這樣:
$.ajax{
url:"xxxx",
data:{
p: ["123", "456", "789"]
}
}
若是單純寫成這樣,在java後臺是沒法取到參數的,由於jQuery須要調用jQuery.param序列化參數,
jQuery.param( obj, traditional )
默認的話,traditional爲false,即jquery會深度序列化參數對象,以適應如PHP和Ruby on Rails框架,
但servelt api沒法處理,咱們能夠經過設置traditional 爲true阻止深度序列化,而後序列化結果以下:
p: ["123", "456", "789"] => p=123&p=456&p=456
隨即,咱們就能夠在後臺經過request.getParameterValues()來獲取參數的值數組了,
因此,好比咱們前臺有多個checkbox,前臺的代碼能夠寫成:
var values = $("input[type=checkbox]").map(function(){
return $(this).val();
}).get();
$.ajax{
url:"xxxx",
traditional: true,
data:{
p: values
}
}
關於頁面向後臺傳遞數組,自動添加[]的問題也使用攔截器:
@Service("requestParamInterceptor") @Scope(value=ConfigurableBeanFactory.SCOPE_PROTOTYPE) @SuppressWarnings("serial") public class RequestParamInterceptor implements Interceptor { private static final Log log = LogFactory.getLog(RequestParamInterceptor.class); private static Pattern SCRIPT_PATTERN = Pattern .compile("<script.*>.*<\\/script\\s*>"); private static Pattern HTML_PATTERN = Pattern.compile("<[^>]+>"); private String uriEncoding=null; public String intercept(ActionInvocation invocation) throws Exception { //經過核心調度器invocation來得到調度的Action上下文 final ActionContext context = invocation.getInvocationContext(); HttpServletRequest request = (HttpServletRequest) context.get(ServletActionContext.HTTP_REQUEST); HttpServletResponse response = (HttpServletResponse) context.get(ServletActionContext.HTTP_RESPONSE); response.setCharacterEncoding(request.getCharacterEncoding());//TOMCAT WEB.XML設置的編碼方式 response.setHeader("Pragma", "no-cache"); response.setHeader("Cache-Control", "no-cache"); response.setHeader("Cache-Control", "no-store"); response.setDateHeader("Expires", 0); if(uriEncoding == null) getUriEncoding(); String method = request.getMethod(); Boolean isGet=false; if ("get".equalsIgnoreCase(method) && request.getCharacterEncoding() != null && !request.getCharacterEncoding().equals(uriEncoding)) isGet=true; //獲取Action上下文的值棧 ValueStack stack = context.getValueStack(); Map<?, ?> paramMap = request.getParameterMap(); int flag = 0; String lowStr = null; Set<?> keSet = paramMap.entrySet(); for (Iterator<?> itr = keSet.iterator(); itr.hasNext();) { try { @SuppressWarnings("rawtypes") Map.Entry me = (Map.Entry) itr.next(); Object ok = me.getKey(); if(ok.equals("_")) continue; Object ov = me.getValue(); String[] value = new String[1]; if (ov instanceof String[]) { value = (String[]) ov; } else { value[0]=ov.toString(); } //處理後的請求參數加入值棧中 處理有些數組名後自動加了[]的狀況 stack.setValue(((String)ok).replace("[]", ""), (String[])value); } catch(Exception e) { } } return invocation.invoke(); } public void destroy() { } public void init() { } public void getUriEncoding() { String encoding=null; Map<String, String> map = TomcatServer.getConnectorUriEncoding(); for(Map.Entry<String, String> entry : map.entrySet()) { // System.out.println(entry.getKey() + " --> " + entry.getValue()); encoding=entry.getValue(); break; } try { if(VerifyString.isEmpty(encoding)) encoding=SystemTool.getTomcatConfig("URIEncoding"); } catch (IOException e) { } //System.out.println(uriEncoding); if(VerifyString.isEmpty(encoding)) uriEncoding="ISO-8859-1"; else uriEncoding=encoding; } }
在sturts2的xml中配置攔截器:
<interceptors> <interceptor name="illegalCharacter" class="requestParamInterceptor" /> <interceptor name="authority" class="authorityInterceptor"></interceptor> <interceptor-stack name="hwhmdStack"> <interceptor-ref name="illegalCharacter"></interceptor-ref> <interceptor-ref name="authority"> <param name="indexAction">login</param> <param name="appCode">cost</param> </interceptor-ref> <interceptor-ref name="defaultStack" /> </interceptor-stack> </interceptors> <default-interceptor-ref name="hwhmdStack" />
又例如:
java的Action:
private List<PersonnelObject> personnelObjects; public List<PersonnelObject> getPersonnelObjects() { return personnelObjects; } public void setPersonnelObjects(List<PersonnelObject> personnelObjects) { this.personnelObjects = personnelObjects; }
前臺:
錯誤寫法1.
//下面這麼寫後臺沒法獲取personnelObjects的值 var data = {}; var personnelList = new Array(); for(var i = 0;i<checkRows.length;i++){ personnelList.push(checkRows[i]); } data["personnelObjects"] = personnelList; $.post(funUrl,data,function(data){});
google請求參數:
錯誤寫法2:
//這麼寫會發現後臺personnelObjects也是爲null,接受不到值 var data = {}; for(var i = 0;i<checkRows.length;i++){ personnelList.push(checkRows[i]); data["personnelObjects["+i+"]"] = checkRows[i]; } $.post(funUrl,data,function(data){})
google請求參數爲:
可是若是這麼寫:
//這麼寫會發現後臺personnelObjects有值,集合中的每一個對象的ID有值 var data = {}; for(var i = 0;i<checkRows.length;i++){ personnelList.push(checkRows[i]); data["personnelObjects["+i+"].id"] = i;//只傳遞數組中的每一個對象的ID值 } $.post(funUrl,data,function(data){})
疑問:傳遞完整的每一個對象,後臺接受不到值;若是傳遞的是每一個對象的某個屬性,則會獲取到對應的值
進一步測試
//這麼寫會發現後臺personnelObjects有值,集合中的每一個對象的ID有值 var data = {}; for(var i = 0;i<checkRows.length;i++){ personnelList.push(checkRows[i]); //data["personnelObjects["+i+"].id"] = i;//只傳遞數組中的每一個對象的ID值 for (var key in checkRows[i]){ if (!$.isArray(checkRows[i][key]) && !$.isFunction(checkRows[i][key]) && (typeof checkRows[i][key]) == "object") { continue; } data["personnelObjects["+i+"]."+key]=checkRows[i][key]; } } $.post(funUrl,data,function(data){})
google瀏覽器的請求參數:
發現這種寫法,後臺也可以正常的獲取.
好像向後臺傳遞參數的時候,若是屬性在符號".id"能夠正常解析,可是[id]不可以解析.
接下來測試$.param:
var aa = $.param(data);//這個就是正常的jquery的參數序列化 var bb = $.param(data,true);
aa的參數序列化格式爲:
bb的參數格式爲:
可見:
$.param(data,true)的淺度序列化並無解析出object對象,因此在傳遞參數的時候並無可以真正的給後臺傳值.
$.param(data)就可以正確的解析出來
總結:
普通參數和基本類型數組可使用$.param(data,true);
若是要傳遞非基本類型數組,那麼就要循環數組中的每一個對象,利用"."來賦值參數屬性