验证、数据绑定和类型转换
将验证视为业务逻辑有其优缺点,而Spring提供了一种验证和数据绑定的设计,这种设计并不排除这两种观点中的任何一种。具体来说,验证不应与Web层绑定,且应易于进行本地化;同时,应该能够插入任何可用的验证器。考虑到这些因素,Spring提供了一个Validator接口,该接口既基础又非常适用于应用程序的每一层。
数据绑定(Data Binding)有助于将用户输入动态地与应用程序的领域模型(或者用于处理用户输入的任何对象)关联起来。Spring提供了名为DataBinder的工具来实现这一功能。Validator和DataBinder共同组成了validation包,该包主要应用于(但不限于)Web层。
BeanWrapper是Spring框架中的一个基本概念,在很多地方都会用到。然而,你可能并不需要直接使用BeanWrapper。不过,由于这是参考文档,我们认为还是有必要做一些解释。在这一章中,我们会对BeanWrapper进行说明,因为如果你确实需要使用它的话,很可能是在尝试将数据绑定到对象的时候。
Spring的DataBinder和更低层的BeanWrapper都使用PropertyEditorSupport实现来解析和格式化属性值。PropertyEditor和PropertyEditorSupport类型是JavaBeans规范的一部分,在本章中也有介绍。Spring的core.convert包提供了一般的类型转换功能,还有一个更高级的format包用于格式化UI字段值。你可以使用这些包作为PropertyEditorSupport实现的简化替代方案。这些内容在本章也会有讨论。
Spring 通过设置基础设施和适配器来支持 Java Bean Validation,这些适配器与 Spring 自带的 Validator 接口相匹配。应用程序可以像 Java Bean Validation 中描述的那样全局启用 Bean Validation,并将其专门用于所有验证需求。在 Web 层,应用程序还可以根据每个 DataBinder 注册控制器本地的 Spring Validator 实例,如 配置 DataBinder 中所述,这对于插入自定义验证逻辑非常有用。
部分总结
使用Spring的Validator接口进行验证
Spring 提供了一个 Validator 接口,你可以使用它来验证对象。Validator 接口通过使用 Errors 对象来工作,这样在验证过程中,验证器可以将验证失败的信息报告给 Errors 对象。
数据绑定
数据绑定对于将用户输入与目标对象进行绑定非常有用,其中用户输入是一个以属性路径作为键的映射(map),遵循JavaBeans的约定。DataBinder是支持这一功能的主要类,它提供了两种方式来绑定用户输入:
将错误代码解析为错误信息
我们已经讨论了数据绑定和验证。本节将介绍如何输出与验证错误相对应的消息。在前一节展示的示例中,我们拒绝了“name”和“age”这两个字段。如果我们想使用MessageSource来输出错误消息,就可以通过我们在拒绝字段时提供的错误代码来实现(本例中为“name”和“age”)。当你调用rejectValue方法或Errors接口中的其他拒绝方法(无论是直接调用还是间接调用,例如通过ValidationUtils类)时,底层实现不仅会注册你传递的错误代码,还会注册一些额外的错误代码。MessageCodesResolver负责确定Errors接口所注册的错误代码。默认情况下,使用的是DefaultMessageCodesResolver,它不仅会注册你提供的错误代码,还会注册包含字段名称的消息(这些消息中也包含传递给reject方法的字段名称)。因此,如果你使用rejectValue(\"age\", \"too.darn.old\")来拒绝一个字段,除了“too.darn.old”这个错误代码外,Spring还会注册“too.darn.old.age”和“too.darn.old.age.int”这两个错误代码(前者包含字段名称,后者包含字段类型)。这样做的目的是为了方便开发者查看错误信息。
Spring类型转换
core.convert包提供了一个通用的类型转换系统。该系统定义了一个SPI(Service Provider Interface)来实现类型转换逻辑,以及一个API来在运行时执行类型转换。在Spring容器内部,你可以使用这个系统作为PropertyEditor实现的替代方案,将外部化的bean属性值字符串转换为所需的属性类型。你也可以在应用程序中任何需要类型转换的地方使用这个公共API。
Spring字段格式化
如前一节所讨论的,core.convert是一个通用的类型转换系统。它提供了一个统一的ConversionService API,以及一个强类型的Converter SPI,用于实现从一种类型到另一种类型的转换逻辑。Spring容器使用这个系统来绑定bean属性的值。此外,Spring表达式语言(SpEL)和DataBinder也使用这个系统来绑定字段值。例如,当SpEL需要将Short强制转换为Long以完成expression.setValue(Object bean, Object value)的操作时,core.convert系统会执行这种强制转换。
配置全局日期和时间格式
默认情况下,未使用 @DateTimeFormat 注解的日期和时间字段会使用 DateFormat.SHORT 格式从字符串进行转换。如果你有特殊需求,可以定义自己的全局格式来更改这一设置。
Java Bean Validation
Spring框架提供了对Java Bean Validation API的支持。