1.数据绑定流程分析
(1) 提出问题
① 日期字符串格式的表单参数,提交后转换为Date类型
<!--解决问题:
1. 数据类型转换
2. 数据格式
3. 数据校验
-->
BirthDay :<form:input path="birthDay"/>
Employee类中增加日期类型属性:关于类型转换
private Date birthDay ;
(2) 数据绑定流程原理
① Spring MVC 主框架将 ServletRequest 对象及目标方法的入参实例传递给 WebDataBinderFactory 实例,以创建 DataBinder 实例对象
② DataBinder 调用装配在 Spring MVC 上下文中的 ConversionService 组件进行数据类型转换、数据格式化工作。将 Servlet 中的请求信息填充到入参对象中
③ 调用 Validator 组件对已经绑定了请求消息的入参对象进行数据合法性校验,并最终生成数据绑定结果 BindingData 对象
④ Spring MVC 抽取 BindingResult 中的入参对象和校验错误对象,将它们赋给处理方法的响应入参
Spring MVC 通过反射机制对目标处理方法进行解析,将请求消息绑定到处理方法的入参中。数据绑定的核心部件是 DataBinder,运行机制如下:
2.<mvc:annotation-driven/>作用
(1) <mvc:annotation-driven/>配置在什么时候必须配置?
① 直接配置响应的页面:无需经过控制器来执行结果 ;但会导致其他请求路径失效,需要配置mvc:annotation-driven标签。
<mvc:view-controller path="/success" view-name="success"/>
<mvc:default-servlet-handler/>
② RESTful-CRUD操作,删除时,通过jQuery执行delete请求时,找不到静态资源,需要配置mvc:annotation-driven标签。
③ 配置类型转换器服务时,需要指定转换器服务引用 <mvc:annotation-driven conversion-service=“conversionService”/> 会将自定义的 ConversionService 注册到 Spring MVC 的上下文中。
④后面完成JSR 303数据验证,也需要配置。
2.<mvc:annotation-driven/>介绍:
(1) <mvc:annotation-driven/>配置在什么时候必须配置?
① 直接配置响应的页面:无需经过控制器来执行结果 ;但会导致其他请求路径失效,需要配置mvc:annotation-driven标签。
<mvc:view-controller path="/success" view-name="success"/>
<mvc:default-servlet-handler/>
② RESTful-CRUD操作,删除时,通过jQuery执行delete请求时,找不到静态资源,需要配置mvc:annotation-driven标签。
③ 配置类型转换器服务时,需要指定转换器服务引用 <mvc:annotation-driven conversion-service=“conversionService”/> 会将自定义的 ConversionService 注册到 Spring MVC 的上下文中。
④后面完成JSR 303数据验证,也需要配置。
(2) 关于 <mvc:annotation-driven />的作用:
① RequestMappingHandlerMapping
② RequestMappingHandlerAdapter
③ ExceptionHandlerExceptionResolver
说明: ①② 用于做请求路径的解析,③ 用于做异常的处理。
还将提供以下支持:
支持使用 ConversioinService 实例对表单参数进行类型转换
支持使用 @NumberFormat、@DateTimeFormat 注解完成数据类型的格式化
支持使用 @Valid 注解对 JavaBean 实例进行 JSR 303 验证
支持使用 @NumberFormat、@DateTimeFormat 注解完成数据类型的格式化
支持使用 @Valid 注解对 JavaBean 实例进行 JSR 303 验证
支持使用 @RequestBody 和 @ResponseBody 注解
3.InitBinder注解
(1) @InitBinder
由 @InitBinder 标识的方法,可以对 WebDataBinder 对象进行初始化。WebDataBinder 是 DataBinder 的子类,用于完成由表单字段到 JavaBean 属性的绑定
@InitBinder方法不能有返回值,它必须声明为void。
由 @InitBinder 标识的方法,可以对 WebDataBinder 对象进行初始化。WebDataBinder 是 DataBinder 的子类,用于完成由表单字段到 JavaBean 属性的绑定
@InitBinder方法不能有返回值,它必须声明为void。
@InitBinder方法的参数通常是 WebDataBinder
(2) 实验代码
@InitBinder
public void initBinder(WebDataBinder dataBinder){
//在给处理器方法入参POJO对象属性绑定的参数时,不希望特定参数被绑定时,可以通过这个方法来处理参数绑定问题。
dataBinder.setDisallowedFields( "lastName");
}
4.数据的格式化
(1) 日期格式化:
如果指定什么样的类型只需要在实体类的属性前面加上相对应的格式即可,详见示例:
① 页面表单
<!-- 解决问题:
1.数据类型转换
2.数据格式
3.数据校验
-->
BirthDay :<input type="text" name="birthDay"/><br><br>
② Employee类增加日期对象属性
@DateTimeFormat(pattern="yyyy-MM-dd")
private Date birthDay ;
③ 配置,配置时不能指定conversion-service属性,否则,依然报错400。
<mvc:annotation-driven conversion-service="conversionService"/>
(2) 数值格式化:
@NumberFormat 可对类似数字类型的属性进行标注,它拥有两个互斥的属性:
① style:类型为 NumberFormat.Style。用于指定样式类型,包括三种:Style.NUMBER(正常数字类型)、 Style.CURRENCY(货币类型)、 Style.PERCENT(百分数类型)
② pattern:类型为 String,自定义样式,如patter="#,###";
实验代码
salary:<form:input path= "salary" />
@NumberFormat(pattern= "#,###,###.#")
private Double salary;
@RequestMapping(value="/emp" ,method=RequestMethod.POST)
public String doAdd(Employee employee,BindingResult bindingResult,Map map){
System. out.println(employee);
if(bindingResult.getErrorCount() > 0 ){
System. out.println("类型转换处错误了" );
List<FieldError> fieldErrors = bindingResult.getFieldErrors();
for(FieldError fieldError : fieldErrors){
System. out.println(fieldError.getField() + " - " + fieldError.getDefaultMessage());
}
//如果类型转换失败后,希望跳转到添加页面,显示下拉列选
map.put("deptList", departmentDao.getDepartments());
return "add" ;
}
employeeDao.save(employee);
return "redirect:/emps" ;
}
5.SpringMVC数据校验:
(1)
JSR 303 用于对Java Bean 中的字段的值进行验证,
使得验证逻辑从业务代码中脱离出来
。是一个运行时的数据验证框架,在验证之后验证的错误信息会被马上返回。一般用于表单提交页面(如用户名必填、只能由数字字母组成等等)。
@NotNull 注解元素必须是非空
@Null 注解元素必须是空
@Digits 验证数字构成是否合法
@Future 验证是否在当前系统时间之后
@Past 验证是否在当前系统时间之前
@Max 验证值是否小于等于最大指定整数值
@Min 验证值是否大于等于最小指定整数值
@Pattern 验证字符串是否匹配指定的正则表达式
@Size 验证元素大小是否在指定范围内
@DecimalMax 验证值是否小于等于最大指定小数值
@DecimalMin 验证值是否大于等于最小指定小数值
@AssertTrue 被注释的元素必须为true
@AssertFalse 被注释的元素必须为false
(2)
Hibernate Validator扩展注解类
@Email 被注释的元素必须是电子邮箱地址
@Length 被注释的字符串的大小必须在指定的范围内
@NotEmpty 被注释的字符串的必须非空
@Range 被注释的元素必须在合适的范围内
(3) 实验代码
① 添加jar包:
hibernate-validator-5.0.0.CR2\dist
hibernate-validator-5.0.0.CR2.jar
hibernate-validator-annotation-processor-5.0.0.CR2.jar
hibernate-validator-5.0.0.CR2\dist\lib\required (EL就不需要加了)
classmate-0.8.0.jar
jboss-logging-3.1.1.GA.jar
validation-api-1.1.0.CR1.jar
② 在验证属性上增加验证注解
public class Employee {
private Integer id;
@NotEmpty
private String lastName;
@Email
private String email;
private Integer gender;
private Department department;
//关于类型转换
@Past //被标注的日期必须是一个过去的日期
@DateTimeFormat(pattern="yyyy-MM-dd")
private Date birthDay ;
@NumberFormat(pattern="#,###,###.#")
private double salary ;
}
③ 增加,如果验证失败,跳转到当前页面。
@RequestMapping(value="/emp" ,method=RequestMethod.POST)
public String doAdd(@Valid Employee employee,BindingResult bindingResult,Map map){
System. out.println(employee);
if(bindingResult.getErrorCount() > 0 ){
System. out.println("类型转换处错误了" );
List<FieldError> fieldErrors = bindingResult.getFieldErrors();
for(FieldError fieldError : fieldErrors){
System. out.println(fieldError.getField() + " - " + fieldError.getDefaultMessage());
}
//如果类型转换失败后,希望跳转到添加页面,显示下拉列选
map.put("deptList", departmentDao.getDepartments());
return "add" ;
}
employeeDao.save(employee);
return "redirect:/emps" ;
}
④ 如果校验失败,后台打印错误消息
⑤ 前台打印错误消息
⑥ 测试验证,解决EL表达式错误
拷贝hibernate-validator-5.0.0.CR2\dist\lib\required目录下的el-api-2.2.jar、javax.el-2.2.4.jar、javax.el-api-2.2.4.jar三个包到Tomcat/lib目录下,将原来的el-api.jar删除。重启tomcat6
⑦ 如果希望验证失败,回到添加页面,在上面③已经做过。
⑧ 在错误页面显示错误消息
<form:errors path= "*" /><br>< br>
(4) 关于错误消息的显示和国际化错误消息的定制:
① 在表单上页面上显示所有的错误消息
<!-- 显示所有的错误消息 -->
<form:errors path="*"/>
② 显示某一个表单域的错误消息
<%@page import="java.util.HashMap"%> <%@page import="java.util.Map"%> <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> <!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:form action="${pageContext.request.contextPath }/emp" method="POST" modelAttribute="employee"> <%-- <form:errors path="*"></form:errors><br><br> --%> LastName : <form:input path="lastName"/><form:errors path="lastName"></form:errors> <br><br> Email : <form:input path="email"/> <form:errors path="email"></form:errors><br><br> <% Map<String,String> genders = new HashMap<String,String>(); genders.put("0", "female"); genders.put("1", "male"); request.setAttribute("genders", genders); %> Gender : <form:radiobuttons path="gender" items="${requestScope.genders }"/> <br><br> <!-- itemLabel : 用于下拉中显示 itemValue : 用于提交选择的选项值 --> deptName : <form:select path="department.id" items="${requestScope.deptList }" itemLabel="departmentName" itemValue="id"></form:select> <br><br> birthDay : <form:input path="birthDay"/><form:errors path="birthDay"></form:errors><br><br> salary : <form:input path="salary"/><br><br> <input type="submit" value="添加"> <br><br> </form:form> <hr> <form action="${pageContext.request.contextPath }/empAdd" method="POST"> <!-- 解决问题: 1.数据类型转换 2.数据格式 3.数据校验 1)-如何校验 验证格式,需要个注解就可以了 ①使用JSR 303验证标准 ②加入hibernate validator验证框架 ③在SpringMVC配置文件中增加<mvc:annotation-driven/> ④需要在bean的属性上增加对应验证的注解 ⑤在目标方法bean类型的前面增加@Valid注解 2)-验证出错后,跳转到哪个页面 3)错误消息,如何显示,如何国际化 自定义类型转换器: 将字符串转换为Employee对象,完成添加功能 --> Employee : <input type="text" name="employee"/> <input type="submit" value="Submit"><br><br> </form> </body> </html>
(5) 提示消息的国际化
① 定义国际化资源文件:i18n.properties
NotEmpty.employee.lastName=\u7528\u6237\u540D\u4E0D\u80FD\u4E3A\u7A7A
Email.employee.email=\u7535\u5B50\u90AE\u4EF6\u5730\u5740\u4E0D\u5408\u6CD5
Past.employee.birthDay=\u65E5\u671F\u5FC5\u987B\u662F\u4E00\u4E2A\u8FC7\u53BB\u7684\u65F6\u95F4
typeMismatch.employee.birthDay=\u4E0D\u662F\u4E00\u4E2A\u65E5\u671F\u6709\u6548\u683C\u5F0F
② 声明国际化资源配置
<!-- 声明国际化资源文件 -->
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename" value="i18n"></property>
</bean>
6.springMVC中JSON的使用
返回异步请求一般用json,在springMVC中使用JSON通过代码演示:
(1) 加入 jar 包:
http://wiki.fasterxml.com/JacksonDownload/ 下载地址
jackson-annotations-2.1.5.jar
jackson-core-2.1.5.jar
jackson-databind-2.1.5.jar
(2) 在请求的jsp页面提交请求信息
< a id ="testJSON" href ="testJSON">testJSON </a>
(3) 编写目标方法,使其返回 JSON 对应的对象或集合
package com.atguigu.springmvc.crud.handlers;
import java.util.Collection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.atguigu.springmvc.crud.dao.EmployeeDao;
import com.atguigu.springmvc.crud.entities.Employee;
@Controller
public class JSONHandles {
@Autowired
private EmployeeDao employeeDao;
@ResponseBody //以 json的形式返回
@RequestMapping( "testJSON")
public Collection<Employee> testJSON(){
Collection<Employee> emps= employeeDao.getAll();
return emps;
}
}
(4) 增加页面代码:index.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 >
<script type= "text/javascript" src=" ${pageContext.request.contextPath }/scripts/jquery-1.9.1.min.js" ></script>
<script type= "text/javascript">
$(function(){
$( "#testJSON").click(function (){
var url = this .href;
var data = {};
var callback = function(result){
for(var i=0;i<result.length;i++){
alert(result[i].id+ " - " + result[i].lastName);
}
};
$.post(url,data,callback);
return false ;
});
});
</script>
</head>
<body>
<a id="testJSON" href= "testJSON">testJSON </a>
</body>
</html>
(5) 测试
、