之前学习了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. 利用结果集元数据将查询结果封装为map

    package it.cast.jdbc; import java.sql.Connection; import java.sql.ParameterMetaData; import java.sql ...

  2. JavaScript中in操作符(for..in)、Object.keys()和Object.getOwnPropertyNames()的区别

    ECMAScript将对象的属性分为两种:数据属性和访问器属性.每一种属性内部都有一些特性,这里我们只关注对象属性的[[Enumerable]]特征,它表示是否通过 for-in 循环返回属性,也可以 ...

  3. 如何设置iframe高度自适应,在跨域的情况下能做到吗?

    在页面上使用iframe来动态加载页面内容是网页开发中比较常见的方法.在父页面中给定一个不带滚动条的iframe,然后对属性src指定一个可加载的页面,这样当父页面被访问的时候,子页面可以被自动加载. ...

  4. Hadoop常用命令汇总

    启动Hadoop 进入HADOOP_HOME目录. 执行sh bin/start-all.sh 关闭Hadoop 进入HADOOP_HOME目录. 执行sh bin/stop-all.sh 1.查看指 ...

  5. mvc 相关js

    http://modernizr.com/ https://github.com/Modernizr/Modernizr/wiki 主要看下Polyfills 用于html5,用于一些老ie,fire ...

  6. JavaScript适配器模式

    适配模式可用来在现有接口和不兼容的类之间进行适配,使用这种模式的对象又叫包装器(wrapper),因为它们是在用一个新的接口包装另一个对象. 基本理论 适配器模式:将一个接口转换成客户端需要的接口而不 ...

  7. ML学习分享系列(2)_计算广告小窥[中]

    原作:面包包包包包包 改动:寒小阳 && 龙心尘 时间:2016年2月 出处:http://blog.csdn.net/Breada/article/details/50697030 ...

  8. VirtualBox 安装 Ubuntu 14.04 无法调节分辨率问题

    基础环境 宿主系统:Windows 10 虚拟机系统:Ubuntu 14.04-32bit.Ubuntu 14.04-64bit VirtualBox:5.2.0 r118431 (Qt5.6.2) ...

  9. jQuery架构(源码)分析

    ( function( global, factory ) { "use strict"; if ( typeof module === "object" &a ...

  10. 一, Python 一次性多行打印多个变量

    >>> n = 123 >>> f = 456.789 >>> s1 = 'hello ,world' >>> s2 = 'he ...