Spring Framework 官方文档学习(四)之Validation、Data Binding、Type Conversion

前言

在Spring Framework官方文档中,这三者是放到一起讲的,但没有解释为什么放到一起。大概是默认了读者都是有相关经验的人,但事实并非如此,例如我。好在闷着头看了一遍,又查资料又敲代码,总算明白了。

其实说穿了一文不值,我们用一个例子来解释:

假定,现有一个app,功能是接收你输入的生日,然后显示你的年龄。看起来app只要用当前日期减去你输入的日期就是年龄,应该很简单对吧?可惜事实不是这样的。

这里面有三个问题:

问题一:我们输入的永远是字符串,字符串需要转成日期格式才能被我们的app用使用。--对应 类型转换

问题二:我们输入的字符串转成的日期怎么给app后台逻辑使用? --对应 数据绑定

问题三:人的年龄是有限制的,不能为负数,不能太大(例如超过了200)。 --对应 校验

同样的问题也出现在浏览器与服务器的交互之中,因为请求与响应,大都是被解析成字符串。

现在,你应该已经明白Validation、Data Binding、Type Conversion三者之间的关系了,它们彼此独立,但又互相配合。

前提

在了解更多之前,你应该先知道两个关键的概念:JavaBean 和 Property。

JavaBean是一个简单类,无参构造,命名惯例(SETTER/GETTER) -- 其标准由Oracle提供!详见 JavaBeansJavaBean wiki

SETTER/GETTER 对应的部分称为Property(属性)。

另外,org.springframework.beans 包 遵守Oracle提供的JavaBean标准。但是JavaBean 和 Spring的bean 不是同一个概念!

嗯嗯,有时间研究下JavaBean spec。

概览

现在我们来看看具体的定义以及Spring中提供的工具:

Validation 校验:对Property进行校验。--【谁的Property?JavaBean的!】

Spring提供了Validator接口,可在任意layer使用。

Data Binding 数据绑定:将数据绑定到Property上。--【谁的Property?JavaBean的!】

Spring提供了DataBinder来完成具体的数据绑定工作。

Validator和DataBinder都在org.springframework.validation包中。

Type Conversion 类型转换:将一种类型的对象转成另一种类型的对象,例如String与Date之间。--【谁的类型?Property的!】

Spring提供了PropertyEditors 以及core.convert 包和format 包。后两者是Spring 3 引入的,可以看作PropertyEditor 的替代品,更简单。

注意到没有,这三者其实都是在操作JavaBean的Property。

那么问题又来了,Spring如何操作JavaBean及其Property?答案是通过BeanWrapper接口和其实现BeanWrapperImpl,其内部通过PropertyEditors来解析和格式化Property。

BeanWrapper这个东西是很底层的概念,用户一般不必直接使用它,了解即可。

另,PropertyEditor是JavaBeans specification的一部分!

深入

下面来研究下Spring这些工具的具体用法:

1、Validator,查看源码可知,该接口只有两个方法,supports(Class<?> clazz)用于判断是否支持某类;validate(Object target, Errors errors)则用于校验,如有错误信息则报告给Errors -- 建议配合工具类ValidationUtils来使用。

实现该接口即可定义自己的Validator,代码如下:

[][][][][][] olw

注意,如果是复合类的校验,还可以注入已有的Validator -- 复用、高效。

2、Resolving code to error message

如果我们想要通过MessageSource输出error message,我们会使用之前填入error code。

当我们直接或间接的调用Errors的reject方法时,其实现不仅会注册我们传入的code,同时还会注册一些额外的error code。具体注册的error code是由MessageCodesResolver决定的。

默认情况下,会使用DefaultMessageCodesResolver,它不仅注册了你传入的code,还注册了字段名!

例如,你使用rejectValue(”age”, ”too.darn.old”),不仅会注册 ”too.darn.old”,还会注册 ”too.darn.old.age” 和 ”too.darn.old.age.int”。

更多策略见MessageCodesResolver和DefaultMessageCodesResolver的JavaDoc。

上面这两个,怎么说呢,没有涉及到反射之类的。这与下面要说的有所不同,提前说一下。

3、BeanWrapper,位于org.springframework.beans包中。

根据其JavaDoc可知,BeanWrapper提供的功能包括:set/get property values (单个/多个), get property descriptor, 以及查询判断property是可读的还是可写的。还支持nested property。还支持添加standard JavaBeans PropertyChangeListeners and VetoableChangeListeners,无需在目标类中编码(这不是废话么,类似aop的监听器)。最后还支持the setting of indexed properties。

BeanWrapper一般不直接用在代码中,而是用在DataBinder 和 BeanFactory 中。

另外,顾名思义,BeanWrapper的工作方式是wrap一个bean以执行操作。

下面讲一下其具体功能:

3.1、Setting and getting basic and nested properties

就是set/get property values(基本的和嵌套的),通过BeanWrapper的setPropertyValues()和getPropertyValues()方法完成 -- 详见JavaDoc。

这里需要重点了解的就是几个约定,例子如下:

Expression 解释
name Property name。
account.name nested property name of the property account
account[2] the 3rd element of the indexed property account
account[COMPANYNAME] map

这一小节不提供源码阅读,因为我们基本用不到它。仅作了解即可。

3.2、内建的PropertyEditor实现

必须再说一遍,PropertyEditor是JavaBeans specification的一部分! 全限定名:java.beans.PropertyEditor。

其本身是个接口(就是抽象啦),所以需要提供实现以供使用。于是Spring就提供了一堆实现。

时间: 10-09

Spring Framework 官方文档学习(四)之Validation、Data Binding、Type Conversion的相关文章

Spring Framework 官方文档学习心得

到目前为止,已经看了一百页,感受良多.再次感慨下,如果想使用,那可以看视频或者找例子,但如果想深入理解,最好还是看官方文档. 其一,对容器有了新的认识. 第二,对lifecycle有了新的认识. 第三,对版本演化有了认识. 第四,种种功能,各司其职. 以上只是泛泛而言,稍后在本文总结一下.初步设想是把一些基本接口的功能.层次以及彼此的关系罗列一下.同时兼顾版本的演化,简述下相应功能的历史,最好是画一张图. 以BeanPostProcessor接口为例,当configuration metadat

Spring Framework 官方文档学习(三)之Resource

起因 标准JDK中使用 java.net.URL 来处理资源,但有很多不足,例如不能限定classpath,不能限定 ServletContext 路径. 所以,Spring提供了 Resource 接口. 注意,Spring提供的Resource抽象不是要取代(replace)标准JDK中的功能,而是尽可能的封装(wrap)它. 例如,UrlResource 就封装了一个URL. 介绍 Spring内置了很多Resource实现,以用于不同情况.如下: UrlResource ,ClassPa

Spring 4 官方文档学习(十二)View技术

1.介绍 Spring 有很多优越的地方,其中一个就是将view技术与MVC框架的其他部分相隔离.例如,在JSP存在的情况下使用Groovy Markup Templates 还是使用Thymeleaf,仅仅是一个配置问题. 本章覆盖了主要的view技术,嗯嗯,可以与Spring结合的那些,并简明的说明了如何增加新的view技术. 本章假定你已经熟悉了Spring 4 官方文档学习(十一)Web MVC 框架之resolving views 解析视图 -- 它覆盖了views如何耦合到MVC框架

Spring 4 官方文档学习(十一)Web MVC 框架之resolving views 解析视图

接前面的Spring 4 官方文档学习(十一)Web MVC 框架,那篇太长,故另起一篇. 针对web应用的所有的MVC框架,都会提供一种呈现views的方式.Spring提供了view resolvers,可以让你在浏览器中render model,而不必绑定到某种特定的view技术上.开箱即用,例如,Spring可以让你使用JSPs.Velocity目标和XSLT views.See Chapter 23, View technologies for a discussion of how

Spring JMS 官方文档学习

最后部分的XML懒得写了,因为个人更倾向于JavaConfig形式. 为知笔记版本见这里,带格式~ 做了一个小demo,放到码云上了,有兴趣的点我. 说明:需要先了解下JMS的基础知识. 1.介绍 Spring 提供了一个JMS集成框架,简化了JMS API的使用,类似于Spring提供的JDBC API集成. JMS可以粗略地划分成两大功能区域,就是消息的生产(production)和消费(consumption).JmsTemplate 用于消息的生产和同步的消息接收.对于异步消息接收,类似

Spring 4 官方文档学习(十一)Web MVC 框架之配置Spring MVC

在前面的文档中讲解了Spring MVC的特殊beans,以及DispatcherServlet使用的默认实现.在本部分,你会学习两种额外的方式来配置Spring MVC.分别是:MVC Java config 和  MVC XML namespace. 原文: Section 22.2.1, "Special Bean Types In the WebApplicationContext" and Section 22.2.2, "Default DispatcherSer

Spring 4 官方文档学习(五)核心技术之SpEL

1.介绍 SpEL支持在runtime 查询.操作对象图. 2.功能概览 英文 中文 Literal expressions 字面值表达式 Boolean and relational operators 布尔和关系操作符 Regular expressions  正则表达式 Class expressions 类表达式 Accessing properties, arrays, lists, maps 访问properties.arrays.lists.maps Method invocati

Spring 4 官方文档学习(十三)集成其他web框架

重点是通用配置,非常建议看一下!有助于理解Spring的ApplicationContext与Servlet Container的关系! 1.介绍 Spring Web Flow SWF目标是成为web应用页面flow管理的最佳解决方案. SWF集成了现有的框架,如Spring MVC 和 JSF,在Servlet和Portlet环境中.如果你有一个(或多个)业务处理,且 受益于会话模型而非纯请求模型,那SWF可能就是解决方案. SWF允许捕获逻辑页面flows,并将其作为自包容的模块 -- 可

Spring 4 官方文档学习(十一)Web MVC 框架之HTTP caching support

一个良好的HTTP缓存策略可以显著地增进web应用的性能和其客户端的体验.主要使用"Cache-Control" HTTP response header来完成,配合conditional headers例如"Last-Modified"和"ETag". "Cache-Control" HTTP response header 会建议私有缓存(如浏览器)和公开缓存(如代理)如何缓存HTTP response以供将来复用. &q