数据绑定,在我的理解里就是表单参数与方法形参之间的映射及转换关系的描述,比如,形参名称与表单参数名称的同名映射机制,@RequestParam value属性带来的别名机制(间接绑定),又或者说POJO类型对象接收参数时的属性名与表单参数名,属性对象的属性名与表单参数的映射(表单参数名,需要写成属性对象名称.属性名的形式,形如 staff.lastname)都属于数据的绑定。

不知道大家有没有好奇,即使通过各种形式,完成了表单参数与形参上的映射,但表单参数实际上传递的都是字符串,它又是如何赋值给形参中的int、double、datetime等等这些类型中的呢,这也是数据绑定的一种表现形式,同时也是最典型最显著的一种形式。

它内部的机制大概如下:

1.springmvc把ServletRequest对象传递给DataBinder;
2.将处理方法的入参对象传递给DataBinder;
3.DataBinder调用ConversionService组件进行数据类型转换、数据格式化,并将ServletRequest对象中的消息填充到参数对象中;
4.调用Validator组件对已经绑定了请求数据的参数对象进行数据合法性检测;
5.校验完成后会生成数据绑定结果BindingResult对象,springmvc会将BindingResult对象中的内容赋给处理方法的对应参数;

当请求处理方法被调用时,首先被唤醒开始工作的是RequestMappingAdapterHandler,它会将Servlet对象传给DataBinder,

有些时候,这个概念还包含了数据验证,它可以让框架更多的自动化,更好容错性以及更高的编码效率,像在spring中,model中的数据与request域的绑定就是这样一种关系,他其实就相当于spring帮我们屏蔽了底部servletapi,我们只需要使用Spring的api就可以实现这些功能,但这并不意味着数据绑定不重要,相反,想让框架更丝滑,就需要对数据绑定的运用更加出神入化,所以,我们需要对这一概念有着更深入的了解。

整个的应用,除了体现在参数接收之外,还有一些典型的场景,Converter、formatter 以及Validater。

内置的类型转换器

转换器其实是对Converter<S,T> 接口的不同实现,它提供的能力,是将一种数据类型转换成另一种数据类型的接口,这里 S 表示源类型,T 表示目标类型。类型转换一般发生在前后端进行数据交互时,对于基本类型(例如 int、long、float、double、boolean 以及 char 等),框架已经做好了基本类型转换。另外,对于常用的引用数据类型,我们无须创建自己的类型转换器,因为SpringMVC 提供了大量内置的类型转换器替我们完成了这部分的工作。

标量转换器

名称 作用
StringToBooleanConverter String 到 boolean 类型转换
ObjectToStringConverter Object 到 String 转换,调用 toString 方法转换
StringToNumberConverterFactory String 到数字转换(例如 Integer、Long 等)
NumberToNumberConverterFactory 数字子类型(基本类型)到数字类型(包装类型)转换
StringToCharacterConverter String 到 Character 转换,取字符串中的第一个字符
NumberToCharacterConverter 数字子类型到 Character 转换
CharacterToNumberFactory Character 到数字子类型转换
StringToEnumConverterFactory String 到枚举类型转换,通过 Enum.valueOf 将字符串转换为需要的枚举类型
EnumToStringConverter 枚举类型到 String 转换,返回枚举对象的 name 值
StringToLocaleConverter String 到 java.util.Locale 转换
PropertiesToStringConverter java.util.Properties 到 String 转换,默认通过 ISO-8859-1 解码
StringToPropertiesConverter String 到 java.util.Properties 转换,默认使用 ISO-8859-1 编码

集合、数组相关转换器

名称 作用
ArrayToCollectionConverter 任意数组到任意集合(List、Set)转换
CollectionToArrayConverter 任意集合到任意数组转换
ArrayToArrayConverter 任意数组到任意数组转换
CollectionToCollectionConverter 集合之间的类型转换
MapToMapConverter Map之间的类型转换
ArrayToStringConverter 任意数组到 String 转换
StringToArrayConverter 字符串到数组的转换,默认通过“,”分割,且去除字符串两边的空格(trim)
ArrayToObjectConverter 任意数组到 Object 的转换,如果目标类型和源类型兼容,直接返回源对象;否则返回数组的第一个元素并进行类型转换
ObjectToArrayConverter Object 到单元素数组转换
CollectionToStringConverter 任意集合(List、Set)到 String 转换
StringToCollectionConverter String 到集合(List、Set)转换,默认通过“,”分割,且去除字符串两边的空格(trim)
CollectionToObjectConverter 任意集合到任意 Object 的转换,如果目标类型和源类型兼容,直接返回源对象;否则返回集合的第一个元素并进行类型转换
ObjectToCollectionConverter Object 到单元素集合的类型转换

:在使用内置类型转换器时,请求参数输入值与接收参数类型要兼容,否则会报 400 错误。请求参数类型与接收参数类型不兼容问题可以利用数据校验处理

自定义类型转换器

大多数情况下,内置的类型转换器都足以支持我们的开发正常进行,但也会存在特殊类型需要我们编写特定的类型转换器,SpringMVC 提供了3种转换器接口:

  • Converter<S,T>:将S类型对象转换为T类型对象。
  • ConverterFactory:将相同系列多个“同质”Converter封装一起。如果希望将一种类型的对象转换为另一种类型及其子类的对象(例如将String转换为Number及Number子类(Integer,Long,Double等)对象)可使用该转换器工厂类
  • GenericConverter:会根据源类对象及目标类对象所在的宿主类中的上下文信息进行类型转换

对任意一个接口进行实现,都可以把自定义的转换器注册进 ConversironServiceFactoryBean 中。不过,只是实现接口,框架并不会立刻识别到我们的自定义类型转换器 ,还需要 一些在配置文件中做一些调整,这里我们来做一个演示吧!

场景模拟分析

大概的业务场景是这样,用户在浏览人员列表时,突然对某个人特别感兴趣,想查看其详细信息。那这个时候,客户端会将用户选中行的主键标识通过请求发送至服务器端,它希望可以从响应或者域中拿到对应的信息,这个时候我们的思路大概是这样:

  • 正常的情况是我们需要手动编码从数据库查询对应数据,然后将信息封装成 bean对象后响应回传给客户端,或者通过域共享给客户端
  • 有转换器的情况下,我们就可以考虑将数据查询以及封装的动作在转换器内进行,这样的话,查询和封装的动作就会在每次请求时,自动进行

关于具体实现的步骤,我们需要做这样几件事:

  • 创建实体类
  • 创建控制器类
  • 创建自定义类型转换器类
  • 注册类型转换器
  • 创建相关视图

关于项目环境的搭建,大家可以参考之前的文章

创建实体类

在 net.biancheng.po 包下创建 User 实体类,代码如下。

@Data
@ToString
public class Person implements Serializable {// private Long id;@Length(min = 2, max = 8, message = "用户名不能少于2位大于8位")private String lastname;private String username;private int age;@DateTimeFormat(pattern = "yyyy-MM-dd")private Date birthday;private LocalDate workDate;private double height;@Email(regexp = "[a-zA-Z0-9]+@[a-zA-Z0-9]+\\.[a-zA-Z0-9]", message = "邮箱格式不正确")private String email;@NotNull(message = "手机号不可为空")private String mobile;}

创建控制器类

@RequestMapping("add")
public String addPerson(){// System.out.println("沾衣不湿杏花雨,吹面不寒杨柳风");return "person/add";
}@RequestMapping("convert")
public String convert(@RequestParam("id") Person person, Model model){model.addAttribute("person",person);return "person/info";
}
  • addPerson() 用于获取表单填写的视图,这里用表单填写代替查询列表以及点击事件
  • convert() 方法是核心的请求处理方法,用于测试类型的转换,我们可以在转发的视图页中验证转换的效果
  • 注释的那句,是我闲着没事测试热部署的,你们有兴趣的话,也可以搞一波,参考在这里

创建自定义类型转换器

public class PersonConverter implements Converter<String, Person> {@Overridepublic Person convert(String source) {Person person = new Person();if ("1".equals(source)){person.setLastname("user_01");person.setAge(23);}else if ("2".equals(source)){person.setLastname("user_02");person.setAge(27);}else{throw new IllegalArgumentException("类型转换失败!!!");}return person;}
}
  • 为了代码结构的简洁,这里直接硬编码填充了人员数据,真实场景中我们一般从数据库或者缓存中拿数据
  • 关于异常的处理,可以结合自定义异常以及统一异常处理等场景来考虑,咱们不扩展,有兴趣的话,可以参考

配置转换器

在 springmvc-servlet.xml 文件中添加以下代码。

<!-- 不配置的情况下,使用默认的 ConversionService配置的情况下,不是覆盖默认的机制,而是在原有的基础上,追加自定义的配置
-->
<mvc:annotation-driven conversion-service="converterService"/>
<!-- 配置ConversionFactoryBean 的 converters 属性 -->
<bean id="converterService" class="org.springframework.context.support.ConversionServiceFactoryBean"> <property name="converters"><list><bean class="com.fanshr.springmvc.converter.PersonConverte"/></list></property>
</bean>
  • bean对象的配置,是为了通过工厂bean,构建注册自定义的类型转换器的实例到IOC容器中
  • mvc:annotation-driven 标签的配置是为了数据绑定的过程中,可以调用自定义的的转换服务来补充默认的转换服务,具体的调用过程和工作原理,可以参考
  • ConversionService:Spring 类型转换体系的核心接口,Bean 属性配置及Spring MVC 处理方法入参绑定等场合使用它进行数据的转换
  • ConversionServiceFactoryBean:工厂Bean,借助它的 converts属性,我们可以注册生成一个 ConversionService 到IOC容器里

:annotation-driven 的作用

  • 自动注册RequestMappingHandlerMapping,RequestMappingHandlerAdpater,ExceptionHandlerExceptionResolver
  • 支持使用ConversionService对参数进行类型转换
  • 支持使用@NumberFormat,@DateFormat完成数据格式化
  • 支持使用@Valid注解对请求参数惊醒JSR303校验
  • 支持使用@RequestBody和@ResponseBody注解

创建相关视图

add.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="UTF-8"%>
<html>
<head><title>添加页面</title>
</head>
<body><form action="${pageContext.request.contextPath}/binder/convert"method="post">请输入用户标识:<input type="text" name="id" /><br><input type="submit" value="提交" />
</form>
</body>
</html>

info.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="UTF-8"%>
<html>
<head><title>Title</title>
</head>
<body>查询用户信息如下:
<br/>
<!-- 使用EL表达式取出model中的user信息 -->
姓名:${person.lastname } <br/>
年龄:${person.age } <br/>
生日:${person.birthday } <br/>
工作日期:${person.workDate } <br/>
邮箱:${person.email}
</body>
</html>

内置的格式化转换器

Formatter 与 Converter<S, T> 一样,也是一个可以将一种数据类型转换成另一种数据类型的接口,一般用于对属性对象的输入/输出进行格式化,但从本质上讲依然属于 “类型转换” 的范畴。不同的是,Converter 的源类型可以是任意数据类型,而Formatter 的源类型必须是 String 类型。在 Web 应用中由 HTTP 发送的请求数据到控制器中都是以 String 类型获取,因此在 Web 应用中选择 Formatter 比选择 Converter<S, T> 更加合理。

之所以说,格式化器与转换器本质上相同,是因为在其内部实现中,格式化模块中定义了一个 FormattingConversionService 类,该类同样实现了 ConversionService ,而且扩展了 GenericConversionService,所以它同时具备类型转换和格式化的功能。

同样的,SpringMVC 也为我们提供了一些内置的格式化器,我们可以通过注解调用。

  • NumberFormatter:实现 Number 与 String 之间的解析与格式化。
  • CurrencyFormatter:实现 Number 与 String 之间的解析与格式化(带货币符号)。
  • PercentFormatter:实现 Number 与 String 之间的解析与格式化(带百分数符号)。
  • DateFormatter:实现 Date 与 String 之间的解析与格式化,可以用于标注java.util.Date、java.util.Calendar、java.long.Long等类型

SpringMVC-转换器与格式化相关推荐

  1. 【SSM - SpringMVC篇】06 - SpringMVC转换器,日期格式转换器,后台Date转json,前台json转Date

    文章目录 1. SpringMVC字符串向日期Date格式转换 1.1 通过注解`@DateTimeFormat()`实现日期格式转换. 1.2 编写自定义转换器实现`Converter`,通过重写方 ...

  2. SpringMVC 数据的格式化、JSR 303数据校验和国际化

    SpringMVC 数据的格式化.JSR 303数据校验和国际化 转载于:https://www.cnblogs.com/lusufei/p/7400963.html

  3. 解决 js 对 long 型数据处理丢失精度问题~ 对象映射器和扩展SpringMVC转换器

    大家好,我是一名在算法之路上不断前进的小小程序猿!体会算法之美,领悟算法的智慧~ 希望各位博友走过路过可以给我点个免费的赞,你们的支持是我不断前进的动力!! 加油吧!未来可期!!! 本文介绍的是解决 ...

  4. java学习笔记——springmvc 之 数据自定义转换器 数据格式化 JSR303数据校验返回与接收JSON(@RequestBody 和 @ResponseBody)

    九.数据绑定流程分析 1.提出问题 日期字符串格式的表单参数,提交后转换为Date类型 <!--    解决问题: 1.数据类型转换 2.数据格式 3.数据校验 --> BirthDay ...

  5. SpringMVC(8)——格式化转换器Formatter

    目录 概述 内置的格式化转换器 自定义格式化转换器 创建实体类 创建控制器类 创建自定义格式化转换器类 注册格式化转换器 其他JSP页面 运行效果 概述 SpringMVC框架的Formatter&l ...

  6. SpringMVC日期格式化

    一.关于SpringMVC日期的格式化大概可分为四点 1.@ResponseBody方式返回json的日期格式化 2.ajax方式返回json的日期格式化 3.数据保存时String转Date 4.页 ...

  7. spring 类型转换器_Spring中的类型转换

    spring 类型转换器 以下是一些需要类型转换的简单情况: 情况1. 为了帮助简化bean配置,Spring支持属性值与文本值之间的转换. 每个属性编辑器仅设计用于某些类型的属性. 为了使用它们,我 ...

  8. SpringMVC自动配置

    springboot为SpringMVC配置了自动配置,以下是SpringBoot对SpringMVC的默认配置 org.springframework.boot.autoconfigure.web. ...

  9. java框架之SpringBoot(5)-SpringMVC的自动配置

    本篇文章内容详细可参考官方文档第 29 节. SpringMVC介绍 SpringBoot 非常适合 Web 应用程序开发.可以使用嵌入式 Tomcat,Jetty,Undertow 或 Netty ...

  10. Spring MVC Formatter(数据格式化)详解

    Spring MVC 框架的 Formatter<T> 与 Converter<S,T> 一样,也是一个可以将一种数据类型转换成另一种数据类型的接口.不同的是,Formatte ...

最新文章

  1. pytorch自定义交叉熵损失函数
  2. Python程序设计题解【蓝桥杯官网题库】 DAY15-算法训练
  3. Golang gorouting 并发控制 sync.WaitGroup 介绍与使用
  4. ustc小道消息20211213
  5. matlab swt函数,matlab swt 函数出错
  6. php curl 要安装pear,MacOS 安装pear
  7. go.js节点字体设置
  8. uctf-杂项题目分析
  9. 【推荐】 Neutralizer 安卓上特殊的均衡器
  10. 引用 使用Eclipse生成Java Doc
  11. React中防止事件冒泡:e.stopPropagation()
  12. 【前端优化】在线图片压缩有这4个网站就够了(免费又好用)
  13. 常用网络js链接大全(jQuery、bootstrap、vue、ECharts、easyUI、React、maven、Mybatis、Spring、SpringMVC、Redis)
  14. Yandex域名邮箱逻辑
  15. qt linux不能读写u盘文件,Qt读取U盘文件内容
  16. Python-音乐播放器APP制作
  17. 布尔-施罗德逻辑代数中的公设对应-- 布尔逻辑之六
  18. android photoview github,android – 无法解析com.github.chrisbanes:PhotoView:1.3.1
  19. 18.企业信息化战略与实施
  20. 程序运行无线循环与死循环的区别

热门文章

  1. Windows关于文件句柄数的限制
  2. textarea回车换行的方法
  3. weui学习总结——1、weui表单常用标签
  4. 不带头结点的单链表的创建(头插法和尾插法)
  5. Lombok 插件安装、使用
  6. Eclipse IDE
  7. Drools记录之DRL规则语言
  8. 本地——云服务器文件传输
  9. 一个人生活,如何摆脱孤独提升幸福感?
  10. Unity 角色朝向目标 / 动态转向动画