数据绑定流程分析(包括数据转换与格式化)

一:介绍

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]

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值