spirng 数据绑定

数据绑定

数据绑定介绍

在执行程序时,Spring MVC会根据客户端请求参数的不同,将请求消息中的信息以一定的方式转换并绑定到控制器类的方法参数中。这种将请求消息数据与后台方法参数建立连接的过程就是Spring MVC中的数据绑定。
在数据绑定过程中,Spring MVC框架会通过数据绑定组件将请求参数串的内容进行类型转换,然后将转换后的值赋给控制器类中方法的形参,这样后台方法就可以正确绑定并获取客户端请求携带的参数了。
1)Spring MVC将ServletRequest对象传递给DataBinder。
2)将处理方法的入参对象传递给DataBinder。
3)DataBinder调用ConversionService组件进行数据类型转换、数据格式化等工作,并将ServletRequest对象中的消息填充到参数对象中。
4)调用Validator组件对已经绑定了请求消息数据的参数对象进行数据合法性校验。
5)校验完成后会生成数据绑定结果BindingResult对象,Spring MVC会将BindingResult对象中的内容赋给处理方法的相应参数。
根据客户端请求参数类型和个数的不同,我们将Spring MVC中的数据绑定主要分为简单数据绑定和复杂数据绑定

简单数据绑定

绑定默认数据类型

当前端请求的参数比较简单时,可以在后台方法的形参中直接使用Spring MVC提供的默认参数类型进行数据绑定。
常用的默认参数类型
1、HttpServletRequest:通过request对象获取请求信息
2、HttpServletResponse:通过response处理响应信息
3、HttpSession:通过session对象的得到session中存储的对象
4、Model/ModelMap:Model是一个接口,ModelMap是一个接口实现,作用是将model数据填充到request域。
1)在Eclipse中,创建一个名为chapter13的Web项目,然后将Spring MVC相关JAR包添加到项目的lib目录下,并发布到类路径中。添加JAR包后的lib目录。
2)在web.xml中,配置Spring MVC的前端控制器等信息。
3)在src目录下,创建SpringMVC的核心配置文件springmvc-config.xml,在该文件中配置组件扫描器和视图解析器。
springmvc-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    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.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">
	<context:component-scan base-package="com.ex.controller"/>
	<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
	<property name="prefix" value="/WEB-INF/jsp/"/>
	<property name="suffix" value=".jsp"/>
</bean>
</beans>

4)在src目录下,创建一个com.ex.controller包,在该包下创建一个用于用户操作的控制器类UserController

package com.ex.controller;

import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class UserController {
	@RequestMapping("/selectUser")
	public String selectUser(HttpServletRequest request){
		String id=request.getParameter("id");
		System.out.println("id="+id);
		return "success";
	}
}

5)在WEB-INF目录下,创建一个名为jsp的文件夹,然后在该文件夹中创建页面文件success,jsp,该界面只作为正确执行操作后的响应页面,没有其他业务逻辑

<%@ 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>Insert title here</title>
</head>
<body>
  ok
</body>
</html>

6)将项目发布到Tomcat中并启动,在浏览访问。
在这里插入图片描述
在这里插入图片描述

绑定简单数据类型

简单数据类型的绑定,就是指Java中几种基本数据类型的绑定,如int、String、Double等类型。
1)首先修改控制器类,将控制器中的方法的参数修改为使用简单数据类型的形式

	@RequestMapping("/selectUser")
	public String selectUser(int id){
		System.out.println("id="+id);
		return "success";
	}

与默认数据类型案例中的selectUser()方法相比,此方法中只是将HttpServletRequest参数替换为了Integer类型。
启动项目,用浏览器打开查看
在这里插入图片描述
需要注意的是,有时候前端请求中的参数名和后台控制器类方法中的形参名不一样,这就会导致后台无法正确绑定并接收到前端请求的参数。为此,Spring MVC提供了RequestParam注解来进行间接数据绑定。
@RequestParam注解主要用于对请求中的参数进行定义,在使用时可以指定它的4个属性

属性说明
valuename属性的别名,这里指参数的名字,即入参的请求参数名字,如value="item_id"表示请求的参数中名字为item_id的参数的值将传入。如果只使用value属性,则可以省略value属性名
name指定请求头绑定的名称,同value
require用于指定参数是否必须,默认是true,表示请求中一定要有相应的参数
defaultValue默认值,表示如果请求中没有同名参数时的默认值
	@RequestMapping("/selectUser")
	public String selectUser(@RequestParam(value="user_id")Integer id){
		System.out.println("id="+id);
		return "success";
	}

绑定POJO类型

在使用简单数据类型绑定时,可以很容易地根据具体需求来定义方法中地形参类型和个数,然而在实际应用中,客户端请求可能会传递多个不同类型地参数数据,如果还使用简单数据类型进行绑定,那么就需要手动编写多个不同类型地参数,这种操作显然比较繁琐。此时就可以使用POJO类型进行数据绑定。
POJO类型的数据绑定就是将所有关联的请求参数封装在一个POJO中,然后在方法中直接使用该POJO作为形参来完成数据绑定。
1)在src目录下,创建一个com.ex.po包,在包下创建一个User类来封装用户注册的信息参数
User.java

package com.ex.po;
public class User {
	private Integer id;
	private String username;
	private Integer password;
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}
	public Integer getPassword() {
		return password;
	}
	public void setPassword(Integer password) {
		this.password = password;
	}
}

2)在控制器UserController类中,编写接受用户注册信息和向注册页面跳转地方法

	@RequestMapping("/toRegister")
	public String toRegister(){
		return "register";
	}
	@RequestMapping("/registerUser")
	public String registerUser(User user){
		String username=user.getUsername();
		Integer password=user.getPassword();
		System.out.println("username="+username);
		System.out.println("password="+password);
		return "success";
	}

3)在/WEB-INF/jsp目录下,创建一个用户注册页面register.jsp,在该界面中编写用户注册表单,表单需要以POST方式提交,并且在提交时会发送一条以"/registerUser"结尾地请求消息。
register.jsp

<%@ 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>Insert title here</title>
</head>
<body>
	<form action="${pageContext.request.contextPath}/registerUser" method="post">
		用户名:<input type="text name="username"/><br/> 
		密码:<input type="password" name="password"/><br/>
		<input type="submit" value="注册"/>
	</form>
</body>
</html>

4)将项目发布到Tomcat服务器并启动,浏览器访问
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
解决请求参数中文乱码
在这里插入图片描述
在这里插入图片描述
可以看到,密码信息已正确显示,用户名却是乱码。
为了防止前端传入的中文出现乱码问题,我们可以使用Spring提供的编码过滤器来统一编码,要使用编码过滤器,执行在web.xml中添加如下代码

<filter>
  	<filter-name>CharacterEncodingFilter</filter-name>
  	<filter-class>
  		org.springframework.web.filter.CharacterEncodingFilter
  	</filter-class>
  	<init-param>
  		<param-name>encoding</param-name>
  		<param-value>UTF-8</param-value>
  	</init-param>
  </filter>
  <filter-mapping>
  	<filter-name>CharacterEncodingFilter</filter-name>
  	<url-pattern>/*</url-pattern>
  </filter-mapping>

上述代码通过<filter-mapping>元素的配置会拦截前端页面中的所有请求,并交由名称为CharacterEncodingFilter的编码过滤器类进行处理,在<filter>元素中,首先配置了编码过滤器类org.springframework.web.filter.CharacterEncodingFilter,然后通过初始化参数设置统一的编码为UTF-8,这样所有的请求信息内容都会以UTF-8的编码格式进行解析。
在这里插入图片描述

绑定包装POJO

使用简单POJO类型已经完成多数的数据绑定,但有时客户端请求中传递的参数会比较复杂。例如,在用户查询订单时,页面传递的参数可能包括订单编号、用户名等信息,这就包括了订单和用户两个对象的信息,如果将订单和用户的所有查询条件都封装在一个简单POJO中,显然会比较混乱,这时就可以考虑使用包装POJO类型的数据绑定。
1)在chapter13项目的com.ex.po包中,创建一个订单类,Orders,该类用于封装订单和用户信息
Orders.java

package com.ex.po;
public class Orders {
	private Integer ordersId;
	private User user;
	public Integer getOrdersId() {
		return ordersId;
	}
	public void setOrdersId(Integer ordersId) {
		this.ordersId = ordersId;
	}
	public User getUser() {
		return user;
	}
	public void setUser(User user) {
		this.user = user;
	}
}

在上述包中装类POJO类中,定义了订单号和用于POJO的属性及其对应的getter/setter方法。这样订单类中不仅可以封装订单的基本属性参数,还可以封装User类型的属性参数。
2)在com.ex.controler包中,创建一个订单控制器类OrdersController,在该类中编写一个跳转到订单查询页面的方法和一个查询订单及用户信息的方法
OrdersController.java

	@RequestMapping("findOrdersWithUser")
	public String findOrdersWithUser(Orders orders){
		Integer orderId=orders.getOrdersId();
		User user=orders.getUser();
		String username=user.getUsername();
		System.out.println("ordersId="+ordersId);
		System.out.println("username="+username);
		return "success";
	}

3)在/WEB-INF/jsp目录下,创建一个用户订单查询页面orders.jsp,在页面中编写通过订单编号和所属用户作为查询条件来查询订单信息的代码

<%@ 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>Insert title here</title>
</head>
<body>
	<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>
</body>
</html>

4)浏览器访问
在这里插入图片描述
在这里插入图片描述

自定义数据绑定

在一般情况下,使用基本数据类型和POJO类型的参数数据,然而有些特殊类型的参数是无法在后台进行直接转换的,例如日期数据就需要开发自定义转换器或格式化来进行数据绑定。
1、Converter
Spring框架提供了一个Converter用于将一种类型的对象转换为另一种类型的对象。例如,用户输入的日期形式可能是"2017-04-08"或"2017/04/08"的字符串,而要Spring将输入的日期与后天的Date进行绑定,则需要将字符串转换为日期,此时就可以自定义一个Converter类来进行日期转换。
自定义Converter类需要实现org.springframework.core.convert.converter.Converter接口

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

在上述接口代码中,泛型中的S表示源类型,T表示目标类型,而convert(S source)表示接口中的方法。
在src目录下,创建一个com.ex.convert包,在该包下创建日期转换类DataConverter,并在该类接口中编写将String类型转化成Date类型的代码,
DateConverter.java

package com.ex.convert;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.springframework.core.convert.converter.Converter;
public class DateConverter implements Converter<String,Date>{
	private String datePattern="yyyy-MM-dd HH:mm:ss";
	@Override
	public Date convert(String source) {
		SimpleDateFormat sdf=new SimpleDateFormat(datePattern);
		try{
			return sdf.parse(source);
		}catch (ParseException e){
			throw new IllegalArgumentException("无效的日期格式,请使用这种格式:"+datePattern);
		}
	}
	
}

在上述代码中,DateConverter类实现了Converter接口,该接口中第一个类型String表示需要被转换的数据类型,第二个类型Date表示需要转换成的目标类型。
为了让Spring MVC知道并使用这个转换器类,还需要在其配置文件中编写一个id为conversionService的Bean
springmvc-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
	xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd">
	<context:component-scan base-package="com.ex.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="conversion">
		<set>
			<bean class="com.ex.convert.DateConverter"/>
		</set>
	</property>
</bean>
</beans>

首先添加了3个mvc的schema信息;然后定义了组件扫描器和视图解析器;接下来显示装配了自定义的类型转换器;最后编写了自定义类型转换器的配置,其中Bean的类名称必须为org.springframework.context.support.ConversionServiceFactoryBean,并且Bean中还需要包含一个converters属性,通过该属性列出程序中自定义的所有Converter。
为了测试转换器的使用,可以在com.ex.controller包中创建一个日期控制类DateController,并在类中编写绑定日期数据的方法。

package com.ex.controller;

import java.util.Date;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;


@Controller
public class DateController {
	@RequestMapping("/customDate")
	public String CustomDate(Date date){
		System.out.println("date="+date);
		return "success";
	}
}

在这里插入图片描述

在这里插入图片描述
注意:日期数据之间的空格。
2、Formatter
除了使用Converter进行转换外,我们还可以使用Formatter来进行类型转换。Formatter与Converter的作用相同,只是Formatter的源类型必须是一个String类型,而Converter可以是任意类型。
使用Formatter自定义转化器类需要实现org.springframework.format.Formatter接口

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

在上述代码中,Formatter接口继承了Printer和Parser接口,其泛型T表示输入字符串要转换的目标类型。在Print和Parser接口中,分别包括一个print()和Parse()方法,所有的实现类必须覆盖这两个方法。
在com.ex.convert包中,创建日期转换类DateFormatter,在该类中使用Formatter自定义日期转换器
DateFormatter.java

package com.ex.controller;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import org.springframework.format.Formatter;
public class DateFormatter implements Formatter<Date>{
	private String datePattern="yyyy-MM-dd HH:mm:ss";
	private SimpleDateFormat simpleDateFormat;
	@Override
	public String print(Date date, Locale locale) {
		return new SimpleDateFormat().format(date);
	}

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

DateFirmatter类实现了Formatter接口,并实现了接口中的两个方法。其中print()方法会返回目标对象的字符串,而parse()方法会利用指定的Locale将一个String解析成目标类型。
要使用Formatter自定义的日期转换器,同样需要在Spring MVC的配置文件中进行注册

<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
	<property name="formatters">
		<set>
			<bean class="com.ex.convert.DateFormatter"/>
		</set>
	</property>
</bean>

在这里插入图片描述

复杂数据绑定

绑定数组

在实际开发中,可能会遇到前端请求需要传递到后台一个或多个相同名称参数的情况(如批量删除),此种情况采用前面讲解的简单数据绑定的方式显然是不合适的。此时,就可以使用绑定数组的方式,来完成实际需求。
1)在chapter13项目的/WEB-INF/jsp目录下,创建一个展示用户信息的列表页面user.jsp

<%@ 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>Insert title here</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>
	</form>
</body>
</html>

2)在控制类UserController中,编写接受批量删除用户的方法

	@RequestMapping("/toUser")
	public String selectUsers(){
		return "user";
	}
	@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)浏览器访问
在这里插入图片描述
在这里插入图片描述

绑定集合

前端传递过来的数据可能就会包含各种类型的数据,如Integer、String等。针对这种情况,我们可以使用集合数据绑定。即在包装类中定义一个包含用户信息类的集合,然后在接受方法中将参数类型定义为该包装类的集合。
1)在src目录下,创建一个com.ex.vo包,并在包中创建包装类UserVO来封装用户集合属性
UserVO.java

package com.ex.vo;

import java.util.List;

import com.ex.po.User;

public class UserVO {
	private List<User> users;

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

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

2)在控制器类UserController中,编写接受批量修改用户的方法,以及向用户修改页面跳转的方法

	@RequestMapping("/toUserEdit")
	public String toUserEdit(){
		return "user_edit";
	}
	@RequestMapping("/editUsers")
	public String editUsers(UserVO userList){
		List<User> users=userList.getUsers();
		for(User user:users){
			if(user.getId()!=null){
				System.out.println("修改了id为"+user.getId()+"的用户名为:"+user.getUsername());
			}
		}
		return "success";
	}

注:在使用集合数据绑定时,后台方法中不支持直接使用结合形参进行数据绑定,所以需要使用包装POJO作为形参,然后在POJO中包装一个集合属性。
3)在项目的/WEB-INF/jsp目录下,创建页面文件user_edit.jsp

<%@ 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>Insert title here</title>
</head>
<body>
		<form action="${pageContext.request.contextPath }/editUsers" method="post">
		<table width="20%" border=1>
			<tr>
				<td>选择</td>
				<td>用户名</td>
			</tr>
			<tr>
				<td><input name="user[0].id" value=1 type="checkbox"></td>
				<td><input name="user[0].username" value="tome" type="text"></td>
			</tr>
			<tr>
				<td><input name="user[1].id" value=2 type="checkbox"></td>
				<td><input name="user[1].username" value="jack" type="text"></td>
			</tr>
		</table>
		<input type="submit" value="修改"/>
	</form>
</body>
</html>

4)浏览器查看

在这里插入图片描述
在这里插入图片描述

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值