文章目录

  • 一、Overview
  • 二、Validation by Using Spring’s Validator Interface(使用 Spring 的 Validator 接口进行验证)
  • 三、Resolving Codes to Error Messages(将代码解析为错误信息)
  • 四、Bean Manipulation and the BeanWrapper(Bean 操作和BeanWrapper)
    • 1、Setting and Getting Basic and Nested Properties(设置和获取基本属性和内嵌属性)
    • 2、Built-in PropertyEditor Implementations(内置属性编辑器实现)

生词汇总:

  • tied to ------------------------ 绑定,栓
  • eminently ------------------- 突出地
  • aptly ------------------------- 恰如其分地
  • apart from ----------------- 除了
  • handly ---------------------- 轻便的
  • Last but not least ------------- 最后但也重要的

一、Overview

There are pros and cons for considering validation as business logic,and Spring offers a design for validation that does not exclude either one of them.Specifically, validation should not be tied to the web tier and should be easy to localize, and it should be possible to plug in any available validator. Considering these concerns, Spring provides a Validator contract that is both basic and eminently usable in every layer of an application.

将验证视为业务逻辑有利有弊,Spring 提供的验证设计不排除其中任何一个。具体来说,验证不应该绑定到 Web 层,并且应该易于本地化,以及应该可以插入任何可用的验证器。考虑到这些关注点,Spring 提供了一个 Validator 契约,它在应用程序的每一层中既基本又非常有用。

Data binding is useful for letting user input be dynamically bound to the domain model of an application (or whatever objects you use to process user input). Spring provides the aptly named DataBinder to do exactly that. The Validator and the DataBinder make up the validation package, which is primarily used in but not limited to the web layer.

数据绑定对于让用户输入动态绑定到应用程序的域模型(也就是实体类,或用于处理用户输入的任何对象)非常有用。Spring提供合适的命名DataBinder来具体处理。Validator和DataBinder组成了validation包,主要用于web层但不限于web层。

The BeanWrapper is a fundamental concept in the Spring Framework and is used in a lot of places. However, you probably do not need to use the BeanWrapper directly. Because this is reference documentation, .

BeanWrapper是spring框架中的一个基本概念,并且被用于许多地方。然而,你可能不需要直接使用BeanWrapper,因为这是参考文档。

二、Validation by Using Spring’s Validator Interface(使用 Spring 的 Validator 接口进行验证)

Spring features a Validator interface that you can use to validate objects. The Validator interface works by using an Errors object so that, while validating, validators can report validation failures to the Errors object.The following example of a small data object:

Spring Validator接口提供校验对象的功能,Validator接口通过使用一个Errors对象工作,当校验时,Validator能够将校验失败报告给Errors对象。以下是一个普通的数据对象:

public class Person {private String name;private int age;// the usual getters and setters...
}

The next example provides validation behavior for the Person class by implementing the following two methods of the org.springframework.validation.Validator interface:

  • supports(Class): Can this Validator validate instances of the supplied Class?
  • validate(Object, org.springframework.validation.Errors): Validates the given object and, in case of validation errors, registers those with the given Errors object.

Implementing a Validator is fairly straightforward, especially when you know of the ValidationUtils helper class that the Spring Framework also provides. The following example implements Validator for Person instances:

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

  • supports(Class):判断校验器是否能对指定类型进行校验;
  • validate(Object,org.springframework.validation.Errors): 验证给定的对象,并在验证错误的情况下使用给定的 Errors 对象注册这些对象。

实现 Validator 相当简单,尤其是当你知道 Spring Framework 还提供了 ValidationUtils 帮助程序类时。以下示例为 Person 实例实现了 Validator:

public class PersonValidator implements Validator {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");}   }public static void main(String[] args) {Person person= new Person();person.setName("");person.setAge(111);PersonValidator validator = new PersonValidator ();DataBinder dataBinder = new DataBinder(person);dataBinder.setValidator(validator);dataBinder.validate();BindingResult result = dataBinder.getBindingResult();System.out.println("results:"+ result);}//执行main函数将输出results:org.springframework.validation.BeanPropertyBindingResult: 2 errors
Field error in object 'target' on field 'name': rejected value []; codes [name.empty.target.name,name.empty.name,name.empty.java.lang.String,name.empty]; arguments []; default message [null]
Field error in object 'target' on field 'age': rejected value [111]; codes [too.darn.old.target.age,too.darn.old.age,too.darn.old.int,too.darn.old]; arguments []; default message [null]
}

The static rejectIfEmpty(…) method on the ValidationUtils class is used to reject the name property if it is null or the empty string.While it is certainly possible to implement a single Validator class to validate each of the nested objects in a rich object, it may be better to encapsulate the validation logic for each nested class of object in its own Validator implementation. A simple example of a “rich” object would be a Customer that is composed of two String properties (a first and a second name) and a complex Address object. Address objects may be used independently of Customer objects, so a distinct AddressValidator has been implemented. If you want your CustomerValidator to reuse the logic contained within the AddressValidator class without resorting to copy-and-paste, you can dependency-inject or instantiate an AddressValidator within your CustomerValidator, as the following example shows:

ValidationUtils 类上的静态 rejectIfEmpty(…) 方法用于拒绝 name 属性为 null 或空字符串。可以实现用单个 Validator 类来验证富对象中的每个嵌套对象,并将每个嵌套对象类的验证逻辑封装在其自己的 Validator 实现中。“丰富”对象的一个​​简单示例是由两个 String 属性(第一个和第二个名称)和一个复杂的 Address 对象组成的 Customer。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.calss)){throw new IllegalArgumentException("The supplied Validator must support the validation of Address instance");}this.addressValidator = addressValidator;}public boolean supports(Class clazz){return Customer.class.isAssignableFrom(clazz);}public void validate(Object target,Errors errors){ValidatorUtils.rejectIfEmptyOrWhitespace(errors,"firstName","field.required");ValidatorUtils.rejectIfEmptyOrWhitespace(errors,"surname","field.required");Customer customer = (Customer)target;try{errors.pushNestedPath("address");ValidatorUtils.invokeValidator(this.addressValidator,customer.getAddress(),  errors);} finally{errors.popNestedPath();}
}

三、Resolving Codes to Error Messages(将代码解析为错误信息)

We covered databinding and validation.This Section covers outputting messages that correspond to validation errors.In the example shown in the preceding section,we rejected the name and age fields.If we want to output the error messages by using a MessageSource,we can do so using the error code we provide when rejecting the field(‘name’ and ‘age’ in this case).When you call rejectValue or one of the other reject methods from the Errors interface,the underlying implementation not only registers the code you passed in but also registers a number of additional error codes.The MessageCodeResolver determines which error codes the Errors interface registers.By default,the DefaultMessageCodesResolver is used,which not only registers a message with the code you gave but also registers message that include the field name you passed to the reject method.So,if you reject a field by using rejectValue(“age”,“too.darn.old”),apart from the too.darn.old code,Spring also registers too.darn.cold.age and too.darn.old.age.int.This is done as a convenience to aid developers when targeting error messages.

在前面我们讲解了数据绑定和校验,本部分将关注于输出与校验错误相对应的消息。在上一节的例子中,我们拒绝了姓名和年龄字段。如果我们想通过一个MessageSource输出错误消息,我们可以在拒绝字段(本例中是name和age)时提供相应的错误代码。当你调用Errors接口的rejectValue方法或其他reject方法时,默认的实现不仅会注册你传递的错误代码也会注册许多其他的错误代码。MessageCodeResolver 决定Errors注册哪些错误代码。默认情况下,使用的是DefaultMessageCodesResolver ,该Resolver不仅注册你提供的错误代码,也注册在reject方法中相应字段的错误代码。所以,如果你使用rejectValue(“age”,“too.darn.old”)拒绝age字段,除了代码too.darn.old,Spring也将注册too.darn.cold.age和too.darn.cold.age.int。这样做是为了方便开发人员在定位错误消息时提供帮助。

四、Bean Manipulation and the BeanWrapper(Bean 操作和BeanWrapper)

One quite important class in the beans package is the BeanWrapper interface and its corresponding implementation (BeanWrapperImpl). As quoted from the javadoc, the BeanWrapper offers functionality to set and get property values (individually or in bulk), get property descriptors, and query properties to determine if they are readable or writable. Also, the BeanWrapper offers support for nested properties, enabling the setting of properties on sub-properties to an unlimited depth. The BeanWrapper also supports the ability to add standard JavaBeans PropertyChangeListeners and VetoableChangeListeners, without the need for supporting code in the target class. Last but not least, the BeanWrapper provides support for setting indexed properties. The BeanWrapper usually is not used by application code directly but is used by the DataBinder and the BeanFactory.

在beans包中一个非常重要的类就是BeanWrapper接口和它的相关实现。正如javadoc中所描述的,BeanWrapper提供设置和获取属性值,获取属性相关描述信息以及查询属性是否存在等功能。同时,BeanWrapper提供支持内嵌属性,能够设置属性中的属性。BeanWrapper也支持添加标准JavaBeans PropertyChangeListeners 和VetoableChangeListeners的功能,不需要目标类中的支持代码。最后但也重要的是,BeanWrapper提供设置索引属性的支持。BeanWrapper通常不仅在应用程序中直接使用,也用于DataBinder和BeanFactory中。

1、Setting and Getting Basic and Nested Properties(设置和获取基本属性和内嵌属性)

Setting and getting properties is done through the setPropertyValue and getPropertyValue overloaded method variants of BeanWrapper. The following two example classes use the BeanWrapper to get and set properties:

设置和获取属性是通过 BeanWrapper 的 setPropertyValue 和 getPropertyValue 重载方法变体完成的。以下两个示例类使用 BeanWrapper 来获取和设置属性:

public class Company {private String name;private Employee managingDirector;public String getName() {return this.name;}public void setName(String name) {this.name = name;}public Employee getManagingDirector() {return this.managingDirector;}public void setManagingDirector(Employee managingDirector) {this.managingDirector = managingDirector;}
}
public class Employee {private String name;private float salary;public String getName() {return this.name;}public void setName(String name) {this.name = name;}public float getSalary() {return salary;}public void setSalary(float salary) {this.salary = salary;}
}
public class TestClass{public static void main(String[] args){BeanWrapper company  = new BeanWrapperImpl(new Company());// 设置company的 name属性company.setPropertyValue("name","Some Company Inc.");// 也可以这样设置PropertyValue value = new PropertyValue("name","Some Company Inc");company.setPropertyValue(value);// 好的,让我们创建员工并将其绑定到公司:BeanWrapper jim = new BeanWrapperImpl(new Employee());jim.setPropertyValue("name","Jim Stravinsky");jim.setPropertyValue("salary", 8000.00);company.setPropertyValue("managingDirector",jim.getWrappedInstance());// 获取属性值Float salary = (Float)company.getPropertyValue("managingDirector.salary");}
}

2、Built-in PropertyEditor Implementations(内置属性编辑器实现)

Spring uses the concept of a PropertyEditor to effect the conversion between an object and a String.It can be handly to represent properties in a different way than the object itself.For example,a Date can be represented in a human readable way(as the String: ‘2007-14-09’),while we can still convert the human readable form back to the original date(or,even better,convert any date entered in a human readable form back to Date objects).This behavior can be achieved by registering custom editors of type java.beans.PropertyEditor.Registring custom editors on a BeanWrapper or,alternatively,in a specific Ioc container(as mentioned in the previous chapter),gives it the knowledge of how to convert properties to the desired type.

Spring 使用 PropertyEditor 的概念来实现对象和字符串之间的转换。以与对象本身不同的方式来表示属性可能很方便。例如,一个Date可以表示为人们易于阅读的形式(比如字符串:2007-14-09),而且我们也可以将其转换回原始的Date类型。可以通过注册相应的editor来实现。在 BeanWrapper 上注册自定义编辑器,或者在特定的 Ioc 容器中(如前一章所述),让它知道如何将属性转换为所需的类型。

A couple of examples where property editing is used in Spring:

在 Spring 中使用属性编辑的一对示例:

  • Setting properties on beans is done by using PropertyEditor implementations.When you use String as the value of a property of some bean that you declare in an XML file,Spring uses ClassEditor to try to resolve the parameter to a Class object.
  • Parsing HTTP request parameters in Spring’s MVC framework is done by using all kinds of PropertyEditor implementations that you can manually bind in all subclasses of the CommandController.
  • 在bean创建后通过PropertyEditor实现类设置属性。当你在XMl配置文件中使用字符串来表示属性值时,Spring会使用ClassEditor来尝试将其解析为类对象。
    在SpringMVC中使用各种类型的PropertyEditor实现来解析Http请求参数,你可以在CommandController的所有子类中手动绑定。

Spring has a number of built-in PropertyEditor implementations to make life easy. They are all located in the org.springframework.beans.propertyeditors package. Most, (but not all, as indicated in the following table) are, by default, registered by BeanWrapperImpl. The following table describes the various PropertyEditor implementations that Spring provides:

Spring 有许多内置的 PropertyEditor 实现来简化工作。它们都位于 org.springframework.beans.propertyeditors 包中。大多数(但不是全部,如下表所示)默认由 BeanWrapperImpl 注册。下表描述了 Spring 提供的各种 PropertyEditor 实现:

Class Explanation
ByteArrayPropertyEditor Editor for byte arrays. Converts strings to their corresponding byte representations. Registered by default by BeanWrapperImpl.(字节数组的编辑器。将字符串转换为其相应的字节表示。由 BeanWrapperImpl 默认注册。)
ClassEditor Parses Strings that represent classes to actual classes and vice-versa. When a class is not found, an IllegalArgumentException is thrown. By default, registered by BeanWrapperImpl.(将代表类的字符串解析为实际类,反之亦然。如果找不到类,则会抛出 IllegalArgumentException。默认情况下,由 BeanWrapperImpl 注册。)
CustomBooleanEditor Customizable property editor for Boolean properties. By default, registered by BeanWrapperImpl but can be overridden by registering a custom instance of it as a custom editor.(布尔属性的可定制属性编辑器。默认情况下,由 BeanWrapperImpl 注册,但可以通过将其自定义实例注册为自定义编辑器来覆盖。)
CustomCollectionEditor Property editor for collections, converting any source Collection to a given target Collection type.(集合的属性编辑器,将任何源集合转换为给定的目标集合类型。)
CustomDateEditor Customizable property editor for java.util.Date, supporting a custom DateFormat. NOT registered by default. Must be user-registered with the appropriate format as needed.(java.util.Date 的可自定义属性编辑器,支持自定义 DateFormat。默认未注册。必须根据需要使用适当的格式进行用户注册。)
CustomNumberEditor Customizable property editor for any Number subclass, such as Integer, Long, Float, or Double. By default, registered by BeanWrapperImpl but can be overridden by registering a custom instance of it as a custom editor.(任何 Number 子类的可定制属性编辑器,例如 Integer、Long、Float 或 Double。默认情况下,由 BeanWrapperImpl 注册,但可以通过将其自定义实例注册为自定义编辑器来覆盖。)
FileEditor Resolves strings to java.io.File objects. By default, registered by BeanWrapperImpl.(将字符串解析为 java.io.File 对象。默认情况下,由 BeanWrapperImpl 注册。)
InputStreamEditor One-way property editor that can take a string and produce (through an intermediate ResourceEditor and Resource) an InputStream so that InputStream properties may be directly set as strings. Note that the default usage does not close the InputStream for you. By default, registered by BeanWrapperImpl.(单向属性编辑器,可以接受一个字符串并生成(通过中间的 ResourceEditor 和 Resource)一个 InputStream,以便可以将 InputStream 属性直接设置为字符串。请注意,默认用法不会关闭 InputStream。默认情况下,由 BeanWrapperImpl 注册。)
LocaleEditor Can resolve strings to Locale objects and vice-versa (the string format is [language][country][variant], same as the toString() method of Locale). Also accepts spaces as separators, as an alternative to underscores. By default, registered by BeanWrapperImpl.(可以将字符串解析为 Locale 对象,反之亦然(字符串格式为 [language][country][variant],与 Locale 的 toString() 方法相同)。也接受空格作为分隔符,作为下划线的替代。默认情况下,由 BeanWrapperImpl 注册。)
PatternEditor Can resolve strings to java.util.regex.Pattern objects and vice-versa.(可以将字符串解析为 java.util.regex.Pattern 对象,反之亦然。)
PropertiesEditor Can resolve strings to java.util.regex.Pattern objects and vice-versa.(可以将字符串(使用 java.util.Properties 类的 javadoc 中定义的格式进行格式化)转换为 Properties 对象。默认情况下,由 BeanWrapperImpl 注册。)
URLEditor Can resolve a string representation of a URL to an actual URL object. By default, registered by BeanWrapperImpl.(可以将字符串(可以将 URL 的字符串表示解析为实际的 URL 对象。默认情况下,由 BeanWrapperImpl 注册。)

Spring Core 之 Validation, Data Binding(校验和数据绑定)相关推荐

  1. Data Binding Library数据绑定框架

    Data Binding Library是Google在2015年IO大会上发布的一个用于实现MVVM设计模式的支持库 环境配置 在Android Studio 2.0 原生支持Data Bindin ...

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

    本篇太乱,请移步: Spring Framework 官方文档学习(四)之Validation.Data Binding.Type Conversion(一) 写了删删了写,反复几次,对自己的描述很不 ...

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

    接前一篇 Spring Framework 官方文档学习(四)之Validation.Data Binding.Type Conversion(一) 本篇主要内容:Spring Type Conver ...

  4. WPF中的数据绑定Data Binding使用小结

    完整的数据绑定的语法说明可以在这里查看: http://www.nbdtech.com/Free/WpfBinding.pdf MSDN资料: Data Binding: Part 1 http:// ...

  5. XAML数据绑定(Data Binding)

    XAML数据绑定(Data Binding) Data Binding可以使得XAML标签属性的赋值更为灵活和方便.在绑定过程中,获取数据的标签成为目标标签:提供数据的标签成为源标签.在XAML中,一 ...

  6. WPF中的Data Binding调试指南

    点击蓝字"大白技术控"关注我哟 加个"星标★",每日良时,好文必达! WPF中的Data Binding如何Debug? 大家平时做WPF开发,相信用Visua ...

  7. Spring教程– Spring Core Framework教程

    Spring is one of the most widely used Java EE frameworks. I have written a lot on Spring Tutorial an ...

  8. Android开发教程 - 使用Data Binding(二)集成与配置

    本系列目录 使用Data Binding(一)介绍 使用Data Binding(二)集成与配置 使用Data Binding(三)在Activity中的使用 使用Data Binding(四)在Fr ...

  9. Binding(一):数据绑定

    这节开始分几期来讲一下WPF中Binding的相关用法,本节主要讲使用Binding进行数据绑定. Binding的作用 在WinForm中,我们要想对控件赋值,需要在后台代码中拿到控件对象进行操作, ...

  10. Data Binding学习(一)

    1.为什么要使用Data Binding? 当我们没使用Data Binding时候布局是这样的 <LinearLayout -><TextView android:id=" ...

最新文章

  1. Linux内核官方文档atomic_ops.txt【摘自Linux 内核文档】
  2. flash builder 关联svn
  3. 201621123053 张雨阳软工作业2
  4. 安装Google Object Detection API
  5. 06.search_shard_api操作
  6. solr 启动、停止
  7. 使用sslsplit嗅探tls/ssl连接
  8. Python获取本机ip地址的两种有效方法
  9. doxygen 教程 linux,使用Doxygen生成全中文的chm、pdf帮助文档的方法
  10. 读河南干旱帖有感而发的一天(20191006)
  11. 医院、诊所看这里,一个分诊屏+叫号系统,实现门诊高效排队叫号
  12. 中国科学院的研究所很难进吗?
  13. google爬取搜索结果
  14. word文件图标无法显示的问题
  15. python爬虫--小说爬取
  16. 机器学习常见求逆矩阵的方法
  17. 惊闻苏州GDP总量突破2万亿大关!
  18. 什么是 DDoS 攻击?- DDoS 含义
  19. Windows containers are not supported by your Windows version. Check documentation for minimum requir
  20. 手游神武2最新服务器,神武2手游新服开启公告 安卓IOS新服开启

热门文章

  1. android 裁剪图片工具,十大最佳Android图像裁剪(裁剪小部件)库
  2. 解决力扣等国外网站打不开问题
  3. 基于ROS2多机器人编程资料
  4. 各双拼输入方案之间有明显的优劣之分吗?
  5. 依然仰望星空,脚踏实地——个人CSDN年度总结。
  6. flutter能开发游戏吗_Flutter Flame游戏开发上手(1)
  7. 英语心理测试脸型软件,心理测试:脸型分析自己
  8. 用ros3.3中的nth进行带宽叠加
  9. Blekko推出类Flipboard社交新闻网站ROCKZi
  10. 给ESXi虚拟机硬盘瘦身