SpringMVC学习(3):数据绑定

前言

什么是数据绑定?

在执行程序时,Spring MVC会根据客户端请求参数的不同,将请求消息中的信息以一定的方式转换并绑定到控制器类的方法参数中。这种将请求消息数据与后台方法参数建立连接的过程就是Spring MVC中的数据绑定。

数据绑定的过程

在数据绑定过程中,Spring MVC框架会通过数据绑定组件(DataBinder)将请求参数串的内容进行类型转换,然后将转换后的值赋给控制器类中方法的形参,这样后台方法就可以正确绑定并获取客户端请求携带的参数了。

数据绑定的过程:
1.Spring MVC将ServletRequest对象传递给DataBinder;
2.将处理方法的入参对象传递给DataBinder;
3.DataBinder调用ConversionService组件进行数据类型转换、数据格式化等工作,并将ServletRequest对象中的消息填充到参数对象中;
4.调用Validator组件对已经绑定了请求消息数据的参数对象进行数据合法性校验;
5.校验完成后会生成数据绑定结果BindingResult对象,Spring MVC会将BindingResult对象中的内容赋给处理方法的相应参数。

基本数据类型

基本数据类型包括:byte、short、int、long、float、double、boolean、char。下面以int数据类型为例,后台需要int类型的参数,直接在业务方法定义处添加int类型的形参即可,且http请求参数名必须与形参名一致。

    @RequestMapping(value="/baseType")
    @ResponseBody
    public String baseType(int id){
        return "id:"+id;
    }

(1)没有传入参数,报500的错误

错误原因:基本数据类型不能赋值null,参数“id”不能转为null

(2)参数类型为字符串,报400的错误

错误原因:参数类型错误,String类型不能转换为int类型

(3)http请求参数名必须与形参名一致,请求数据为int类型,成功调用方法

结论:用基本类型进行参数绑定时,就必须传入key值,且value值必须是声明的基本类型,否则将报错

包装类

包装类包括:Byte,Short,Integer,Long,Double,Float,Charater,Boolean。下面以Integer数据类型为例,后台需要Integer类型的参数,直接在业务方法定义处添加Integer类型的形参即可,且http请求参数名必须与形参名一致。

    @RequestMapping(value="/packageType")
    @ResponseBody
    public String packageType(Integer id){
        return "id:"+id;
    }

(1)没有传入参数,自动给参数赋值为null,成功调用方法

(2)参数类型为字符串,报400的错误

错误原因:String类型不能转换为Integer类型

(3)http请求参数名必须与形参名一致,请求数据为Integer 类型,成功调用方法

结论:包装类型绑定参数时,key的值可以不传,数据也可以为空,但是要想绑定成功绑定,传的key值要和里面绑定的参数名一致;如果想要必须传入某个参数进行绑定,可以用@RequestParam,用了这个只有所需绑定的参数必须传入,否则报错

参数列表添加@RequestParam注解,可以对参数进行相关设置。

    @RequestMapping(value="/packageType")
    @ResponseBody
    public String packageType(@RequestParam(value="id",required=false,defaultValue="1") Integer id){
        return "id:"+id;
    }

@RequestParam参数:

value="id":将http请求中名为id的参数与形参进行映射。
required=false:id参数非必填,可省略。
defaultValue="1":若http请求中没有id参数,默认值为1。

数组

    @RequestMapping(value="/arrayType")
    @ResponseBody
    public String arrayType(String[] name){
         StringBuffer sbf = new StringBuffer();
         for(String item:name) {
             sbf.append(item).append(" ");
         }
        return "name:"+sbf.toString();
    }

成功调用方法:

 

List

SpringMVC不支持List类型的直接转换,需要包装成Object。

1、定义List包装类

    public class UserList {
    private List<User> users;

    public List<User> getUsers() {
        return users;
    }

    public void setUsers(List<User> users) {
        this.users = users;
    }

}

2、编写业务方法

    @RequestMapping(value="/listType")
    @ResponseBody
    public String listType(UserList userList){
        StringBuffer sbf = new StringBuffer();
        for(User user:userList.getList()){
            sbf.append(user);
        }
        return "用户:"+sbf.toString();
    }

3、创建addList.jsp,同时添加三个用户信息,input的name指向自定义包装类UserList中的users属性,级联到name和age,同时以下标区分集合中不同的对象

    <form action="listType" method="post">
        用户1姓名:<input type="text" name="users[0].name"/><br/>
        用户1年龄:<input type="text" name="users[0].age"/><br/>
        用户2姓名:<input type="text" name="users[1].name"/><br/>
        用户2年龄:<input type="text" name="users[1].age"/><br/>
        用户3姓名:<input type="text" name="users[2].name"/><br/>
        用户3年龄:<input type="text" name="users[2].age"/><br/>
        <input type="submit" value="提交"/>
    </form>

4、运行

处理@ResponseBody中文乱码:

在springmvc.xml中配置消息转换器。

    <mvc:annotation-driven >
        <!-- 消息转换器 -->
        <mvc:message-converters register-defaults="true">
          <bean class="org.springframework.http.converter.StringHttpMessageConverter">
            <property name="supportedMediaTypes" value="text/html;charset=UTF-8"/>
          </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>

Map

1、定义Map包装类

    public class UserMap {
    private Map<String,User> users;

    public Map<String, User> getUsers() {
        return users;
    }

    public void setUsers(Map<String, User> users) {
        this.users = users;
    }

}

2、编写业务方法,遍历Map集合的key值,通过key值获取value

    @RequestMapping(value="/mapType")
    @ResponseBody
    public String mapType(UserMap userMap){
        StringBuffer sbf = new StringBuffer();
        for(String key:userMap.getUsers().keySet()){
            User user = userMap.getUsers().get(key);
            sbf.append(user);
        }
        return "用户:"+sbf.toString();
    }

3、创建addMap.jsp,与List不同的是,不能通过下标区分不同的对象,需要改为通过key值来区分

    <form action="mapType" method="post">
        用户1姓名:<input type="text" name="users['a'].name"/><br/>
        用户1年龄:<input type="text" name="users['a'].age"/><br/>
        用户2姓名:<input type="text" name="users['b'].name"/><br/>
        用户2年龄:<input type="text" name="users['b'].age"/><br/>
        用户3姓名:<input type="text" name="users['c'].name"/><br/>
        用户3年龄:<input type="text" name="users['c'].age"/><br/>
        <input type="submit" value="提交"/>
    </form>

4、运行

简单对象

1、创建User类

    public class User {
    private String name;
    private int age;
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    @Override
    public String toString() {
        return "User [name=" + name + ", age=" + age + "]";
    }

}

2、创建add.jsp,页面input标签的name值与实体类的属性名对应

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>填写用户信息</title>
</head>
<body>
    <form action="pojoType" method="post">
        姓名:<input type="text" name="name"/><br/>
        年龄:<input type="text" name="age"/><br/>
        <input type="submit" value="提交"/>
    </form>
</body>
</html>

3、编写业务方法

    @RequestMapping(value="/pojoType")
    @ResponseBody
    public String pojoType(User user){
        return "信息:"+user;
    }

4、运行

多层级对象

1、创建Address类

    public class Address {
    private int id;
    private String name;
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    @Override
    public String toString() {
        return "Address [id=" + id + ", name=" + name + "]";
    }

}

2、在User类添加address属性

    public class User {
    private String name;
    private int age;
    private Address address;

    public Address getAddress() {
        return address;
    }
    public void setAddress(Address address) {
        this.address = address;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    @Override
    public String toString() {
        return "User [name=" + name + ", age=" + age +",address=Address[id="+address.getId()+"],name=["+address.getName()+"]]";
    }

}

3、修改add.jsp,添加address信息,为input标签的name设置属性级联,即先关联User的address属性,再级联address的id和name

    <form action="pojoType" method="post">
        姓名:<input type="text" name="name"/><br/>
        年龄:<input type="text" name="age"/><br/>
        地址编号:<input type="text" name="address.id"/><br/>
        地址:<input type="text" name="address.name"/><br/>
        <input type="submit" value="提交"/>
    </form>

4、运行

JSON

1、创建ajax.jsp,Ajax请求后台业务方法,并将json格式的参数传给后台

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%><%
    String path = request.getContextPath();
    String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path;
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>填写用户信息</title>
<script src="<%=basePath %>/js/jquery-1.8.3.min.js"></script>
<script type="text/javascript">
    var user = {
            "name":"jex",
            "age":24
    };
    $.ajax({
        url:"jsonType",
        data:JSON.stringify(user),
        type:"post",
        contentType: "application/json;charse=UTF-8",
        dataType:"text",
        success:function(data){
            var obj = eval("(" + data + ")");
            alert(obj.name+"---"+obj.age);
        }
    })
</script>
</head>
<body>

</body>
</html>
</script>

注意:json数据必须用JSON.stringify()方法转换成字符串;contentType不能省略。

2、编写业务方法

    @RequestMapping(value="/jsonType")
    @ResponseBody
    public User jsonType(@RequestBody User user){
        //修改年龄
        user.setAge(user.getAge()+1);
        //返回前端
        return user;
    }

@RequestBody注解

读取http请求参数,通过SpringMVC提供的HttpMessageConverter接口将读取的参数转为json,xml格式的数据,绑定到业务方法的形参。

@ResponseBody注解

将业务方法返回的对象,通过HttpMessageConverter接口转为指定格式的数据,json,xml等,响应给客户端。

我们使用的是阿里的fastjson来取代Spring默认的Jackson进行数据绑定。

fastjson的优势在于如果属性为空就不会将其转化为json,数据会简洁很多。

如何使用fastjson

1.pom.xml引入fastjson依赖jar包。

    <dependency>
       <groupId>com.alibaba</groupId>
       <artifactId>fastjson</artifactId>
       <version>1.2.18</version>
   </dependency> 

2.springmvc.xml中配置fastjson。

   <mvc:annotation-driven >
        <!-- 消息转换器 -->
        <mvc:message-converters register-defaults="true">
          <bean class="org.springframework.http.converter.StringHttpMessageConverter">
            <property name="supportedMediaTypes" value="text/html;charset=UTF-8"/>
          </bean>
          <!-- 阿里fastjson -->
          <bean class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter4"/>
        </mvc:message-converters>
    </mvc:annotation-driven>

3、运行

源码

链接:
https://pan.baidu.com/s/1f0QBRFETFC8aUCxQh9HQBA 
提取码:rq38

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值