Spring MVC 复杂数据绑定

用起来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类型的数据绑定().

参考博客

springMVC4(12)复杂对象和集合类型入参绑定

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值