验证、数据绑定和类型转换
将验证视为业务逻辑有其优缺点,而 Spring 提供了一种验证和数据绑定的设计,这种设计并不排除其中的任何一个。具体来说,验证不应与 Web 层绑定,并且应该易于本地化,同时应该可以插入任何可用的验证器。考虑到这些问题,Spring 提供了一个 Validator
合约,它既基本又可以在应用程序的每一层中使用。
数据绑定对于让用户输入动态绑定到应用程序的领域模型(或您用来处理用户输入的任何对象)非常有用。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
实例,如 Configuring a DataBinder 中所述,这对于插入自定义验证逻辑非常有用。
章节摘要
📄️ 使用 Spring 的 Validator 接口进行验证
Spring 提供了一个 Validator 接口,可以用来验证对象。Validator 接口通过使用 Errors 对象来工作,因此在验证过程中,验证器可以将验证失败报告给 Errors 对象。
📄️ 数据绑定
数据绑定对于将用户输入绑定到目标对象非常有用,其中用户输入是一个以属性路径为键的映射,遵循 JavaBeans 约定。DataBinder 是支持此功能的主要类,它提供了两种方式来绑定用户输入:
📄️ 解析代码为错误信息
我们已经讨论了数据绑定和验证。本节介绍如何输出与验证错误对应的消息。在前一节中展示的示例中,我们拒绝了 name 和 age 字段。如果我们想使用 MessageSource 输出错误消息,可以通过我们在拒绝字段时提供的错误代码(在本例中是 'name' 和 'age')来实现。当你调用(直接或间接地,通过例如 ValidationUtils 类)rejectValue 或 Errors 接口中的其他拒绝方法时,底层实现不仅会注册你传入的代码,还会注册许多其他错误代码。MessageCodesResolver 决定了 Errors 接口注册哪些错误代码。默认情况下,使用 DefaultMessageCodesResolver,它不仅注册你提供的代码的消息,还注册包含你传递给拒绝方法的字段名称的消息。例如,如果你使用 rejectValue(\"age\", \"too.darn.old\") 拒绝一个字段,除了 too.darn.old 代码外,Spring 还会注册 too.darn.old.age 和 too.darn.old.age.int(第一个包含字段名称,第二个包含字段的类型)。这样做是为了方便开发人员在定位错误消息时使用。
📄️ Spring 类型转换
core.convert 包提供了一个通用的类型转换系统。该系统定义了一个 SPI 来实现类型转换逻辑,并提供了一个 API 以在运行时执行类型转换。在 Spring 容器中,你可以使用这个系统作为 PropertyEditor 实现的替代方案,将外部化的 bean 属性值字符串转换为所需的属性类型。你也可以在应用程序中任何需要类型转换的地方使用这个公共 API。
📄️ 春季字段格式化
正如前一节所讨论的,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 验证
Spring 框架为 Java Bean Validation API 提供支持。