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


    一:介绍

    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]

  • 相关阅读:
    inndo 表与存储逻辑_1
    msyql master thread
    redo log重做日志缓冲
    redo log 重做日志
    Latex 写算法伪代码
    Just for test
    ASP.NET Web API 2 OData v4教程
    MVC系统过滤器 OutputCacheAttribute
    MVC系统过滤器、自定义过滤器
    .NET如何从配置文件中获取连接字符串
  • 原文地址:https://www.cnblogs.com/juncaoit/p/8728217.html
Copyright © 2020-2023  润新知