前言:
相信很人都被springmvc接收数组问题折磨过,查过几个解决方案,都不能很好的解决。那些方法一般存在一个问题:把接收到的数据结构转换成你想要的结构时,不好处理。为什么说不好处理下文有具体例子介绍(见1.2)。
1 本文springmvc版本为3.1 ,ecplise:月神(luna),tomcat:7.0,jdk:1.6,maven:3.0.
2 我博客所有文章目录:http://blog.csdn.net/wabiaozia?viewmode=contents
3 注:百度链接页面异常,点此链接恢复正常:点击打开链接
常见的解决方案VS我要介绍的方案:
在springmvc接收数组对象List<user>时:
批量删除比较简单,用我的解决方案一的十分之一功力就可以解决,传个id数组就行了,后台根据id数组删除就行了。麻烦的是对一 个对象的数组,进行批量新增修改,这时,如果可以把前台传来的数据,直接封装到对象的数组(List<user>)中:即数据封装到list的同时,也把name,pwd两个属性,封装到user对象中,就会简化后面对数据的处理。
一:常见的解决方案
1.1博客上看到的一些解决方案:
着重介绍下引入新的"参数解析器",使用“springmvc内置的支持”,这两个方案,为什么要着重介绍呢?因为我发现很多人都是从这里拷贝的,但是没有拷贝完整,所以导致有人在文章下面评论:楼主,你真的测试过这个方法吗?你确定这个办法可行? 我觉得引入新的“参数解析器是很好的办法”,涛哥(京东)写的"参数解析器"点我:我是外链,使用“springmvc内置的支持”点我:我是外链。而且开涛在这个专栏里也写了参数绑定里的源码,推荐可以去看看。但是项目组内是否允许你这样使用是个问题。
1.2还有一个作者写的:
点我:我是外链这个我测试过,可行,但是不好处理接收的数据。为什么这么说呢:我想接受的数据是User对象的数组,但是接收的数据是:[{name=111, pwd=111},{name=222, pwd=222}],不能自动封装到我的对象里,没有把name,pwd,封装到User对象中。 下面是我的测试:
实体类MyDomain
[html]
view plain
copy
class MyDomain{ private String name; private String pwd; .......... }
我想封装到 List<MyDomain> 中,list里是两个MyDomain对象,封装到 List的同时也把name和pwd两个属性也封装到MyDomain对象中,见下图中 上半部分图。但是他的list里是两个LinkedHasnMap,name和pwd两个属性没有封装到MyDomain对象中,见图下半部分1,不是我想要的list里是两个MyDomain对象。谁有好的办法可以发给我。。。。。。。
debug跟一下:
二:我的方案解决方案
2.1 方案一
我最常用的解决方案是RequestParam,直接提交表单
jsp页面
[html]
view plain
copy
<form .....method=
"post"..............
> 姓名1:
<input type=
"text" name=
"id" value=
""> 年龄1:
<input type=
"text" name=
"age" value=
""> 地址1:
<input type=
"text" name=
"address" value=
""> 姓名2:
<input type=
"text" name=
"id" value=
""> 年龄2:
<input type=
"text" name=
"age" value=
""> 地址2:
<input type=
"text" name=
"address" value=
""><pre code_snippet_id=
"1597573" snippet_file_name=
"blog_20160304_1_2164278" name=
"code" class=
"html"></form>
[html]
view plain
copy
controller @RequestMapping("/...........") public String update(Export export, @RequestParam("id")String[] ids, @RequestParam("age")String[] ages, @RequestParam("address")String[] address, Model model){ //ids,ages,addres接收进来的是什么样的数据呢? //接收的数据类型是ids[111,222,333],ages[222,333,444],address[sss,ddd,yyy] //拓展:若用@RequestParam("id")String ids接收,则传进来的是一个个String字符串,用逗号分隔。例如ids:“abc,cde,def” //批量增加 for(int
i=
0,
len=
ids.length;i
<len;i++){ User
user=
new User(); user.setId(ids[i]); user.setAge(ages[i]); user.setAddress(address[i]); userDao.isnert(user); } } 这种方案适合特别修改删除,而且相比用js拼接数据有个好处,不用在前端拼接参数。
2.2 方案二
由于后台不能接收数组,所以要想办法让后台接收数组,这样就陷入了困境。这里可以转换下思路,
为什么非要让后台接收数组呢?可以把数组序列化成Json字符串提交,后台springmvc里用@ RequestBody
String 方式接收,然后把这个接收到的json串用json工具转换为数组,这样就解决了springmvc不能绑定对象数组的问题了。
为什么用和json相关的解决方案呢?因为现在json和java对象的转换的工具特别多,也特别方便,而且网上有很多成熟的工具,jackson,Gson,fastjson.......等等,所以用和json相关的解决方案。
因为jackson,引入jar少。所以我这里用了jackson处理。不会jackson的可以参考点我:我是外链和点我:我是外链
js:
[html]
view plain
copy
var
users =
JSON.stringify([ {name: "wabiaozai1", pwd: "123"}, {name: "wabiaozai2", pwd: "123"} ]); $.ajax({ type: "post", url: "/wabiaozai", data:users , contentType: "application/json;
charset=
utf-8", dataType: "json", success: function (response, ifo) { alert("success"); }, error: function () { alert("error"); } })
js中注意两个细节:
dataType:'json',//预期的服务器响应的数据类型。
contentType: "application/json; charset=utf-8",//发送数据到服务器时所使用的内容类型。默认是:"application/x-www-form-urlencoded"。 关于ajax分享两篇文章:jquery_ajax: 点我:我是外链 ajax: 点击打开链接
如果不加contentType,myDomain接收的数据为类似{"id":243,%name":4,"age":1048,"格式,json转换会报错,
controller层
我这里用的@requestBody,是否可以用其他的我没有测试。
[html]
view plain
copy
@RequestMapping(
value =
"/wabiaozai",
method =
RequestMethod.POST) public void myDomain(HttpServletRequest request, @RequestBody String myDomain) throws Exception{ ObjectMapper
objectMapper =
new ObjectMapper(); JavaType
javaType =
objectMapper.getTypeFactory().constructParametricType(List.class, MyDomain.class); List
<MyDomain> list =
objectMapper.readValue(myDomain, javaType); System.out.println(""); }
这里提一点@RequestBody的相关知识
1 该注解用来处理Content-Type编码方式: 一般不是适用于application/x-www-form-urlencoded编码的内容,而是适用于application/json, application/xml等;它是通过使用HandlerAdapter 配置的HttpMessageConverters来解析post data body,然后绑定到相应的bean上的。因为配置有FormHttpMessageConverter,所以也可以用来处理 application/x-www-form-urlencoded的内容,处理完的结果放在一个MultiValueMap<String, String>里,这种情况在某些特殊需求下使用,详情查看FormHttpMessageConverter api;更多介绍见:
点击打开链接
2 官方文档是这样描述的(spring3.2.18里关于注解@RequestBody的描述):
使用@RequestBody 注解映射请求体时:方法参数中的@RequestBody 注解表示方法参数应该被绑定了 HTTP请求体的值。请求体到方法参数的转换是由 HttpMessageConverter 完成的。HttpMessageConverter 负责将 HTTP 请求信息转换成对象,以及将对
象转换回一个 HTTP 响应体。对于@RequestBody 注解,RequestMappingHandlerAdapter 提供了以下几种默认的HttpMessageConverter 支持:
[html]
view plain
copy
ByteArrayHttpMessageConverter 用以转换字节数组 StringHttpMessageConverter 用以转换字符串 FormHttpMessageConverter 用以将表格数据转换成MultiValueMap
<String, String
>或从 MultiValueMap
<String,String
>中转换出表格数据 SourceHttpMessageConverter 用于javax.xml.transform.Source 类的互相转换....
更多请参照官方文档。。。。
三:debug看结果
ok,代码写完了,我们debug一下看结果:
用json转换:不会jackson的可以参考http://www.blogjava.net/bolo/archive/2014/04/16/412533.html
..............................................................................................呵呵,成功..............................................................................................
四:思考
这个是在前端拼接组合的users,
var users = JSON.stringify([ {name: "wabiaozai1", pwd: "123"}, {name: "wabiaozai2", pwd: "123"} ]);
有没有办法不要拼?我要告诉你
http://blog.csdn.net/lutinghuan/article/details/46820023 里面的第4种方法:将表单对象序列化成Json字符串提交,以List接收 ,把对象转换成json数组,我已经测试过,也成功转换,但究竟有bug吗暂时未知。
五:spring3.2 直接支持泛型集合
##注:spring 3.2 直接支持泛型集合,如List<Sample> Map<String, Sample>等集合泛型
具体步骤
1 要配置驱动注解<mvc:annotation-driven/> ,里面注册了会把json绑定到list的"Bean实例"(注册的实例会因为spring版本的不同而不同,具体注册里哪些实例详见官网)
2 前台传json数组,后台直接@RequestBody List<Color> list接收就可以了。
亲测可行。
也可以参见:http://jinnianshilongnian.iteye.com/blog/1835431 评论里demo
六:写在最后
20160427重新排版.
20160428重新配图.
有真的不要组合对象传递参数的吗?
欲知后事如何请听下回分解。。。。。。。。。。。
我博客所有文章目录:http://blog.csdn.net/wabiaozia?viewmode=contents
转载标明链接:http://blog.csdn.net/wabiaozia/article/details/50803581