b spring之Validator &Error Messages& & BeanWrapper--Spring类型校验和错误处理


Spring 使用Validator接口来在 应用的每一层完成数据的验证。
Data binding(数据绑定),可以动态的注入数据,Spring使用DataBinder类。Validator和databinder组成了validation包。
BeanWrapper是一个Lowel的接口,一般不会用到。
Spring的DataBinder和BeanWrapper都使用PropertyEditorSupport的实现去解析和格式化属性值。PropertyEditorPropertyEditorSupport都是javaBeans细节的一部分。
SPring 3 介绍了core.convert包去提供通用的类型转化

JSR-303和JSR Bean Validation

3.1 使用Validatior 接口进行校验

Validator使用一个Error对象来反馈失败的信息。
示例
b spring之Validator &Error Messages& & BeanWrapper--Spring类型校验和错误处理
下面的例子提供了对Person类的验证,通过使用
org.springframework.validation.Validator接口的两个方法。

  • support(Class):验证,该Validator类是否支持对该示例的验证
  • validate(Object, org.springframework.validation.Errors)
    验证呗被给予的对象,错误时返回Errors对象。

b spring之Validator &Error Messages& & BeanWrapper--Spring类型校验和错误处理
示例中 ValidationUtils.rejectIfEmpty来验证String为非null。
类似一个装饰器模式,你可以在validator中包含validator来注入式的验证
b spring之Validator &Error Messages& & BeanWrapper--Spring类型校验和错误处理
invokerValidator注入式的调用

3.2 解决Error Messages

关于错误的输出和输出消息的绑定,可以选择使用MessageSource。当你调用ValidationUtils的reject方法或者rejectValue(或者直接使用ValidationUtils类的时候),一堆关于错误信息的处理就注册到了Spring上去。MessageCodeResolver会识别注册上来的消息方法

  • 直接注册:rejectValue(“age”,“too.darn.old”)。把信息注册上去,出错时会用到

3.3 Bean的处理和BeanWrapper

javabean的默认形式是提供一个无参数的构造器,并且对属性具备getter和setter方法。
BeanWrapper和BeanWrapperImpl就为属性提供了setter和getter等的包装。除此之外好还支持标准的PropertyChangeListenersVetoableChangeListeners,也提供了对属性index的支持。
一般不会直接使用,但是DataBinder和BeanFactory有大量的使用

3.31 Setting 和 Getting Basic and 嵌套的Properties

默认具备的方法
b spring之Validator &Error Messages& & BeanWrapper--Spring类型校验和错误处理
示例:包含嵌套
b spring之Validator &Error Messages& & BeanWrapper--Spring类型校验和错误处理
通用的设置方法
b spring之Validator &Error Messages& & BeanWrapper--Spring类型校验和错误处理

3.3.2 内置的PropertyEditor实现

spring使用 PropertyEdior来在Object和String之前互相转化。例如:Date2019-14-09的转化。这个实现可以通过注册自定义的java.beans.PropertyEditor类。
关于注册基于BeanWrapper或者IoC container的编辑器,可以看the javadoc of the java.beans package from Oracle
两个在Spring中编辑属性的办法

  • 使用PropertyEditor在beans中设置属性。可以在xml中声明
  • 在Spring MVC中解析HTTP请求时使用各种类型的PropertyEditor,可以在CommandController手工绑定
    b spring之Validator &Error Messages& & BeanWrapper--Spring类型校验和错误处理

PropertyEdiorManager

Spring使用PropertyEdiorManager设置搜索路径来搜索可能用到的属性编辑器。这个路径也包含了sun.bean.editors–PropertyEditor 的实现 for Font, Color等。自动加载要求类和Editor在同一路径下,名称有要求如图
b spring之Validator &Error Messages& & BeanWrapper--Spring类型校验和错误处理
也可事使用JavaBeans的标注组件去严格注册一个
b spring之Validator &Error Messages& & BeanWrapper--Spring类型校验和错误处理

Registering Additional Custom PropertyEditor Implementations

当将bean属性设置为字符串值时,Spring IoC容器最终使用标准JavaBeans PropertyEditor实现将这些字符串转换为属性的复杂类型。 Spring预注册了许多自定义的PropertyEditor实现(例如,将表示为字符串的类名称转换为Class对象)。此外,Java的标准JavaBeans PropertyEditor查找机制允许适当地命名类的PropertyEditor,并将其与提供支持的类放在同一包中,以便可以自动找到它。

如果需要注册其他自定义PropertyEditor,则可以使用几种机制。最手动的方法(通常不方便或不建议使用)是使用ConfigurableBeanFactory接口的registerCustomEditor()方法,假设您有BeanFactory引用。另一种(稍微方便些)的机制是使用一种称为CustomEditorConfigurer的特殊bean工厂后处理器。尽管可以将Bean工厂后处理器与BeanFactory实现一起使用,但CustomEditorConfigurer具有嵌套的属性设置,因此我们强烈建议您将其与ApplicationContext一起使用,在其中可以将其以与其他任何Bean相似的方式进行部署,并且可以在任何位置进行部署。自动检测并应用。

请注意,所有bean工厂和应用程序上下文通过使用BeanWrapper处理属性转换,都会自动使用许多内置的属性编辑器。上一节列出了BeanWrapper注册的标准属性编辑器。此外,ApplicationContext还以适合特定应用程序上下文类型的方式重写或添加其他编辑器,以处理资源查找。

标准JavaBeans PropertyEditor实例用于将表示为字符串的属性值转换为该属性的实际复杂类型。可以使用bean工厂的后处理器CustomEditorConfigurer来方便地将对其他PropertyEditor实例的支持添加到ApplicationContext。

考虑以下示例,该示例定义了一个名为ExoticType的用户类和另一个名为DependsOnExoticType的类,该类需要将ExoticType设置为属性:
b spring之Validator &Error Messages& & BeanWrapper--Spring类型校验和错误处理
正确设置之后,我们希望能够将type属性分配为字符串,PropertyEditor会将其转换为实际的ExoticType实例。以下bean定义显示了如何建立这种关系:
b spring之Validator &Error Messages& & BeanWrapper--Spring类型校验和错误处理
注册到CustomEditorConfigurer
b spring之Validator &Error Messages& & BeanWrapper--Spring类型校验和错误处理

Using PropertyEditorRegistrar

使用Spring容器注册属性编辑器的另一种机制是创建和使用PropertyEditorRegistrar。当需要在几种不同情况下使用同一组属性编辑器时,此接口特别有用。您可以编写相应的注册商,并在每种情况下重复使用它。 PropertyEditorRegistrar实例与一个称为PropertyEditorRegistry的接口一起工作,该接口由Spring BeanWrapper(和DataBinder)实现。当与CustomEditorConfigurer(在此描述)结合使用时,PropertyEditorRegistrar实例特别方便,该实例公开了名为setPropertyEditorRegistrars(…)的属性。以这种方式添加到CustomEditorConfigurer中的PropertyEditorRegistrar实例可以轻松地与DataBinder和Spring MVC控制器共享。此外,它避免了在自定义编辑器上进行同步的需求:希望PropertyEditorRegistrar为每次创建bean的尝试创建新的PropertyEditor实例。

以下示例说明如何创建自己的PropertyEditorRegistrar实现:
b spring之Validator &Error Messages& & BeanWrapper--Spring类型校验和错误处理
另请参见org.springframework.beans.support.ResourceEditorRegistrar以获取示例PropertyEditorRegistrar实现。请注意,在实现registerCustomEditors(…)方法时,它如何创建每个属性编辑器的新实例。

下一个示例显示了如何配置CustomEditorConfigurer并将其注入我们的CustomPropertyEditorRegistrar的实例:
b spring之Validator &Error Messages& & BeanWrapper--Spring类型校验和错误处理
最后(对于使用Spring的MVC网络框架的读者来说,与本章的重点有所偏离),将PropertyEditorRegistrars与数据绑定控制器(例如SimpleFormController)结合使用会非常方便。下面的示例在initBinder(…)方法的实现中使用PropertyEditorRegistrar:
b spring之Validator &Error Messages& & BeanWrapper--Spring类型校验和错误处理
这种样式的PropertyEditor注册可以导致代码简洁(initBinder(…)的实现只有一行长),并且可以将通用的PropertyEditor注册代码封装在一个类中,然后根据需要在许多Controller之间共享。