起重设备智能点检系统(前端)的设计与实现外文翻译资料
2022-10-26 10:04:32
8. Validation, Data Binding, and Type Conversion
8.1 Introduction
JSR-303/JSR-349 Bean Validation
Spring Framework 4.0 supports Bean Validation 1.0 (JSR-303) and Bean Validation 1.1 (JSR-349) in terms of setup support, also adapting it to Springrsquo;s Validatorinterface.
An application can choose to enable Bean Validation once globally, as described in Section 8.8, “Spring Validation”, and use it exclusively for all validation needs.
An application can also register additional Spring Validator instances per DataBinder instance, as described in Section 8.8.3, “Configuring a DataBinder”. This may be useful for plugging in validation logic without the use of annotations.
There are pros and cons for considering validation as business logic, and Spring offers a design for validation (and data binding) that does not exclude either one of them. Specifically validation should not be tied to the web tier, should be easy to localize and it should be possible to plug in any validator available. Considering the above, Spring has come up with a Validator interface that is both basic and eminently usable in every layer of an application.
Data binding is useful for allowing user input to be dynamically bound to the domain model of an application (or whatever objects you use to process user input). Spring provides the so-called 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 MVC framework.
The BeanWrapper is a fundamental concept in the Spring Framework and is used in a lot of places. However, you probably will not have the need to use the BeanWrapperdirectly. Because this is reference documentation however, we felt that some explanation might be in order. We will explain the BeanWrapper in this chapter since, if you were going to use it at all, you would most likely do so when trying to bind data to objects.
Springrsquo;s DataBinder and the lower-level BeanWrapper both use PropertyEditors to parse and format property values. The PropertyEditor concept is part of the JavaBeans specification, and is also explained in this chapter. Spring 3 introduces a 'core.convert' package that provides a general type conversion facility, as well as a higher-level 'format' package for formatting UI field values. These new packages may be used as simpler alternatives to PropertyEditors, and will also be discussed in this chapter.
8.2 Validation using Springrsquo;s Validator interface
Spring features a Validator interface that you can use to validate objects. The Validator interface works using an Errors object so that while validating, validators can report validation failures to the Errors object.
Letrsquo;s consider a small data object:
public class Person {
private String name;
private int age;
// the usual getters and setters...
}
Wersquo;re going to provide validation behavior for the Person class by implementing the following two methods of the org.springframework.validation.Validatorinterface:
- 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 givenErrors object
Implementing a Validator is fairly straightforward, especially when you know of the ValidationUtils helper class that the Spring Framework also provides.
public class PersonValidator implements Validator {
/**
* This Validator validates *just* 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() lt; 0) {
e.rejectValue('age', 'negativevalue');
} else if (p.getAge() gt; 110) {
e.rejectValue('age', 'too.darn.old');
}
}
}
As you can see, the static rejectIfEmpty(..) method on the ValidationUtils class is used to reject the name property if it is null or the empty string. Have a look at the ValidationUtils javadocs to see what functionality it provides besides the example shown previously.
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 second name) and a complex Address object. Address objects may be used independently of Customer objects, and 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, and us
剩余内容已隐藏,支付完成后下载完整资料
第八章:校验,数据绑定,与属性编辑器
8.1介绍
JSR-303/JSR-349Bean 校验
Spring Framework 4.0支持Bean校验1.0(jsr - 303)和Bean校验1.1(jsr - 349)的安装支持,还适用于对Spring的Validator接口
如8.8节“Spring Validation”部分所述,在全球范围内应用程序可以选择启用Bean Validation一次,并专门用于所有验证需求。第8.8.3节“配置一个DataBinder”部分表明对于每个DataBinder实例,应用程序也可以注册附加的Spring Validation实例,这可以在不使用注释时用于验证逻辑堵塞。
对是否把校验当作业务逻辑这个问题,存在着正和反两种意见,而Spring提供的验证模式(和数据绑定)的设计对这两种意见都不排斥。特别是,校验应该不应该被强制绑定在Web层,而且应该很容易本地化并且可以方便地加入新的验证逻辑。基于上述的考虑,Spring提供了一个Validator接口。这是一个基础的接口并且适用于应用程序的任何一个层面。
BeanWrapper作为一个基础组件被用在了Spring框架中的很多地方。不过,你可能很少会需要直接使用BeanWrapper。由于这是一篇参考文档,因而我们觉得对此稍作解释还是有必要的。我们在这一章节里对BeanWrapper的说明,或许到了你日后试图进行类似对象与数据之间的绑定这种与BeanWrapper非常相关的操作时会有一些帮助。
Spring大量地使用了PropertyEditor(属性编辑器)。PropertyEditor的概念是JavaBean规范的一部分。正如上面提到的BeanWrapper一样,由于它与BeanWrapper以及DataBinder三者之间有着密切的联系,我们在这里同样对PropertyEditor作一番解释。
8.2. 使用Spring的Validator接口进行校验
你可以使用Spring提供的validator接口进行对象的校验。Validator接口与Errors协同工作,在Spring做校验的时候,它会将所有的校验错误汇总到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以后。我们一起来看一下如何才能创建一个校验器。
public class PersonValidator implements Validator {
/**
* This Validator validates *just* 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() lt; 0) {
e.rejectValue('age', 'negativevalue');
} else if (p.getAge() gt; 110) {
e.rejectValue('age', 'too.darn.old');
}
}
}
如你所见,我们使用了ValidationUtils中的一个静态方法rejectIfEmpty(..)来对name属性进行校验,假若name属性是 null 或者空字符串的话,就拒绝验证通过 。请参照ValidationUtils相关的JavaDoc,查看一下除了例子中介绍过的之外其他的一些功能。
对复杂对象来说,实现Validator类来验证其内置的属性类当然也是可行的,但是为每个内置类的示例实现Validator可能是个更好的主意。关于这样的一个rich这样的例子是Customer类,它包含两个String属性(first name 和second name),还有一个复杂的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中,你可以使用lt;spring:bind/gt;标签来检查错误信息,当然你也可以自行处理错误。可以在它的Javadoc中找到它提供的方法的描述。
8.3. 从错误代码到错误信息
我们已经讨论了数据绑定和校验。最后我们来讨论一下与校验错误相对应的错误信息输出。在先前的示例中,我们对name和age字段进行了校验并发现了错误。如果我们想用MessageSource来输出错误信息,当某个字段校验出错时(在这个例子中是name和age)我们输出的是错误代码。无论你直接或者间接使用示例中的ValidationUtils 类来调用Errors接口中rejectValue方法或者任何一个其它的reject方法,底层的实现不仅为你注册了你传入的代码,还同时为你注册了许多额外的错误代码信息。而你使用的MessageCodesResolver将决定究竟注册什么样的错误代码。默认情况下,将会使用DefaultMessageCodesResolver。回到前面的例子,使用DefaultMessageCodesResolver,不仅会为你注册你提供的错误代码信息,同时还包含了你传入到reject方法中的字段信息。所以在这个例子中,你通过rejectValue('age', 'too.darn.old')来注册一个字段校验错误。Spring不仅为你注册了too.darn.old这个代码,同时还为你注册了too.darn.old.age和too.darn.old.age.int来分别表示字段名称和字段的类型。这种是现实为了方面开发者来定位错误信息。
更多有关MessageCodesResolver的信息以及默认的策略可以在线访问相应的JavaDocs: MessageCodesResolver 和 资料编号:[154002],资料为PDF文档或Word文档,PDF文档可免费转换为Word