利用post向后台传递数组或者list参数

在项目上用到了批量删除与批量更改状态,前台使用了EasyUI的DataGrid,用到了批量更改数据状态功能。

在前台可以获取每条数据的ID,但是如何通过数组方式传递给后台?

目前有两种方式可行:

方式一:

前台代码:

// 方式一  
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');  
    }  
}); 

注意:

1、_list 是一个对象

2、_list中的属性需要结合后台参数名称,例如”selectedIDs“,组合成类似:selectedIDs[0],selectedIDs[1]...等Request.Params

这里是最重要的,否则后台认不出来。这种方式也可以传递自定义类的数组。组合方式就是selectedIDs[0].FirstName,selectedIDs[0].LastName,selectedIDs[1].FirstName,selectedIDs[1].LastName...

3、ajax的data参数直接指定为_list

后台代码:

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');
});	 

注意:

1、_list 是一个数组。

2、ajax参数中data为{“selectedIDs”:_list}//传递的参数selectedIDs为一个数组

3、这种方式比较重要的 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为一个数组,有三个元素在数组中

085955_TxD4_2331760.png

发送请求方式:

    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字符串开始:

090425_megM_2331760.png

JSON字符串里面的数组:

090510_EAIv_2331760.png

2. $.param 处理后的格式为字符串,该字符串的式样为get请求在后面拼接多个参数的方式一样,

var param2 = $.param(data);

字符串开始:

090635_zFnK_2331760.png

里面的数组:

092641_KWlE_2331760.png

3.$.param 处理后的格式为字符串,该字符串的式样为get请求在后面拼接多个参数的方式一样,

var param3 = $.param(data,true);

字符串开始:

092701_ukmu_2331760.png

里面的数组:

092736_GsoD_2331760.png

POST方式向后台传递参数:

1. $.post(url,data,function(data){});        

控制台的参数传递:

090811_V1o7_2331760.png

2. $.post(url,param,function(data){})

090914_bsW3_2331760.png

3.$.post(url,param2,function(data){});    

090811_V1o7_2331760.png

4.$.post(url,param3,function(data){
        console.info(222);
    });    

092325_SoQd_2331760.png

5.$.ajax({  
        url: url,  
        data: data,  
        dataType: "json",  
        type: "POST",  
//        traditional: true,  //使用该属性放置深度序列化
        success: function (responseJSON) {  
            console.info(333);
        }  
    });

091755_W6ty_2331760.png

6.$.ajax({  
        url: url,  
        data: data,  
        dataType: "json",  
        type: "POST",  
        traditional: true,  //使用该属性放置深度序列化
        success: function (responseJSON) {  
            console.info(444);
        }  
    });

091847_zV4a_2331760.png

 

针对自定义的类,也可以通过方式一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请求参数:

115510_ZSTD_2331760.png

错误写法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请求参数为:

115229_TN5X_2331760.png

但是如果这么写:

//这么写会发现后台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浏览器的请求参数:

114940_sqmK_2331760.png

发现这种写法,后台也能够正常的获取.

好像向后台传递参数的时候,如果属性在符号".id"可以正常解析,但是[id]不能够解析.

接下来测试$.param:

var aa = $.param(data);//这个就是正常的jquery的参数序列化
var bb = $.param(data,true);

aa的参数序列化格式为:

120212_KbdH_2331760.png

bb的参数格式为:

120315_yVTC_2331760.png

可见:

$.param(data,true)的浅度序列化并没有解析出object对象,所以在传递参数的时候并没有能够真正的给后台传值.

$.param(data)就能够正确的解析出来

总结:

普通参数和基本类型数组可以使用$.param(data,true);

如果要传递非基本类型数组,那么就要循环数组中的每个对象,利用"."来赋值参数属性

转载于:https://my.oschina.net/u/2331760/blog/1505993

  • 6
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值