spring mvc参数绑定

时间:2024-07-14 08:33:14

spring绑定参数的过程

从客户端请求key/value数据,经过参数绑定,将key/value数据绑定到controller方法的形参上。springmvc中,接收页面提交的数据是通过方法形参来接收,而不是在controller类定义成员变更接收!

spring mvc参数绑定

默认支持的类型

直接在controller方法形参上定义下边类型的对象,就可以使用这些对象,在参数绑定过程中,如果遇到下边类型直接进行绑定。

  1. HttpServletRequest,通过request对象获取请求信息
  2. HttpServletResponse,通过response处理响应信息
  3. HttpSession,通过session对象得到session中存放的对象
  4. Model/ModelMap,model是一个接口,modelMap是一个接口实现 。作用是将model数据填充到request域。

简单类型

当参数类型是java的基本数据类型时,提交到controller的name和接收方法的形参名称一致就接收到数据。如:

@RequestMapping(value="/addItems", method={RequestMethod.POST, RequestMethod.GET})
public String addItems(HttpServletRequest request, Model model, String itemsName) throws Exception {
    System.out.println("商品名称:" + itemsName);
    return "forward:queryItems";
}

这时候在浏览器输入http://localhost:8080/ssm/items/addItmes?itemsName='Java编程思想',或者请求页面中的链接为:

<a href="items/addItems?itemsName='Thinking In Java'">参数传递</a><br />

后台就会接收到商品名为《Java编程思想》的商品名。其中那个RequesMapping的属性value是对应的url,method是规定该方法接收的请求类型,这里既运行使用post请求,同事也允许get请求。

如果request传入的参数和形参的名称不一致,需要使用@RequestParam进行绑定才能映射成功

    @RequestMapping(value="/addItems", method={RequestMethod.POST, RequestMethod.GET})
    public String addItems(HttpServletRequest request, Model model, @RequestParam(value="bookName", required=false) String itemsName) throws Exception {
        System.out.println("商品名称:" + itemsName);

        return null;
    }
<a href="items/addItems?bookName='Thinking In Java'">参数传递</a><br />

可以看到请求的参数名称叫做:bookName,而方法的形参名称叫做:itemsName,但是加上这一句@RequestParam(value="bookName", required=false)之后,请求参数可以参观的映射到形参。

如果不使用@RequestParam,要求request传入参数名称和controller方法的形参名称一致,方可绑定成功;如果使用@RequestParam,不用限制request传入参数名称和controller方法的形参名称一致。通过required属性指定参数是否必须要传入,如果设置为true,没有传入参数,报下边错误:

spring mvc参数绑定

pojo绑定

当页面中input的name和controller的pojo形参中的属性名称一致,将页面中数据绑定到pojo。

我的pojo定义如下:

public class Items {

    private Integer id;

    private String name;

    private Float price;

    private String pic;

    private Date createtime;

    private String detail;

    //getter/setter
}

jsp:页面定义:

    <form action="items/addItems" method="post">
        <table width="50%" border="1px">
            <tbody>
                <tr>
                    <td>商品名称</td>
                    <td><input type="text" name="name"/></td>
                </tr>
                <tr>
                    <td>商品价格</td>
                    <td><input type="text" name="price" /></td>
                </tr>
                <tr>
                    <td colspan="2"><input type="submit" value="添加" /></td>
                </tr>
            </tbody>
        </table>
    </form>

先测一测简单的数据类型,商品名和商品价格,因为这两种类型都是简单的数据类型,Date类型接下来再解决。

controller的接收方法

    @RequestMapping("/addItems")
    public String addItems(HttpServletRequest request, Model model, Items items) throws Exception {
        System.out.println("商品名:" + items.getName());
        System.out.println("商品价格:" + items.getPrice());

        return null;
    }

这里可以看到,添加商品的jsp页面中,商品的input的name="name",这个值将映射成为items对象的name属性,input的name="price"商品价格的值会映射到items对象的price这个属性里边。

再来测试另外几种数据类型,再定义一个java bean:Student。

public class Student {
    /*
     * id
     */
    private int id;

    /**
     * 姓名
     */
    private String name;

    /**
     * 是否成年
     */
    private boolean adaut;

    /**
     * 生日
     */
    private Date birthday;

    /**
     * 身高
     */
    private float hight;

    //getter/setter
}

提交表单的jsp页面如下:

<form action="items/addStudent" method="post">
    <table width="50%" border="1px">
        <tbody>
            <tr>
                <td>id</td>
                <td><input type="text" name="id"/></td>
            </tr>
            <tr>
                <td>姓名</td>
                <td><input type="text" name="name" /></td>
            </tr>
            <tr>
                <td>是否成年</td>
                <td>
                    <input type="radio" name="adaut" value="true" checked>是
                    <input type="radio" name="adaut" value="false">否
                </td>
            </tr>
            <tr>
                <td>生日</td>
                <td><input type="text" name="birthday" /></td>
            </tr>
            <tr>
                <td>身高</td>
                <td><input type="text" name="hight" /></td>
            </tr>
            <tr>
                <td colspan="2"><input type="submit" value="添加" /></td>
            </tr>
        </tbody>
    </table>
</form>

在这个JavaBean的属性中有日期类型,需要自定义参数绑定。将请求日期数据串传成 日期类型,要转换的日期类型和pojo中日期属性的类型保持一致,需要向处理器适配器中注入自定义的参数绑定组件。

自定义日期类型绑定

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.springframework.core.convert.converter.Converter;

public class CustomDateConverter implements Converter<String, Date> {

    public Date convert(String source) {
        //实现将日期串转成日期类型(格式是yyyy-MM-dd HH:mm:ss)
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            return sdf.parse(source);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }

}

在配置文件中配置:

    <mvc:annotation-driven conversion-service="conversionService" />
    <!-- 自定义参数绑定 -->
    <bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
        <!-- 转换器 -->
        <property name="converters">
            <list>
                <!-- 日期转换类型 -->
                <bean class="com.shizongger.ssm.model.CustomDateConverter" />
            </list>
        </property>
    </bean>

如此这般,jsp页面的input输入框中,日期格式如:2016-12-12 21:59:00的字符串变会转换成Date的日期格式。是否成年的boolean值也会传递到adaut属性中。

包装类型pojo参数绑定

需求:

商品查询controller方法中实现商品查询条件传入。

实现方法:

  1. 在形参中 添加HttpServletRequest request参数,通过request接收查询条件参数。
  2. 在形参中让包装类型的pojo接收查询条件参数。

分析:

页面传参数的特点:复杂,多样性。条件包括 :用户账号、商品编号、订单信息。如果将用户账号、商品编号、订单信息等放在简单pojo(属性是简单类型)中,pojo类属性比较多,比较乱。建议使用包装类型的pojo,pojo中属性是pojo。

定义一个查询的java bean QueryVo,所有将要查询的条件都将由这个vo接收。

public class QueryVo {

    private Items items;
    private Student student;    

    public Items getItems() {
        return items;
    }
    public void setItems(Items items) {
        this.items = items;
    }
    public Student getStudent() {
        return student;
    }
    public void setStudent(Student student) {
        this.student = student;
    }
}

Items和Student定义如上所述,这个vo定义了两个属性items商品和student用户(里面student就是用户),两者都有一个共同的属性名:name,items商品中有一个属性名name代表商品名称,student有一个属性名name代表用户名称,这个案例将展示如果分别向这个不同的name属性传递值。

jsp页面代码:

<form action="queryItems" method="post">
<table border="1px" width="80%">
    <tr>
        <td>商品名:<input type="text" name="items.name" /></td>
        <td>商品价格:<input type="text" name="items.price" /></td>
        <td>商品详情:<input type="text" name="items.detail" /></td>
        <td>下单用户:<input type="text" name="student.name" /></td>
        <td><input type="submit" value="查询" /></td>
    </tr>
</table>
</form>

controller代码:

    //商品查询
    @RequestMapping("/queryItems")
    public ModelAndView queryItems(HttpServletRequest request, QueryVo queryVo) throws Exception{
        if(null != queryVo && null != queryVo.getItems() && null != queryVo.getStudent()) {
            System.out.println("前端传递过来的查询条件:");
            System.out.println("商品名称:" + queryVo.getItems().getName() + " 商品价格:"
                            + queryVo.getItems().getPrice() + " 商品详情:"
                            + queryVo.getItems().getDetail() + " 下单用户:"
                            + queryVo.getStudent().getName() );
        }
    }

在input的name属性中,name值与queryVo属性的属性名对应,才能映射成功。

集合类型的绑定

数组类型绑定

需求:

商品批量删除,用户在页面选择多个商品,批量删除。

分析:

在批量删除需求中,如果能够一次性拿到jsp页面中复选框选中的内容那好办了。所以我们可以将页面选择(多选)的商品id,传到controller方法的形参,方法形参使用数组接收页面请求的多个商品id。

controller方法定义:

    @RequestMapping("/deleteItems")
    public String deleteItems(HttpServletRequest request, Integer[] itemsIds) {
        for(int i = 0; i < itemsIds.length; i++) {
            System.out.println("要删除的id:" + itemsIds[i]);
        }
        return null;
    }

jsp页面定义:

        <form id="itemsTalbe">
        <table border="1px" width="80%">
            <thead>
                <tr><td>删除</td><th>序列</th><th>商品名称</th><th>商品详情</th><th>商品价格</th><th>订单创建时间</th><th>修改</th></tr>
            </thead>
            <tbody>
                <c:forEach items="${itemsList }" var="items" varStatus="status">
                    <tr>
                        <td><input type="checkbox" name="itemsIds" value="${items.id }" /></td>
                        <td>${status.count }</td>
                        <td>${items.name }</td>
                        <td>${items.detail }</td>
                        <td>${items.price }</td>
                        <td>${items.createtime }</td>
                        <td><a href="editItems?id=${items.id }">修改</a></td>
                    </tr>
                </c:forEach>
                <tr>
                    <td colspan="7"><input type="submit" value="批量删除" onclick="batchDelete()"/></td>
                </tr>
            </tbody>
        </table>
        </form>

js代码:

        function batchDelete() {
            var form = document.getElementById("itemsTalbe");
            form.action ="${pageContext.servletContext.contextPath }/items/deleteItems";
            form.submit();
        }

在jsp页面中,用jstl迭代输出表格中每一行的记录内容。最重要的是每一行的第一个td的内容:

<td><input type="checkbox" name="itemsIds" value="${items.id }" /></td>

name属性等于itemsIds正是controller接收参数Interger数组的名称。

list绑定

通常在需要批量提交数据时,将提交的数据绑定到list< pojo>中,比如:成绩录入(录入多门课成绩,批量提交),本例子需求:

批量商品修改,在页面输入多个商品信息,将多个商品信息提交到controller方法中。

在上诉的请求vo中,再添加属性:

private List<Items> itemsList;

完整的vo如下:

public class QueryVo {

    private Items items;
    private Student student;
    private List<Items> itemsList;

    public List<Items> getItemsList() {
        return itemsList;
    }
    public void setItemsList(List<Items> itemsList) {
        this.itemsList = itemsList;
    }
    public Items getItems() {
        return items;
    }
    public void setItems(Items items) {
        this.items = items;
    }
    public Student getStudent() {
        return student;
    }
    public void setStudent(Student student) {
        this.student = student;
    }

}

jsp页面:

spring mvc参数绑定

springmvc和struts2的区别

  1. springmvc基于方法开发的,struts2基于类开发的。springmvc将url和controller方法映射。映射成功后springmvc生成一个Handler对象,对象中只包括了一个method。方法执行结束,形参数据销毁。springmvc的controller开发类似service开发。

  2. springmvc可以进行单例开发,并且建议使用单例开发,struts2通过类的成员变量接收参数,无法使用单例,只能使用多例。

  3. 经过实际测试,struts2速度慢,在于使用struts标签,如果使用struts建议使用jstl。

参考资料:<传智播客_Springmvc+Mybatis由浅入深之spring mvc>