SpringMVC 数据绑定全面示例(复杂对象,数组等)
Spring restful的文章 http://www.xdemo.org/spring-restful/
项目下载:http://pan.baidu.com/share/link?shareid=955245807&uk=1896630845
首先贴出Controller的全部内容
/**
* @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,参数可选
/**
* 最简的配置,不是用@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,参数必须
/**
* 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,参数可选
/**
* 和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,参数可选
/**
* 和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表达式去取值。
/**
* 跳转到页面
* @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的集合
public class User {
private String userName;
private String address;
private List<Phone> phones;
private Phone[] phones2;
//省略GET和SET...
}
public class Phone {
private String brand;//手机品牌
}
Controller方法如下
/**
* 绑定数据到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表单如下
<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解析器
<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"></bean>
并注册到RequestMappingHandlerAdapter的messageConverters中。
Controller如下:
/**
* 这里可以接受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如下
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方式
/**
* 传递简单的字符串数组
* 这个方法只支持POST
* @param s
* @return
*/
@ResponseBody
@RequestMapping("array")
public String array(@RequestBody String[] s){
System.out.println(s.length);
return "";
}
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]"的效果是一样的,看代码:
/**
* 这个比较奇葩,来自一位朋友的写法,即.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两个成员变量
public class A {
private String x;
}
public class B {
private String x;
}
public class C {
private A a;
private B b;
}
Controller如下
/**
* 一个表单对应多个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如下:
<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取值的
代码如下
@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依赖:
<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配置
@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/