一:介绍
1.介绍
Spring MVC框架将ServletRequest对象及目标方法的入参实例传递给WebDataBinderFactory实例,以创建DataBinder实例对象。
DataBinder调用装配在SpringMVC上下文中的ConversionService组件,进行数据类型转换,数据格式化工作。将servlet的请求信息填充到入参对象中。
调用Validator组件对已经绑定的请求消息的入参对象进行数据合法性校验,并最终生成数据绑定结果BingData对象。
springmvc抽取BindingResult中的入参对象和验证错误对象,将他们赋值处理方法的响应入参。
2.数据绑定流程
二:自定义类型转换器
1.需求
将一个字符串转为Employee对象
2.input.jsp页面
主要是上面的form表单
1 <%@ page language="java" contentType="text/html; charset=utf-8" 2 pageEncoding="utf-8"%> 3 <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%> 4 <%@ page import="java.util.Map"%> 5 <%@ page import="java.util.HashMap"%> 6 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 7 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 8 <html> 9 <head> 10 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> 11 <title>Insert title here</title> 12 </head> 13 <body> 14 <form action="testConversionServiceConver" method="POST"> 15 <!-- lastname-email-gender-department.id --> 16 <!-- GG-gg@123.com-0-105 --> 17 Employee:<input type="text" name="employee"/> 18 <input type="submit" values="Submit"> 19 </form> 20 <br><br> 21 <br><br><br><br><br><br> 22 23 24 <!-- id lastName email gender department --> 25 <!-- modelAttribute默认的bean是command,需要改成对应的bean --> 26 <form:form action="${pageContext.request.contextPath}/emp" method="POST" modelAttribute="employee"> 27 <!-- lastName在修改的时候,不能被显示 --> 28 <c:if test="${employee.id == null}"> 29 LastName:<form:input path="lastName"/><br> 30 </c:if> 31 <c:if test="${employee.id != null}"> 32 <form:hidden path="id"/> 33 <!-- 不能使用form标签,因为modelAttribute对应的bean中没有_method这个属性,只能使用input --> 34 <input type="hidden" name="_method" value="PUT"/> 35 </c:if> 36 37 Email:<form:input path="email"/><br> 38 <% 39 Map<String,String> genders=new HashMap(); 40 genders.put("1", "Male"); 41 genders.put("0", "Female"); 42 request.setAttribute("genders", genders); 43 %> 44 Gender:<form:radiobuttons path="gender" items="${genders}"/><br> 45 Department:<form:select path="department.id" 46 items="${department}" itemLabel="departmentName" itemValue="id"></form:select><br> 47 <input type="submit" values="Submit"> 48 </form:form> 49 </body> 50 </html>
3.自定义转换器
这个bean加了一个注解,就不需要到配置文件中配置bean了。
1 package com.spring.it.converter; 2 3 import org.springframework.core.convert.converter.Converter; 4 import org.springframework.stereotype.Component; 5 6 import com.spring.it.enties.Department; 7 import com.spring.it.enties.Employee; 8 @Component 9 public class EmployeeConverter implements Converter<String,Employee>{ 10 11 @Override 12 public Employee convert(String source) { 13 //<!-- lastname-email-gender-department.id --> 14 if(source!=null) { 15 String[] vals=source.split("-"); 16 if(vals!=null&&vals.length==4) { 17 String lastName=vals[0]; 18 String email=vals[1]; 19 Integer gender=Integer.parseInt(vals[2]); 20 Department department=new Department(); 21 department.setId(Integer.parseInt(vals[3])); 22 Employee employee=new Employee(null, lastName, email, gender, department); 23 System.out.println("*converter*"); 24 return employee; 25 } 26 } 27 return null; 28 } 29 }
4.请求处理器
主要是保存数据,传进来的是字符串,但是保存的是Employee对象。
所以,这个需要使用转换器,这个转换器写好了,然后就需要进行在配置文件中进行注册。
1 package com.spring.it.converter; 2 3 import org.springframework.beans.factory.annotation.Autowired; 4 import org.springframework.stereotype.Controller; 5 import org.springframework.web.bind.annotation.RequestMapping; 6 import org.springframework.web.bind.annotation.RequestParam; 7 8 import com.spring.it.dao.EmployeeDao; 9 import com.spring.it.enties.Employee; 10 11 @Controller 12 public class BinderTest { 13 @Autowired 14 private EmployeeDao employeeDao; 15 @RequestMapping("/testConversionServiceConver") 16 public String testConverter(@RequestParam("employee") Employee employee) { 17 employeeDao.save(employee); 18 return "redirect:/emps"; 19 } 20 }
5.配置文件
主要有两个部分要添加。
转换器,annotation-driven。
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xmlns:context="http://www.springframework.org/schema/context" 5 xmlns:mvc="http://www.springframework.org/schema/mvc" 6 xsi:schemaLocation="http://www.springframework.org/schema/beans 7 http://www.springframework.org/schema/beans/spring-beans.xsd 8 http://www.springframework.org/schema/context 9 http://www.springframework.org/schema/context/spring-context-4.0.xsd 10 http://www.springframework.org/schema/mvc 11 http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd"> 12 <!-- 配置自定义扫描的包 --> 13 <context:component-scan base-package="com.spring.it" ></context:component-scan> 14 15 <!-- 配置视图解析器 --> 16 <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> 17 <property name="prefix" value="/WEB-INF/views/" /> 18 <property name="suffix" value=".jsp" /> 19 </bean> 20 21 <!-- 转换器 --> 22 <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean"> 23 <property name="converters"> 24 <set> 25 <ref bean="employeeConverter"/> 26 </set> 27 </property> 28 </bean> 29 <mvc:annotation-driven conversion-service="conversionService"></mvc:annotation-driven> 30 31 <mvc:default-servlet-handler/> 32 <mvc:annotation-driven ignore-default-model-on-redirect="true"></mvc:annotation-driven> 33 </beans>
6.效果
三:mvc:annotation-driven标签
1.使用的场景
配置直接转发的页面的时候,但是配置的requestmapping不好用了,加了这个标签就可以了。
配置静态资源的时候,但是配置的requestmapping不好用了,加了这个标签就可以了
类型转换器的时候,需要装配自定义的类型转换器。
四:@InitBinder
1.介绍
由@InitBinder标识的方法,可以对WebDataBinder对象进行初始化。
WebDataBinder是DataBinder的子类,用于完成有表单字段到JavaBean属性的绑定。
@InitBinder方法不能有返回值,必须声明为void
@InitBinder方法的参数通常是WebDataBinder
2.示例
需求:不传入lastName。
最后一个方法。
1 package com.spring.it.handlers; 2 3 import java.util.Map; 4 5 import org.springframework.beans.factory.annotation.Autowired; 6 import org.springframework.stereotype.Controller; 7 import org.springframework.web.bind.WebDataBinder; 8 import org.springframework.web.bind.annotation.InitBinder; 9 import org.springframework.web.bind.annotation.ModelAttribute; 10 import org.springframework.web.bind.annotation.PathVariable; 11 import org.springframework.web.bind.annotation.RequestMapping; 12 import org.springframework.web.bind.annotation.RequestMethod; 13 import org.springframework.web.bind.annotation.RequestParam; 14 import org.springframework.web.bind.annotation.ResponseBody; 15 import org.springframework.web.servlet.view.RedirectView; 16 17 import com.spring.it.dao.DepartmentDao; 18 import com.spring.it.dao.EmployeeDao; 19 import com.spring.it.enties.Department; 20 import com.spring.it.enties.Employee; 21 22 @Controller 23 public class EmployeeHander { 24 @Autowired(required=true) 25 private EmployeeDao employeeDao; 26 27 @Autowired(required=true) 28 private DepartmentDao departmentDao; 29 30 /** 31 * 使得lastName不被修改,使用ModelAttribute 32 */ 33 @ModelAttribute 34 public void getEmployee(@RequestParam(value="id",required=false) Integer id,Map<String,Object> map) { 35 if(id!=null) { 36 map.put("employee", employeeDao.get(id)); 37 } 38 } 39 40 /** 41 * 编辑,主要是提交 42 */ 43 @RequestMapping(value="/emp",method=RequestMethod.PUT) 44 public String update(Employee employee) { 45 employeeDao.save(employee); 46 return "redirect:/emps"; 47 } 48 49 /** 50 * 编辑,主要是跳转到要编辑的页面 51 */ 52 @RequestMapping(value="/emp/{id}",method=RequestMethod.GET) 53 public String input(@PathVariable("id") Integer id,Map<String,Object> map) { 54 map.put("department", departmentDao.getDepartments()); 55 //回显 56 map.put("employee", employeeDao.get(id)); 57 return "input"; 58 } 59 60 /** 61 * 删除操作 62 */ 63 @RequestMapping(value="/emp/{id}",method=RequestMethod.DELETE) 64 @ResponseBody 65 public String delete(@PathVariable("id") Integer id) { 66 employeeDao.delete(id); 67 return "redirect:/emps"; 68 } 69 70 /** 71 * 保存,是submit提交过来的请求,属于Post请求 72 */ 73 @RequestMapping(value="/emp",method=RequestMethod.POST) 74 public String save(Employee employee) { 75 employeeDao.save(employee); 76 return "redirect:/emps"; 77 } 78 79 /** 80 * 跳转到input页面,用于添加员工,是Get请求 81 */ 82 @RequestMapping(value="/emp",method=RequestMethod.GET) 83 public String input(Map<String,Object> map) { 84 map.put("department", departmentDao.getDepartments()); 85 //因为form表单的原因,默认一定要回显,第一次尽进来需要传入一个值 86 map.put("employee", new Employee()); 87 return "input"; 88 } 89 90 /** 91 * 展示所有的员工 92 */ 93 @RequestMapping("/emps") 94 public String list(Map<String,Object> map) { 95 System.out.println("===="); 96 map.put("employee", employeeDao.getAll()); 97 return "list"; 98 } 99 100 /** 101 * InitBinder的使用 102 */ 103 @InitBinder 104 public void intiBinder(WebDataBinder binder) { 105 binder.setDisallowedFields("lastName"); 106 } 107 }
3.效果
五:格式化
1.说明
格式化还是属于类型转换的范畴。
2.格式化的底层
3.input
最下面的属于演示代码:
1 <%@ page language="java" contentType="text/html; charset=utf-8" 2 pageEncoding="utf-8"%> 3 <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%> 4 <%@ page import="java.util.Map"%> 5 <%@ page import="java.util.HashMap"%> 6 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 7 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 8 <html> 9 <head> 10 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> 11 <title>Insert title here</title> 12 </head> 13 <body> 14 <form action="testConversionServiceConver" method="POST"> 15 <!-- lastname-email-gender-department.id --> 16 <!-- GG-gg@123.com-0-105 --> 17 Employee:<input type="text" name="employee"/> 18 <input type="submit" values="Submit"> 19 </form> 20 <br><br> 21 <br><br><br><br><br><br> 22 23 24 <!-- id lastName email gender department --> 25 <!-- modelAttribute默认的bean是command,需要改成对应的bean --> 26 <form:form action="${pageContext.request.contextPath}/emp" method="POST" modelAttribute="employee"> 27 <!-- lastName在修改的时候,不能被显示 --> 28 <c:if test="${employee.id == null}"> 29 LastName:<form:input path="lastName"/><br> 30 </c:if> 31 <c:if test="${employee.id != null}"> 32 <form:hidden path="id"/> 33 <!-- 不能使用form标签,因为modelAttribute对应的bean中没有_method这个属性,只能使用input --> 34 <input type="hidden" name="_method" value="PUT"/> 35 </c:if> 36 37 Email:<form:input path="email"/><br> 38 <% 39 Map<String,String> genders=new HashMap(); 40 genders.put("1", "Male"); 41 genders.put("0", "Female"); 42 request.setAttribute("genders", genders); 43 %> 44 Gender:<form:radiobuttons path="gender" items="${genders}"/><br> 45 Department:<form:select path="department.id" 46 items="${department}" itemLabel="departmentName" itemValue="id"></form:select><br> 47 48 <!-- 演示格式化 --> 49 Birth:<form:input path="birth"/><br> 50 Salary:<form:input path="salary"/><br> 51 <input type="submit" values="Submit"> 52 </form:form> 53 </body> 54 </html>
4.Employee
重要的是两个字段,上面加上了注解。
1 package com.spring.it.enties; 2 3 import java.util.Date; 4 import org.springframework.format.annotation.DateTimeFormat; 5 import org.springframework.format.annotation.NumberFormat; 6 7 public class Employee { 8 9 private Integer id; 10 private String lastName; 11 private String email; 12 //1 male, 0 female 13 private Integer gender; 14 private Department department; 15 //birth 16 @DateTimeFormat(pattern="yyyy-MM-dd") 17 private Date birth; 18 //salary 19 @NumberFormat(pattern="###.#") 20 private Float salary; 21 22 public Employee(Integer id, String lastName, String email, Integer gender, 23 Department department) { 24 this.id = id; 25 this.lastName = lastName; 26 this.email = email; 27 this.gender = gender; 28 this.department = department; 29 } 30 31 public Employee() { 32 33 } 34 public Integer getId() { 35 return id; 36 } 37 38 public void setId(Integer id) { 39 this.id = id; 40 } 41 42 public String getLastName() { 43 return lastName; 44 } 45 46 public void setLastName(String lastName) { 47 this.lastName =lastName; 48 } 49 50 public String getEmail() { 51 return email; 52 } 53 54 public void setEmail(String email) { 55 this.email = email; 56 } 57 58 public Integer getGender() { 59 return gender; 60 } 61 62 public void setGender(Integer gender) { 63 this.gender = gender; 64 } 65 66 public Department getDepartment() { 67 return department; 68 } 69 70 public void setDepartment(Department department) { 71 this.department = department; 72 } 73 74 public Date getBirth() { 75 return birth; 76 } 77 78 public void setBirth(Date birth) { 79 this.birth = birth; 80 } 81 // 82 83 public Float getSalary() { 84 return salary; 85 } 86 87 public void setSalary(Float salary) { 88 this.salary = salary; 89 } 90 91 @Override 92 public String toString() { 93 return "Employee [id=" + id + ", lastName=" + lastName + ", email=" + email + ", gender=" + gender 94 + ", department=" + department + ", birth=" + birth + ", salary=" + salary + "]"; 95 } 96 97 }
5.EmployeeHander.java
主要的操作是保存处理函数。
1 /** 2 * 保存,是submit提交过来的请求,属于Post请求 3 */ 4 @RequestMapping(value="/emp",method=RequestMethod.POST) 5 public String save(Employee employee,BindingResult result) { 6 System.out.println(employee); 7 if(result.getErrorCount()>0) { 8 System.out.println("has error"); 9 for(FieldError error:result.getFieldErrors()) { 10 System.out.println(error.getField()+":"+error.getDefaultMessage()); 11 } 12 } 13 employeeDao.save(employee); 14 return "redirect:/emps"; 15 }
6.效果
Employee [id=null, lastName=null, email=OO.123.COM, gender=0, department=Department [id=101, departmentName=null], birth=Tue Feb 04 00:00:00 CST 1992, salary=124.6]