在项目上用到了批量删除与批量更改状态,前台使用了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);
若是要传递非基本类型数组,那么就要循环数组中的每一个对象,利用"."来赋值参数属性