之前学习了SpringMVC数据绑定的基本知识和简单数据绑定以及POJO类型数据的绑定。接下来总结剩下的一些数据类型的绑定

1. 绑定包装POJO

所谓的包装POJO,就是在一个POJO中包含另一个简单POJO。
例如,在订单对象中包含用户对象。这样在使用时,就可以通过订单查询到用户信息。
在po包下新建一个OrdersPOJO:

public class Orders {
    private Integer ordersId; //订单id
    private User user;        //用户POJO
    //省略setter和getter方法
}

新建一个OrdersController,编写以下两个方法:

@Controller
public class OrdersController {
    /**
     * 跳转到查询页面
     * @return
     */
    @RequestMapping("/tofindOrdersWithUser")
    public String tofindOrdersWithUser() {
        return "orders";
    }

    /**
     * 查询订单和用户信息
     * @param orders
     * @return
     */
    @RequestMapping("/findOrdersWithUser")
    public String findOrdersWithUser(Orders orders) {
        Integer ordersId = orders.getOrdersId();
        User user = orders.getUser();
        String username = user.getUsername();
        System.out.println("ordersId=" + ordersId + "  username" + username);

        return "success";
    }
}

新建一个查询页面orders.jsp:

<form action="${pageContext.request.contextPath}/findOrdersWithUser" method="post">
        订单编号:<input type="text" name="ordersId"/><br/>
        所属用户:<input type="text" name="user.username"/><br/>
                 <input type="submit" value="查询"/>
    </form>

在使用包装POJO类型数据绑定时,前端请求的参数名编写必须符合以下两种情况。
1.如果查询条件参数是包装类的直接基本属性,则参数名直接用对应的属性名,如上面代码中的ordersId。

2.如果查询条件是包装类型中POJO的子属性,则参数名必须为[对象.属性],其中[对象]要和包装POJO中的对象属性名称一致,[属性]要和包装POJO中的对象子属性一致,如上述代码中的user.username。

测试运行结果

2.自定义数据绑定

一般情况下,使用基本数据类型和POJO类型的参数数据已经能够满足需求,然而有些特殊类型的参数是无法在后台进行直接转换的,但也有特殊数据类型无法直接进行数据绑定,必须先经过数据转换,例如日期数据。
针对前面提到的特殊数据类型,就需要开发者自定义转换器(Converter)或格式化(Formatter)来进行数据绑定。

2.1 Converter

Spring框架提供了一个Converter用于将一种类型的对象转换为另一种类型的对象。
自定义Converter类需要实现org.springframework.core.convert.converter.Converter接口。
接口代码如下:

public interface Converter<S, T> {
T convert(S source);
}

上述代码中,泛型中的S表示源类型,T表示目标类型,而convert(S source)表示接口中的方法。

在项目中创建一个convert的包,并创建一个日期转换类DateConverter,用于将String类型转换成Date类型,代码如下所示:

/**
 * @Package com.ma.converter
 * @Description: 自定义日期转换器
 * @auther MZ
 * @create 2017/11/5 10:21
 */
public class DateConverter implements Converter<String, Date> {

    //自定义日期格式
    private String datePattern = "yyyy-MM-dd HH:mm:ss";
    @Override
    public Date convert(String s) {
        //格式化日期
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(datePattern);

        try {
            return simpleDateFormat.parse(s);
        } catch (ParseException e) {
            throw new IllegalArgumentException("无效的日期格式,请使用这种格式:"+datePattern);
        }
    }
}

修改springmvc-config.xml文件,添加id为conversionService的Bean。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
       http://www.springframework.org/schema/mvc
       http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context-4.3.xsd">
        <!--定义组件扫描,指定需要扫描的包-->
        <context:component-scan base-package="com.ma.controller"/>
        <!--视图解析器-->
        <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <property name="prefix" value="/WEB-INF/jsp/"/>
            <property name="suffix" value=".jsp"/>
        </bean>

        <!-- 显示的装配自定义类型转换器 -->
        <mvc:annotation-driven conversion-service="conversionService"/>
        <!-- 自定义类型转换器配置 -->
        <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
            <property name="converters">
                <set>
                    <bean class="com.ma.converter.DateConverter"/>
                </set>
            </property>
        </bean>
</beans>

在controller包中新建一个日期控制器类DateConroller


/**
 * @Package com.ma.controller
 * @Description: 日期控制器类
 * @auther MZ
 * @create 2017/11/5 10:32
 */
@Controller
public class DateController {
    @RequestMapping("/customeDate")
    public String customeDate(Date date) {
        System.out.println("date="+date);
        return "success";
    }
}

测试结果:

2.2 Formatter

Formatter与Converter的作用相同,只是Formatter的源类型必须是一个String类型,而Converter可以是任意类型。
使用Formatter自定义转换器类需要实现org.springframework.format.Formatter接口。接口代码如下:

public interface Formatter<T> extends Printer<T>, Parser<T> {}

Formatter接口继承了Printer和Parser接口,其泛型T表示输入字符串要转换的目标类型。在Printer和Parser接口中,分别包含一个print()和parse()方法,所有的实现类必须覆盖这两个方法。
在converter包中新建一个日期转换类DateFormatter,代码如下:


/**
 * @Package com.ma.converter
 * @Description: 使用Formatter自定义日期转换器
 * @auther MZ
 * @create 2017/11/5 10:53
 */
public class DateFormatter implements Formatter<Date> {
    //定义日期格式
    private String datePattern = "yyyy-MM-dd HH:mm:ss";

    //声明SimpleDateFormat对象
    SimpleDateFormat simpleDateFormat;

    @Override
    public Date parse(String s, Locale locale) throws ParseException {
        simpleDateFormat = new SimpleDateFormat(datePattern);

        return simpleDateFormat.parse(s);
    }

    @Override
    public String print(Date date, Locale locale) {
        return new SimpleDateFormat().format(date);
    }
}

在配置文件中注册

<!-- 自定义类型格式化转换器配置 -->
    <bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
        <property name="formatters">
            <set>
                <bean class="com.itheima.convert.DateFormatter" />
            </set>
        </property>
    </bean>

测试结果和Converter的结果一样。

3. 复杂数据绑定

3.1 绑定数组

在实际开发时,可能会遇到前端请求需要传递到后台一个或多个相同名称参数的情况(如批量删除),此种情况采用前面讲解的简单数据绑定的方式显然是不合适的。
针对上述这种情况,如果将所有同种类型的请求参数封装到一个数组中,后台就可以进行绑定接收了。
接下来,以一个批量删除用户的例子来详细讲解绑定数组的操作使用:
新建一个user.jsp页面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>用户列表</title>
</head>
<body>
    <form action="${pageContext.request.contextPath}/deleteUsers" method="post">
        <table width="20%" border="1">
            <tr>
                <td>选择</td>
                <td>用户名</td>
            </tr>
            <tr>
                <td>
                    <input name="ids" value="1" type="checkbox">
                </td>
                <td>tom</td>
            </tr>
            <tr>
                <td>
                    <input name="ids" value="2" type="checkbox">
                </td>
                <td>jack</td>
            </tr>
            <tr>
                <td>
                    <input name="ids" value="3" type="checkbox">
                </td>
                <td>lucy</td>
            </tr>
        </table>
        <input type="submit" value="删除"/>
    </form>
</body>
</html>

在UserController中添加方法

/**
     * 跳转到用户列表
     * @return
     */
    @RequestMapping("/toUser")
    public String selectUsers() {
        return "user";
    }

    /**
     * 接收批量删除的方法
     * @param ids
     * @return
     */
    @RequestMapping("/deleteUsers")
    public String deleteUsers(Integer[] ids) {
        if (ids != null) {
            for (Integer id : ids) {
                System.out.println("删除了id为"+ id + "的用户");
            }
        } else {
            System.out.println("ids = null");
        }
        return "success";
    }

测试运行:

3.2 绑定集合

在批量删除用户的操作中,前端请求传递的都是同名参数的用户id,只要在后台使用同一种数组类型的参数绑定接收,就可以在方法中通过循环数组参数的方式来完成删除操作。
但如果是批量修改用户操作的话,前端请求传递过来的数据可能就会批量包含各种类型的数据,如Integer,String等。

针对上述这种情况,就可以使用集合数据绑定。即在包装类中定义一个包含用户信息类的集合,然后在接收方法中将参数类型定义为该包装类的集合。
新那一个包vo,并创建UserVO来封装用户集合的属性,代码如下:

/**
 * @Package com.ma.vo
 * @Description: 用户包装类
 * @auther MZ
 * @create 2017/11/5 15:21
 */
public class UserVO {
    private List<User> users;

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

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

在UserController中添加方法:


    /**
     * 跳转到用户编辑页面
     * @return
     */
    @RequestMapping("/toUserEdit")
    public String toUserEdit() {
        return "user_edit";
    }

    /**
     * 接收批量修改用户
     * @param userList
     * @return
     */
    @RequestMapping("/editUsers")
    public String editUsers(UserVO userList) {
        //将所有用户数据封装到集合中
        List<User> users = userList.getUsers();
        //循环输出用户信息
        for (User user : users) {
            //如果接收的用户id不为空,则表示对该用户进行了修改
            if (user.getId() != null) {
                System.out.println("修改了id为"+ user.getId() +"用户名为:"+user.getUsername());
            }
        }
        return "success";
    }

在使用集合数据绑定时,后台方法中不支持直接使用集合形参进行数据绑定,所以需要使用包装POJO作为形参,然后在包装POJO中包装一个集合属性

新建一个user_edit.jsp页面

<form action="${pageContext.request.contextPath}/editUsers" method="post" id='formid'>
    <table width="20%" border="1">
        <tr>
            <td>选择</td>
            <td>用户名</td>
        </tr>
        <tr>
            <td>
                <input name="users[0].id" value="1" type="checkbox">
            </td>
            <td>
                <input name="users[0].username" value="tome" type="text">
            </td>
        </tr>
        <tr>
            <td>
                <input name="users[1].id" value="2" type="checkbox">
            </td>
            <td><input name="users[1].username" value="jack" type="text"></td>
        </tr>

    </table>
    <input type="submit" value="修改"/>
</form>

测试结果:

小结

以上就是有关数据绑定的知识,最后的项目目录如下所示:

Spring MVC数据绑定(二)的更多相关文章

  1. Spring MVC篇二、使用JdbcTemplate进行数据库操作

    上一篇只是一个简单的Spring MVC框架,接下来添加一些跟数据库的交互. 一.添加jdbc相关配置   在maven中添加相关依赖后,配置数据库访问参数及数据源.数据库参数使用配置文件,代码如下: ...

  2. spring mvc 数据绑定

    1.spring mvc 默认提供的数据绑定类 private List<HandlerMethodArgumentResolver> getDefaultArgumentResolver ...

  3. Spring MVC(二)

    spring mvc工作流 1A)客户端发出http请求,只要请求形式符合web.xml 文件中配置的*.action的话,就由DispatcherServlet 来处理. 1B)Dispatcher ...

  4. Java框架之Spring MVC(二)

    一.Spring MVC 验证 JSR 303 是ajvaEE6 中的一项子规范 ,叫 Bean Validation 用于对javaBean中的字段进行校验. 官方的参考实现是: Hibernate ...

  5. Spring MVC 数据绑定流程分析

    1.    数据绑定流程原理★ ①   Spring MVC 主框架将 ServletRequest  对象及目标方法的入参实例传递给 WebDataBinderFactory 实例,以创建 Data ...

  6. Spring MVC数据绑定(一)

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

  7. spring mvc 数据绑定总结

    spring mvc 做web开发时,经常会不知道如何合适绑定页面数据.用惯struts2的朋友更认为spring mvc 绑定数据不如struts2方便(本人最开始也是这么认为),经过一段时间的应用 ...

  8. Spring Mvc 笔记二之异常和文件上传

    spring mvc的异常与文件上传 1.异常: spring注解版的异常有局部异常和全局异常                1.局部异常对单个controller有效;(在controller类写一 ...

  9. Spring MVC(二)基于标注的MVC

    1.基于标注的Spring MVC 1.1 建立一个项目导入jar包(ioc aop mvc) 拷贝容器对应的配置文件到src下 在WEB-INF建立一个login.jsp 1.2 在web.xml ...

  10. Spring MVC数据绑定大全 .

    刚开始用spring mvc 做web开发时,经常会不知道如何合适绑定页面数据.用惯struts2的朋友更认为spring mvc 绑定数据不如struts2方便(本人最开始也是这么认为),经过一段时 ...

随机推荐

  1. 重写Equals为什么要同时重写GetHashCode

    .NET程序员都知道,如果我们重写一个类的Equals方法而没有重写GetHashCode,则VS会提示警告 :“***”重写 Object.Equals(object o)但不重写 Object.G ...

  2. CLR via C#深解笔记七 - 自动内存管理(垃圾回收)

    每个应用程序都要使用这样或者那样的资源,比如文件.内存缓冲区.屏幕空间.网络连接.数据库资源等.事实上,在面向对象的环境中,每个类型都代表可供程序使用的一种资源. 要使用这些资源,必须为代表资源的类型 ...

  3. iOS7跳转AppStore地址

    跳转AppStore地址改变: 由 itms-apps://ax.itunes.apple.com/WebObjects/MZStore.woa/wa/viewContentsUserReviews? ...

  4. .NET连接池的配置 【转】

    ADO.Net 在数据库操作过程中默认打开了连接池,不需要再进行手工配置.这个特性可以使数据库操作时效率提高,但也要有相应的代码配合,才能真正提高程序效率. 1.连接字符串 ADO.Net 中的连接池 ...

  5. Unity3D NGUI学习(一)血条

    这次来讲讲Unity3D NGUI这个插件的学习,这个插件是收费的,不过去网上可以下载得很多可用版本.用来做用户的交互UI,学习起来比较简单 第一步,导入NGUI包 http://pan.baidu. ...

  6. POJ 3268 Silver Cow Party(Dijkstra算法求解来回最短路问题)

    题目链接: https://vjudge.net/problem/POJ-3268 One cow from each of N farms (1 ≤ N ≤ 1000) conveniently n ...

  7. tensorflow 的tf.where详解

    最近在用到数据筛选,观看代码中有tf.where()的用法,不是很常用,也不是很好理解.在这里记录一下 tf.where( condition, x=None, y=None, name=None ) ...

  8. Vue音乐项目笔记(三)

    1. 音乐播放前进后退的实现   https://blog.csdn.net/weixin_40814356/article/details/80379606 2. 音乐进度条实现(单独一个组件) h ...

  9. 【Servlet】使用org.eclipse.jetty实现小型的Servlet服务器

    import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpSer ...

  10. MySQL大数据量分页性能优化

    mysql大数据量使用limit分页,随着页码的增大,查询效率越低下. 测试实验 1.   直接用limit start, count分页语句, 也是我程序中用的方法: select * from p ...