SpringMVC数据绑定全面示例(复杂对象,数组等)
点击链接查询原文
http://www.xdemo.org/springmvc-data-bind/
已经使用SpringMVC开发了几个项目,平时也有不少朋友问我数据怎么传输,怎么绑定之类的话题,今天做一个总结。在此之前,大家可以看一下我之前的一篇关于Spring restful的文章http://www.xdemo.org/spring-restful/。
项目下载:http://pan.baidu.com/share/link?shareid=955245807&uk=1896630845
首先贴出Controller的全部内容
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
|
/** * @author <a href="http://www.xdemo.org">xdemo.org</a> */ @Controller @RequestMapping (value= "/request" ) public class RequestParamController { /** * 最简的配置,不是用@RequestParam,效果和get2一样,默认required=false * 请求方式不限 * @param p1 * @param map */ @RequestMapping (value= "get0" ) public void get0(String p1,ModelMap map){ map.addAttribute( "p1" , p1); //往页面传递 } /** * value="p1"表示参数名称<br> * required=true表示如果没有传递参数"p1",则会报400参数异常<br> * 使用void表示约定的路径,即request/get1.jsp * @param p1 * @param map */ @RequestMapping (value= "get1" ,method=RequestMethod.GET) public void get1( @RequestParam (value= "p1" ,required= true )String p1,ModelMap map){ map.addAttribute( "p1" , p1); //往页面传递 } /** * 和get1不同的是,p1这个参数不一定非得需要,即使不给这个参数,也可以正常运行<br> * 返回String是视图的名称,只要将map赋值,给的值也会带到前抬 * @param p1 * @param map * @return */ @RequestMapping (value= "get2" ,method=RequestMethod.GET) public String get2( @RequestParam (value= "p1" ,required= false )String p1,ModelMap map){ map.addAttribute( "p1" , p1); //往页面传递 return "request/get2" ; } /** * 和get2不同的是,返回的对象是ModelAndView * 表示绑定了视图和数据的对象,数据就是ModelMap中的Key-Value * @param p1 * @param map * @return */ @RequestMapping (value= "get3" ,method=RequestMethod.GET) public ModelAndView get3( @RequestParam (value= "p1" ,required= false )String p1,ModelMap map){ map.addAttribute( "p1" , p1); return new ModelAndView( "request/get2" ,map); } /** * 跳转到页面 * @throws NoSuchAlgorithmException */ @RequestMapping ( "userForm" ) public String userForm(HttpServletResponse response) throws NoSuchAlgorithmException{ CookieUtils.writeCookie(response, - 1 , "x" , "dddddddddddddd" ); return "request/userForm" ; } /** * 绑定数据到User对象,支持Map,Set,List,Array等,但是需要使用下标,不是很灵活 * 请查看user2的写法 * @param user * @param map */ @RequestMapping (value= "user" ) public void user(User user,ModelMap map){ map.addAttribute( "user" , user); } /** * 这里可以接受List,Array,Set等,写法是一样的,注意前端写法<br> * 另外这个必须要使用MappingJacksonHttpMessageConverter这个消息转换器 * 请看我上面的配置 * @param user * @return */ @ResponseBody @RequestMapping ( "user2" ) public String user2( @RequestBody List<User> user){ System.out.println(user.size()); return "" ; } /** * 这个方法只支持POST * @param s * @return */ @ResponseBody @RequestMapping ( "array" ) public String array( @RequestBody String[] s){ System.out.println(s.length); return "" ; } /** * 这个比较奇葩,来自一位朋友的写法,即.xxx/5,4这样的请求,SpringMVC竟然也是支持的 * @param id * @return */ @ResponseBody @RequestMapping (value= "array/{id}" ,method=RequestMethod.GET) public String array2( @PathVariable ( "id" )Long[] id){ System.out.println(id.length); return "array length:" +id.length+ "" ; } /** * 一个表单对应多个Bean对象,这些Bean中有相同的属性,那么需要在分装他们的一个整体的对象 * 使之支持object.property的表达式 * @param c */ @ResponseBody @RequestMapping ( "complex" ) public void complexObject(C c){ System.out.println(c.getA().getX()); System.out.println(c.getB().getX()); } /** * 读取Cookie的值 * @param x * @return */ @ResponseBody @RequestMapping ( "cookie" ) public String cookie( @CookieValue ( "x" )String x){ return x; } } |
这种方式支持get和post,参数可选
1
2
3
4
5
6
7
8
9
10
|
/** * 最简的配置,不是用@RequestParam,效果和get2一样,默认required=false * 请求方式不限 * @param p1 * @param map */ @RequestMapping (value= "get0" ) public void get0(String p1,ModelMap map){ map.addAttribute( "p1" , p1); //往页面传递 } |
访问方式简单的比如http://localhost:8080/springmvc-param/request/get0?p1=xxx。
这种方式支持get,参数必须
1
2
3
4
5
6
7
8
9
10
11
|
/** * value="p1"表示参数名称<br> * required=true表示如果没有传递参数"p1",则会报400参数异常<br> * 使用void表示约定的路径,即request/get1.jsp * @param p1 * @param map */ @RequestMapping (value= "get1" ,method=RequestMethod.GET) public void get1( @RequestParam (value= "p1" ,required= true )String p1,ModelMap map){ map.addAttribute( "p1" , p1); //往页面传递 } |
这种方式和第一种不同的是,指定了访问访问必须为GET,而且参数是必须的,可以通过如下方式访问这个地址:http://localhost:8080/springmvc-param/request/get1?p1=xxxx。
这种方式仅支持GET,参数可选
1
2
3
4
5
6
7
8
9
10
11
12
|
/** * 和get1不同的是,p1这个参数不一定非得需要,即使不给这个参数,也可以正常运行<br> * 返回String是视图的名称,只要将map赋值,给的值也会带到前抬 * @param p1 * @param map * @return */ @RequestMapping (value= "get2" ,method=RequestMethod.GET) public String get2( @RequestParam (value= "p1" ,required= false )String p1,ModelMap map){ map.addAttribute( "p1" , p1); //往页面传递 return "request/get2" ; } |
这个方法和第二种唯一不同的就是参数是可选的,其他没有不同。
这种方式仅支持GET,参数可选
1
2
3
4
5
6
7
8
9
10
11
12
|
/** * 和get2不同的是,返回的对象是ModelAndView * 表示绑定了视图和数据的对象,数据就是ModelMap中的Key-Value * @param p1 * @param map * @return */ @RequestMapping (value= "get3" ,method=RequestMethod.GET) public ModelAndView get3( @RequestParam (value= "p1" ,required= false )String p1,ModelMap map){ map.addAttribute( "p1" , p1); //往页面传递 return new ModelAndView( "request/get2" ,map); } |
ModelAndView表示绑定了数据的视图,可以通过EL表达式去取值。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
/** * 跳转到页面 * @throws NoSuchAlgorithmException */ @RequestMapping ( "userForm" ) public String userForm(HttpServletResponse response) throws NoSuchAlgorithmException{ CookieUtils.writeCookie(response, - 1 , "x" , "dddddddddddddd" ); return "request/userForm" ; } /** * 读取Cookie的值 * @param x * @return */ @ResponseBody @RequestMapping ( "cookie" ) public String cookie( @CookieValue ( "x" )String x){ return x; } |
先访问http://localhost:8080/springmvc-param/request/userForm这个方法,跳转到一个页面,并向浏览器写入Cookie,第二个方法访问的时候即可通过@CookieValue方式来取到Cookie中的值。
绑定数据到一个对象上,支持get和post
一个User,一个Phone,一个User拥有多个Phone,为了演示,User中有一个List和Array的Phone的集合
1
2
3
4
5
6
7
8
|
public class User { private String userName; private String address; private List<Phone> phones; private Phone[] phones2; //省略GET和SET... } |
1
2
3
|
public class Phone { private String brand; //手机品牌 } |
Controller方法如下
1
2
3
4
5
6
7
8
9
10
|
/** * 绑定数据到User对象,支持Map,Set,List,Array等,但是需要使用下标,不是很灵活 * 请查看user2的写法 * @param user * @param map */ @RequestMapping (value= "user" ) public void user(User user,ModelMap map){ map.addAttribute( "user" , user); } |
HTML表单如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
< form action = "request/user" method = "get" style = "border:1px solid red;" > < table > < tr >< td colspan = "2" >这个表单演示了对象数据绑定的方法,以及对象中的Set,List,Array数据绑定(三者类似)</ td ></ tr > < tr > < td >用户名:</ td > < td >< input type = "text" name = "userName" value = "张三" ></ td > </ tr > < tr > < td >用户地址:</ td > < td >< input type = "text" name = "address" value = "江苏省无锡市新区菱湖大道200号" >< br ></ td > </ tr > < tr > < td >手机品牌:</ td > < td > < input type = "text" name = "phones[0].brand" value = "SONY" >< br > < input type = "text" name = "phones[1].brand" value = "MOTO" >< br > < input type = "text" name = "phones[2].brand" value = "LG" >< br > </ td > </ tr > < tr > < td >手机品牌2:</ td > < td > < input type = "text" name = "phones2[0].brand" value = "Apple" >< br > < input type = "text" name = "phones2[1].brand" value = "Samsung" >< br > < input type = "text" name = "phones2[2].brand" value = "HTC" >< br > </ td > </ tr > < tr > < td colspan = "2" style = "text-align: right;" > < input type = "submit" value = "提交" > </ td > </ tr > </ table > </ form > |
一对多的时候,使用多一方的在一一方的对象中的属性名,加上数组下标,即phones[0].brand,phones[1].brand即可绑定到User的phones属性上,这种方法的局限性就是要求下标是正确的,否则会无法绑定,不是很方便,但是也有其适用场景。
下面这种方法就是比较方便了,仅支持post,但是必须要在消息转换器中配置JSON解析器
1
|
<bean class = "org.springframework.http.converter.json.MappingJacksonHttpMessageConverter" ></bean> |
并注册到RequestMappingHandlerAdapter的messageConverters中。
Controller如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
/** * 这里可以接受List,Array,Set等,写法是一样的,注意前端写法<br> * 另外这个必须要使用MappingJacksonHttpMessageConverter这个消息转换器 * 请看我上面的配置 * @param user * @return */ @ResponseBody @RequestMapping ( "user2" ) public String user2( @RequestBody List<User> user){ System.out.println(user.size()); return "" ; } |
Javascript如下
1
2
3
4
5
6
7
8
9
10
11
12
13
|
var userList= new Array(); userList.push({userName: "xx" ,address: "fff" }); userList.push({userName: "zzzz" ,address: "ggggg" }); $.ajax({ url: "request/user2" , type: "post" , data:JSON.stringify(userList), dataType: "json" , contentType: "application/json" , success: function (data){ },error: function (data){ } }); |
该方法仅支持POST的方式,会使用到json2.js这个类库,注意设置contentType:"application/json"这个属性,否则会报415未知的类型异常。
传递简单的字符串数组,仅支持POST方式
1
2
3
4
5
6
7
8
9
10
11
12
|
/** * 传递简单的字符串数组 * 这个方法只支持POST * @param s * @return */ @ResponseBody @RequestMapping ( "array" ) public String array( @RequestBody String[] s){ System.out.println(s.length); return "" ; } |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
var array= new Array(); array.push(1); array.push(2); array.push(3); array.push(4); array.push(5); $.ajax({ url: "request/array" , type: "post" , dataType: "json" , data:JSON.stringify(array), dataType: "json" , contentType: "application/json" , success: function (data){ },error: function (data){ } }); |
和上面的方法类似,注意contentType:"application/json",否则同样的415错误。
下面的方法是restful中的路径变量,支持get,post,delete等,如:xxx/1,xxx/2这种方式,经测试,这个方法的奇葩之处在于"xxx/5,4"以及"xxx/[5,4]"的效果是一样的,看代码:
1
2
3
4
5
6
7
8
9
10
11
|
/** * 这个比较奇葩,来自一位朋友的写法,即.xxx/5,4这样的请求,SpringMVC竟然也是支持的 * @param id * @return */ @ResponseBody @RequestMapping (value= "array/{id}" ,method=RequestMethod.GET) public String array2( @PathVariable ( "id" )Long[] id){ System.out.println(id.length); return "array length:" +id.length+ "" ; } |
可以直接将后面的路径变量,转换成相应的数组。可以在浏览器输入:http://localhost:8080/springmvc-param/request/array/5,4,3,2,1或者http://localhost:8080/springmvc-param/request/array/[5,4,3,2,1],都可以转换成数组。
如果一个表单对应多个实体类,恰好这些类中具有相同的属性,这时候SpringMVC就犯难了,我们要做的是让SpringMVC明白我们在给谁赋值。
支持post,get,put
如下,A,B,C,其中C中包含了A和B两个成员变量
1
2
3
|
public class A { private String x; } |
1
2
3
|
public class B { private String x; } |
1
2
3
4
|
public class C { private A a; private B b; } |
Controller如下
1
2
3
4
5
6
7
8
9
10
11
|
/** * 一个表单对应多个Bean对象,这些Bean中有相同的属性,那么需要在分装他们的一个整体的对象 * 使之支持object.property的表达式 * @param c */ @ResponseBody @RequestMapping ( "complex" ) public void complexObject(C c){ System.out.println(c.getA().getX()); System.out.println(c.getB().getX()); } |
HTML如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
< form action = "request/complex" method = "POST" style = "border:1px solid red;" > < table > < tr > < td >A对象:</ td > < td >< input type = "text" name = "a.x" value = "xxx" ></ td > </ tr > < tr > < td >B对象:</ td > < td >< input type = "text" name = "b.x" value = "yyy" >< br ></ td > </ tr > < tr > < td colspan = "2" style = "text-align: right;" > < input type = "submit" value = "提交" > </ td > </ tr > </ table > </ form > |
通过object.property即可指定给谁赋值。
另外一个是关于Session取值的
代码如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
@Controller @SessionAttributes (value= "user" ) @RequestMapping ( "/session" ) public class SessionController { @RequestMapping (method=RequestMethod.GET) public String setUser(ModelMap map){ User user= new User(); user.setAddress( "xxx" ); user.setUserName( "yyy" ); map.put( "user" , user); return "request/userForm" ; } @ResponseBody @RequestMapping (value= "getUser" ,method=RequestMethod.GET) public String getUser( @ModelAttribute ( "user" )User user){ System.out.println(user.getUserName()); return user.getUserName(); } } |
在Controller上加上注解@SessionAttributes(value="user"),再使用ModelMap的put方法(非addAttribute方法),然后在getUser方法中,使用@ModelAttribute("user")即可取得session中的user对象
Maven依赖:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
< properties > < springframework >4.0.5.RELEASE</ springframework > < servlet >3.1.0</ servlet > < jstl >1.2</ jstl > < xstream >1.4.7</ xstream > < commons-fileupload >1.3.1</ commons-fileupload > < jackson >1.9.13</ jackson > </ properties > < dependencies > <!-- jackson json解析支持 --> < dependency > < groupId >org.codehaus.jackson</ groupId > < artifactId >jackson-mapper-asl</ artifactId > < version >${jackson}</ version > </ dependency > <!-- Spring web mvc --> < dependency > < groupId >org.springframework</ groupId > < artifactId >spring-webmvc</ artifactId > < version >${springframework}</ version > </ dependency > <!-- servlet --> < dependency > < groupId >javax.servlet</ groupId > < artifactId >javax.servlet-api</ artifactId > < version >${servlet}</ version > </ dependency > <!-- JSTL --> < dependency > < groupId >jstl</ groupId > < artifactId >jstl</ artifactId > < version >${jstl}</ version > </ dependency > <!--xml解析支持 --> < dependency > < groupId >com.thoughtworks.xstream</ groupId > < artifactId >xstream</ artifactId > < version >${xstream}</ version > </ dependency > </ dependencies > |
Spring配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
@EnableWebMvc // 启用SpringMVC @ComponentScan (basePackages = "org.xdemo.example.springmvc" ) // 配置包扫描路径 @Configuration // 启用注解式配置 //继承WebMvcConfigurerAdapter可以是我们可以重写一些资源或者一些处理器 public class AppConfig extends WebMvcConfigurerAdapter { /** * 设置资源路径 */ @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler( "/resources/**" ).addResourceLocations( "/resources/" ).setCachePeriod( 31556926 ); } /** * 设置默认的Servlet请求处理器 */ @Override public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { configurer.enable(); } /** * 设置视图解析器,以及页面路径 * * @return */ @Bean public InternalResourceViewResolver getInternalResourceViewResolver() { InternalResourceViewResolver resolver = new InternalResourceViewResolver(); resolver.setPrefix( "/WEB-INF/views/" ); resolver.setSuffix( ".jsp" ); return resolver; } /** * 配置消息转换器 */ @Override public void configureMessageConverters( List<HttpMessageConverter<?>> converters) {converters.add(converter()); } /** * JSON格式的支持,这个很重要,只有加上这个JSON的消息转换器,才能够支持JSON格式数据的绑定 * @return */ @Bean public MappingJacksonHttpMessageConverter converter() { MappingJacksonHttpMessageConverter converter = new MappingJacksonHttpMessageConverter(); return converter; } } |
转载请注明来源:http://www.xdemo.org/springmvc-data-bind/
SpringMVC数据绑定全面示例(复杂对象,数组等)的更多相关文章
- SpringMVC接收对象数组参数进行封装
前台代码:注意.contentType : "application/json; charset=utf-8",必须要设置,只有这样SpringMVC才认识这个json数组参数 f ...
- 不可或缺 Windows Native (18) - C++: this 指针, 对象数组, 对象和指针, const 对象, const 指针和指向 const 对象的指针, const 对象的引用
[源码下载] 不可或缺 Windows Native (18) - C++: this 指针, 对象数组, 对象和指针, const 对象, const 指针和指向 const 对象的指针, con ...
- SpringMVC+RestFul详细示例实战教程
一.SpringMVC基础入门,创建一个HelloWorld程序 1.首先,导入SpringMVC需要的jar包. 2.添加Web.xml配置文件中关于SpringMVC的配置 <!--conf ...
- springmvc 项目完整示例04 整合mybatis mybatis所需要的jar包 mybatis配置文件 sql语句 mybatis应用
百度百科: MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBat ...
- springmvc 项目完整示例08 前台页面以及知识点总结
至此已经基本测试成功了,我们稍作完善,让它成为一个更加完整的项目 我们现在重新规划下逻辑 两个页面 一个登录页面 一个欢迎页面 登陆页面输入账号密码,登陆成功的话,跳转登陆成功 欢迎页面 并且,更新用 ...
- iOS--自定义相册---对象数组按照时间戳排序
将对象按照时间戳排序,这里典型的一个例子是登录账户的排序:本地客户端可能保存了多个账户信息,在登录窗口用户可以选择已经登陆过的账户直接登录,现在的需求是要时刻让最近登陆过的账户排在前面,对于每个账户, ...
- 对象数组自定义排序--System.Collections.ArrayList.Sort()
使用System.Collections.ArrayList.Sort()对象数组自定义排序 其核心为比较器的实现,比较器为一个类,继承了IComparer接口并实现int IComparer.Com ...
- 给内部类对象数组属性赋值时报错:Exception in thread "main" java.lang.NullPointerException
前言 1255: 打怪升级(Java),写这个题目程序的时候,控制台提示如下错误: Exception in thread "main" java.lang.NullPointer ...
- vue : watch、computed、以及对象数组
watch和computed是vue框架中很重要的特性. 那么,他们是怎么作用于对象数组的? 今天我们就来探究一下. 上代码. <template> <div class=" ...
随机推荐
- c 语言时间的输出和比较
time_t The most basic representation of a date and time is the type time_t. The value of a time_t va ...
- 2016.10.30 济南学习 Day2 下午 T1
他 [问题描述] 一张长度为N的纸带,我们可以从左至右编号为0 − N(纸带最左端标号为 0).现在有M次操作,每次将纸带沿着某个位置进行折叠,问所有操作之后纸带 的长度是多少. [输入格式] 第一行 ...
- Headfirst设计模式的C++实现——策略模式(Strategy)
前言 最近在学习<Headfirst设计模式>,里面的例子都是Java的.但是我对Java并不熟悉,所以试着用C++来实现书中的例子. 先来看看Duck以及子类 Duck.h #inclu ...
- 淘宝店铺应用android源码
一个淘宝店铺的app 界面模仿蘑菇街 完结版很多朋友想知道web端 我发上来 是用thinkphp框架 懂的同学拿去研究 ,之前做的前台 现在基本上不能用 就看个后台就好了 也比较简单 我放上来 大家 ...
- PHPcms 摘要
一 常量 /** * 主要定义了路径常量,项目中经常用到 **/ define('PHPCMS_PATH',dirname(__FILE__).DIRECTORY_SEPARATOR);// 项目 ...
- PowerPoint Office Mix 插件
一个内嵌在PowerPoint里的一个教学工具,可以以PPT为核心录制视频. 点下面链接了解并安装 https://mix.office.com/ 首先这货是免费,当然是基于PowerPoint的基础 ...
- Zend-MVC intro
Zend-MVC intro Zend MVC层建立在servicemanager.eventmanager.http.stdlib.几个组件之上.相关组件介绍会在其他文章中详细说明. 除了以上4大组 ...
- SQLite数据库的加密【转】
1.创建空的SQLite数据库. //数据库名的后缀你可以直接指定,甚至没有后缀都可以 //方法一:创建一个空sqlite数据库,用IO的方式 FileStream fs = File.Create( ...
- 管理口令(P):[INS-30001] ADMIN口令为空之Oracle安装
在安装oracle database11g 发行版的时候出现下面这个问题. 无论怎么输入密码都提示有问题,都输入得鬼火了!去百度了一下,果然有命名规则的 规则如下:小写字母+数字+大写字母
- 人工智能起步-反向回馈神经网路算法(BP算法)
人工智能分为强人工,弱人工. 弱人工智能就包括我们常用的语音识别,图像识别等,或者为了某一个固定目标实现的人工算法,如:下围棋,游戏的AI,聊天机器人,阿尔法狗等. 强人工智能目前只是一个幻想,就是自 ...