首页 > 其他 > 详细

验证,数据绑定和类型转换

时间:2020-12-19 15:51:39      阅读:27      评论:0      收藏:0      [点我收藏+]

验证,数据绑定和类型转换

考虑将验证作为业务逻辑是有利有弊,Spring 提供了一种验证(和数据绑定)设计,但并不排除其中任何一个。具体来说,验证不应与网络层绑定,并且应该易于本地化,并且应该可以插入任何可用的验证器。考虑到这些问题,Spring 提供了一个Validator接口,该接口既基本又可以在应用程序的每一层使用。

数据绑定对于使用户 Importing 动态绑定到应用程序(或用于处理用户 Importing 的任何对象)域模型很有用。 Spring 提供了恰当地命名为DataBinder的名称。 ValidatorDataBinder组成了validation程序包,该程序包主要用于但不限于 MVC 框架。

BeanWrapper是 Spring 框架中的一个基本概念,在很多地方都使用过。但是,您可能不需要直接使用BeanWrapper。但是,由于这是参考文档,因此我们认为可能需要进行一些解释。我们将在本章中解释BeanWrapper,因为如果您将要使用它,则在尝试将数据绑定到对象时最有可能使用它。

Spring 的DataBinder和较低级别的BeanWrapper都使用PropertyEditorSupport实现来解析和格式化属性值。 PropertyEditorPropertyEditorSupport接口是 JavaBeans 规范的一部分,本章还将对此进行说明。 Spring 3 引入了core.convert软件包,该软件包提供了常规的类型转换工具,以及用于格式化 UI 字段值的高级“格式”软件包。您可以将这些软件包用作PropertyEditorSupport实现的更简单替代方案。本章还将对它们进行讨论。

JSR-303/JSR-349 Bean 验证

从 4.0 版本开始,Spring 框架支持 Bean 验证 1.0(JSR-303)和 Bean 验证 1.1(JSR-349),以支持设置并使其适应 Spring 的Validator接口。

应用程序可以选择一次全局启用 Bean 验证(如Spring Validation中所述),并将其专用于所有验证需求。

应用程序还可以为每个DataBinder实例注册其他 Spring Validator实例,如配置一个 DataBinder中所述。

3.1. 使用 Spring 的 Validator 接口进行验证

Spring 具有Validator接口,可用于验证对象。 Validator接口通过使用Errors对象工作,因此验证器可以在验证时向Errors对象报告验证失败。

考虑以下小型数据对象的示例:

public class Person {

    private String name;
    private int age;

    // the usual getters and setters...
}

下一个示例通过实现org.springframework.validation.Validator接口的以下两种方法来提供Person类的验证行为:

  • supports(Class):此Validator是否可以验证提供的Class的实例?

  • validate(Object, org.springframework.validation.Errors):验证给定的对象,并在验证错误的情况下,将其注册到给定的Errors对象。

实现Validator非常简单,尤其是当您知道 Spring 框架还提供的ValidationUtils helper 类时。以下示例为Person实例实现Validator

public class PersonValidator implements Validator {

    /**
     * This Validator validates *only* Person instances
     */
    public boolean supports(Class clazz) {
        return Person.class.equals(clazz);
    }

    public void validate(Object obj, Errors e) {
        ValidationUtils.rejectIfEmpty(e, "name", "name.empty");
        Person p = (Person) obj;
        if (p.getAge() < 0) {
            e.rejectValue("age", "negativevalue");
        } else if (p.getAge() > 110) {
            e.rejectValue("age", "too.darn.old");
        }
    }
}

ValidationUtils类上的static rejectIfEmpty(..)方法用于拒绝name属性(如果它是null或空字符串)。  

虽然可以实现单个Validator类来验证丰富对象中的每个嵌套对象,但是最好将每个嵌套类的验证逻辑封装在自己的Validator实现中。一个“丰富”对象的简单示例是一个Customer,它由两个String属性(名字和第二个名称)和一个复杂的Address对象组成。 Address对象可以独立于Customer对象使用,因此已实现了不同的AddressValidator如果希望CustomerValidator重用AddressValidator类中包含的逻辑而不求助于复制和粘贴,则可以在CustomerValidator中依赖注入或实例化AddressValidator,如以下示例所示:  

public class CustomerValidator implements Validator {

    private final Validator addressValidator;

    public CustomerValidator(Validator addressValidator) {
        if (addressValidator == null) {
            throw new IllegalArgumentException("The supplied [Validator] is " +
                "required and must not be null.");
        }
        if (!addressValidator.supports(Address.class)) {
            throw new IllegalArgumentException("The supplied [Validator] must " +
                "support the validation of [Address] instances.");
        }
        this.addressValidator = addressValidator;
    }

    /**
     * This Validator validates Customer instances, and any subclasses of Customer too
     */
    public boolean supports(Class clazz) {
        return Customer.class.isAssignableFrom(clazz);
    }

    public void validate(Object target, Errors errors) {
        ValidationUtils.rejectIfEmptyOrWhitespace(errors, "firstName", "field.required");
        ValidationUtils.rejectIfEmptyOrWhitespace(errors, "surname", "field.required");
        Customer customer = (Customer) target;
        try {
            errors.pushNestedPath("address");
            ValidationUtils.invokeValidator(this.addressValidator, customer.getAddress(), errors);
        } finally {
            errors.popNestedPath();
        }
    }
}

验证错误会报告给传递给验证器的Errors对象。对于 Spring Web MVC,可以使用<spring:bind/>标签检查错误消息,但是也可以自己检查Errors对象。  

3.2. 将代码解析为错误消息

我们介绍了数据绑定和验证。本节介绍与验证错误相对应的输出消息。在preceding section所示的示例中,我们拒绝了nameage字段。如果要使用MessageSource输出错误消息,可以使用拒绝字段时提供的错误代码(在这种情况下为“名称”和“年龄”)进行输出。当您从Errors接口调用(直接或间接使用ValidationUtils类)rejectValue或其他reject方法时,基础实现不仅会注册您传入的代码,还会注册许多其他错误代码。 MessageCodesResolver确定Errors接口寄存器的错误代码。默认情况下,使用DefaultMessageCodesResolver,例如,它不仅使用您提供的代码注册一条消息,而且还注册包含您传递给 reject 方法的字段名称的消息。因此,如果您使用rejectValue("age", "too.darn.old")拒绝字段,除了too.darn.old代码,Spring 还会注册too.darn.old.agetoo.darn.old.age.int(第一个包含字段名称,第二个包含字段类型)。这样做是为了方便开发人员在定位错误消息时提供帮助。

3.3. Bean 操作和 BeanWrapper

org.springframework.beans软件包遵循 JavaBeans 标准。 JavaBean 是具有默认无参数构造函数的类,并且遵循命名约定,其中(例如)名为bingoMadness的属性将具有 setter 方法setBingoMadness(..)和 getter 方法getBingoMadness()

Bean 包中的一个非常重要的类是BeanWrapper接口及其相应的实现(BeanWrapperImpl)。正如从 Javadoc 引用的那样,BeanWrapper提供了以下功能:设置和获取属性值(单独或批量),获取属性 Descriptors 以及查询属性以确定它们是否可读或可写。此外,BeanWrapper还支持嵌套属性,从而可以将子属性上的属性设置为无限深度。 BeanWrapper还支持添加标准 JavaBean PropertyChangeListenersVetoableChangeListeners的能力,而无需在目标类中支持代码。最后但并非最不重要的一点是,BeanWrapper支持设置索引属性。 BeanWrapper通常不直接由应用程序代码使用,而由DataBinderBeanFactory使用。

BeanWrapper的工作方式部分地由其名称表示:它包装一个 bean 以对该 bean 执行操作,例如设置和检索属性。

3.3.1. 设置和获取基本和嵌套属性

设置和获取属性的方法是使用setPropertyValuesetPropertyValuesgetPropertyValuegetPropertyValues方法,这些方法带有一些重载的变体。

 

验证,数据绑定和类型转换

原文:https://www.cnblogs.com/jrkl/p/14159233.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!