用起来Spring MVC,比之前写Servlet一个很大的便捷性就是Spring MVC可以自动绑定请求的参数到入参.再也不需要从HttpServletRequest中getParamater了,省下了不少重复代码.
一般的参数绑定,比如int,Long等基本类型,以及基本类型的包装类,String等,都可以在入参使用注解@RequestParam
(Spring独有),或者QueryParam
(Java标准的),绑定请求参数到入参.
这一篇文章,我们说一下复杂的参数绑定,简单对象,Map,Set,List,数组,以及包含Map,set,List,数组的复杂对象
简单对象
简单对象,就是一般的Pojo,而且里面还没有诸如Map,Set,List,数组的属性,这还是很简单的.通过使用注解@ModelAttribute
,或者什么注解也不写(对于Controller上的对象,不写注解,默认使用@ModelAttribute
),只在入参传入一个对象,Spring MVC自动会帮我们把请求的各个参数组装成一个Pojo对象,绑定到入参上
例如: 对于一个url test?id=1&fromSite=www.test.com
,,如下的写法,既可以绑定到入参上
// controller 内的路由映射
@GetMapping("/test")
public String getPojo( /*@ModelAttribute 有没有都可以*/ Pojo pojo){
//do something about pojo
return "test";
}
// 一个Pojo,后续的例子中也是用它
class Pojo{
private int id;
private String fromSite;
public int getId(){return id;}
public void setId(int id){this.id=id;}
public String getFromSite(){return fromSite;}
public void setFromSite(String fromSite){this.fromSite=formSite;}
}
数组
Spring MVC数组的参数绑定,只支持对一般类型(基本类型以及对应包装类,String)的直接绑定,其他类型数组的绑定,需要将数组当成属性,包装成一个类.
对于一般的类型,前端请求来的时候,请求参数的name是一样的,对应的value有多个,比如url为test?id=1,2,3,4
,这是Controller内入参写作int[] ids
,就可以绑定到入参上.
其他数据类型(自定义对象)数组
其他数据类型数组,以及Map,Set,List的绑定,都需要将它们封装在一个包装类内,当成属性才可以.
首先,讨论其他数据类型(例如,自定义对象)的数组.
* 首先,定义一个包装数组的包装类,自定义类我们借用上面提到的Pojo(有属性int id和String fromSite)
class PojoArray{
private Pojo[] pojos;
public Pojo[] getPojos(){return pojos;}
public void setPojos(Pojo[] pojos){this.pojos=pojos;}
}
- 则,对应Controller的形式为:
@GetMapping("/test")
public String getMOdels(PojoArray pojoArray){
// here we get a PojoArray with Pojo[]
return "test";
}
- 对应前端HTML的写法,是这样:
<form method="POST" action="test">
<input type="text" name="pojos[0].id"/>
<input type="text" name="pojos[0].fromSite"/>
<input type="text" name="pojos[1].id"/>
<input type="text" name="pojos[1].fromSite"/>
<!-- 以此类推,填入数组每一个元素的属性,注意数组的下标 -->
<!-- ...... -->
<input type="submit"/>
</form>
- 对应的url为
/test?pojos[0].id=xx&pojos[0].fromSite=xx&pojos[1].id=xx&pojos[1].fromSite=xx
(xx为任意值)
需要注意的是
数组的大小是根据url上传入的下标最大值来确定的,元素的填充也是根据下标来填充的,所以,如果下标出现跳跃(例如,有pojos[0],pojos[2],却没有pojos[1])的情况,最后传入Controller的数组,对应缺失下标的元素为null,数组长度为最大下标+1.
Map,Set,List的集合类
Spring MVC 不支持集合类的直接绑定,与数组绑定类似,都需要当作一个包装类的属性来实现入参绑定.
对于Map
- 首先定义一个对Map的包装类
class PojoMap{
private Map<String,Pojo> pojoMap;
public Map<String,Pojo> getPojoMap(){return pojoMap;}
public void setPojoMap(Map<String,Pojo>){this.pojoMap=pojoMap;}
}
- 对应Controller为
@GetMapping("/test")
public String test(PojoMap pojoMap){
//here we get a PojoMap with Map<String,Pojo>
return "test";
}
- 对应前端HTML
<form method="POST" action="test">
<input type="text" name="pojoMap['pojo1'].id"/>
<input type="text" name="pojoMap['pojo1'].fromSite"/>
<input type="text" name="pojoMap['pojo2'].id"/>
<input type="text" name="pojoMap['pojo2'].fromSite"/>
<!-- 以此类推,填入数组每一个元素的属性,注意数组的下标 -->
<!-- ...... -->
<input type="submit"/>
</form>
- 对应url形式为:
/test?pojoMap['pojo1'].id=xx&pojoMap['pojo1'].fromSite=xx&pojoMap['pojo2'].id=xx&pojoMap['pojo2'].fromSite=xx
.(xx为任意值)
对于Set和List
二者写法一样,不同之处在Set的特性,,这不在编码方法讨论范围,所以我们放到一个里面
- 首先是List和Set的包装类
class PojoWrapper{
List<Pojo> pojoList;
Set<Pojo> pojoSet;
public PojoWrapper(){
// 注意:这里需要手动new出来Set,并且手动向Set里增添Pojo
// 之后,url的参数才能绑定到Set上
// 如果不手动实例化Set,或者Set内手动添加的Pojo个数少于url传入的pojo数,则会抛出异常
pojoSet=new HashSet<>();
Pojo pojo=new Pojo();
pojoSet.add(pojo);
}
public List<Pojo> getPojoList(){return pojoList;}
public void setPojoList(List<Pojo> pojoList){this.pojoList=pojoList;}
public Set<Pojo> getPojoSet(){return pojoSet;}
public void setPojoSet(Set<Pojo> pojoSet){this.pojoSet=pojoSet;}
}
- 对应Controller
@GetMapping("/test")
public String test(PojoWrapper pojowrapper){
//here we get a PojoWrapper with a List<Pojo> and Set<Pojo>
return "test";
}
- 对应html页面
<form method="POST" action="test">
<input type="text" name="pojoList[0].id"/>
<input type="text" name="pojoList[0].fromSite"/>
<input type="text" name="pojoList[1].id"/>
<input type="text" name="pojoList[1].fromSite"/>
<input type="text" name="pojoSet[0].id"/>
<input type="text" name="pojoSet[0].fromSite"/>
<!-- 以此类推,填入数组每一个元素的属性,注意数组的下标 -->
<!-- ...... -->
<input type="submit"/>
</form>
- 对应的url形式为
/test?pojoList[0].id=xx&pojoList[0].fromSite=xx&pojoList[1].id=xx&pojoList[1].fromSite=xx&pojoSet[0].id=xx&pojoSet[0].fromSite=xx
(xx为任意值)
需要注意的:
注意容量问题:
List与数组类似,如果有下标跳跃的问题,跳过的下标位置的元素为null,同时List的size为最大下标+1.
而Set的容量,更加复杂,Set需要手动new出来,手动把对象添加入Set,不能通过url传递的下标初始化大小;
同时Set还不支持基本类型包装类,String类型的数据绑定().