转:http://xiangtui.iteye.com/blog/970951,
验证数据是应用程序生命周期中一个常见的任务,例如,在应用程序的表示层,你可能想验证用户在文本框中输入的字符数最多不超过20个,或者想验证用户在数字字段输入的字符只能是数字。
开发人员在应用程序的各层中通常使用相同的验证逻辑,或者将验证逻辑放在数据模型中。
Bean验证(JSR 303)使验证变得更简单了,减少了重复,错误和凌乱,Bean验证提供了一个标准的验证框架,在框架中相同的验证集可以在应用程序的所有层之间共享。
Bean验证提供了一个框架验证遵循JavaBean规范编写的Java类,你可以使用 注解指定一个JavaBean上的约束,你可以注解一个JavaBean类、字段或属性,你也可以通过XML描述符扩展或覆盖这些约束,验证类验证每个约 束时,你要指定那个验证类用于给定的约束类型。
例如,下面是通过Bean验证注解声明一些约束
public class Address{
@NotNull @Size(max=30)
private String addressline1;
@Size(max=30)
private String addressline2;
...
public String getAddressline1(){
return addressline1;
}
public void setAddressline1(String addressline1) {
this.addressline1=addressline1;
}
...
}
@NotNull注解指定了注解元素addressline1绝不能为空,@Size注解指定注解元素addressline1和addressline2决不能大于指定的长度(30个字符)。
验证Address对象时,addressline1的值传递给为@NotNull约束定义的验证类,同时还要传递给为@Size约束定义的验证类,addressline2的值也要传递给为@Size约束定义的验证类。
@NotNull 和@Size约束内置于Bean验证框架中,因此你不需要为它们定义验证类,但你可以在内置约束上添加自己的约束,那时就需要定义自己的验证类了。例如, 你可以定义如下的@ZipCode约束:
@Size(min=5,max=5)
@ConstraintValidator(ZipcodeValidator.class)
@Documented
@Target({ANNOTATION_TYPE, METHOD,?FIELD})
@Retention(RUNTIME)
public @interface ZipCode{
String message() default "Wrong zipcode";
String[] groups() default {};
}
然后你可以在类、字段或属性上象其它约束定义那样定义@ZipCode约束,如:
public class Address {
...
@ZipCode
private String addressline3;
public String getZipCode(){
return zipCode;
}
public void setZipCode(String zipCode){
this.zipCode=zipCode;
}
Address对象验证时,addressline3的值传递给 ZipcodeValidator类进行验证,注意约束定义包括另一个约束:@Size(min=5, max=5),这意味着由@ZipCode注解注解的元素必须恰好是5个字符,除了执行ZipcodeValidator进行主要的约束检查外,需要再次 使用这个约束对元素进行验证。Bean验证允许你创建一个由其它约束组成的约束,还要注意约束定义了一个错误消息,如果验证检查约束失败就返回这个错误消 息,这里的错误消息是“Wrong zipcode”。
你也可以使用Bean验证验证一个完整的对象图(object graph),一个对象图是由其它对象组成的一个对象,如果你在对象图的根对象上指定@Valid注解,它会指引相关的验证器递归验证对象图中的关联对象,如:
public class Order{
@OrderNumber private String orderNumber;
@Valid @NotNull private Address delivery;
}
Order对象验证时,Address对象和对象图中关联的对象也被验证。
为了满足在应用程序各层之间共享相同的验证集,Java EE 6平台整合了Bean验证。例如,表示层技术,如JSF,以及企业级技术,如JPA,都可以通过Bean验证框架访问约束定义和验证器,你不再需要在多个地方指定约束。
-------------------------------------《Spring in Action3》7.4.3 Validating input-------------
When a user registers with the Spitter application, there are certain requirements that
we’d like to place on that registration. Specifically, a new user must give us their full
name, email address, a username, and a password. Not only that, but the email
address can’t be just freeform text—it must look like an email address. Moreover, the
password should be at least six characters long.
The @Valid annotation is the first line of defense against faulty form input. @Valid
is actually a part of the JavaBean validation specification.4 Spring 3 includes support
for JSR-303, and we’re using @Valid here to tell Spring that the Spitter object should
be validated as it’s bound to the form input.
Should anything go wrong while validating the Spitter object, the validation error
will be carried to the addSpitterFromForm() method via the BindingResult that’s
passed in on the second parameter. If the BindingResult’s hasErrors() method
returns true, then that means that validation failed. In that case, the method will
return spitters/edit as the view name to display the form again so that the user can
correct any validation errors.
But how will Spring know the difference between a valid Spitter and an invalid
Spitter?
DECLARING VALIDATION RULES
Among other things, JSR-303 defines a handful of annotations that can be placed on
properties to specify validation rules. We can use these annotations to define what
“valid” means with regard to a Spitter object. The following shows the properties of
the Spitter class that are annotated with validation annotations.
@Size(min=3,max=20,message= "Usernamemustbebetween3and20characterslong.") @Pattern(regexp="^[a-zA-Z0-9]+$", message="Username mustbealphanumericwithnospaces") private String username; @Size(min=6,max=20, message="The passwordmustbeatleast6characterslong.") private String password; @Size(min=3,max=50,message= "Yourfullnamemustbebetween3and50characterslong.") private String fullName; @Pattern(regexp="[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}", message="Invalid emailaddress.") private String email;
With these annotations in place, when a user submits a registration form to
SpitterController’s addSpitterFromForm() method, the values in the Spitter
object’s fields will be weighed against the validation annotations. If any of those rules
are broken, then the handler method will send the user back to the form to fix the
problem.
When they arrive back at the form, we’ll need a way to tell them what the problem
was. So we’re going to have to go back to the form JSP and add some code to display
the validation messages. DISPLAYING VALIDATION ERRORS
Recall that the BindingResult passed in as a parameter to addSpitterFromForm()
knew whether the form had any validation errors. And we were able to ask if there
were any errors by calling its hasErrors() method. But what we didn’t see was that the
actual error messages are also in there, associated with the fields that failed validation.
One way of displaying those errors to the users is to access those field errors
through BindingResult’s getFieldError() method. But a much better way is to use
Spring’s form binding JSP tag library to display the errors. More specifically, the
<sf:errors> tag can render field validation errors. All we need to do is sprinkle a few
<sf:errors> tags around our form JSP.
<%@ taglibprefix="sf"uri="http://www.springframework.org/tags/form"%>
<div>
<h2>CreateafreeSpitteraccount</h2>
<sf:form method="POST"modelAttribute="spitter"
enctype="multipart/form-data">
<fieldset>
<tablecellspacing="0">
<tr>
<th><sf:label path="fullName">Fullname:</sf:label></th>
<td><sf:input path="fullName"size="15"/><br/>
<sf:errors path="fullName"cssClass="error"/>
</td>
</tr>
<tr>
<th><sf:label path="username">Username:</sf:label></th>
<td><sf:input path="username"size="15"maxlength="15"/>
<small id="username_msg">Nospaces,please.</small><br/>
<sf:errors path="username"cssClass="error"/>
</td>
</tr>
<tr>
<th><sf:label path="password">Password:</sf:label></th>
<td><sf:password path="password"size="30"
showPassword="true"/>
<small>6 charactersormore(betricky!)</small><br/>
<sf:errors path="password"cssClass="error"/>
</td>
</tr>
<tr>
<th><sf:label path="email">EmailAddress:</sf:label></th>
<td><sf:input path="email"size="30"/>
<small>In caseyouforgetsomething</small><br/>
<sf:errors path="email"cssClass="error"/>
</td>
</tr>
<tr>
<th></th>
<td>
<sf:checkbox path="updateByEmail"/>
<sf:label path="updateByEmail"
>Send meemailupdates!</sf:label>
</td>
</tr>
<tr>
<th><label for="image">Profileimage:</label></th>
<td><input name="image"type="file"/>
</tr>
<tr>
<th></th>
<td><input name="commit"type="submit"
value="I accept.Createmyaccount."/></td>
</tr>
</table>
</fieldset>
</sf:form>
</div>
The <sf:errors> tag’s path attribute specifies the form field for which errors should
be displayed. For example, the following <sf:errors> displays errors (if there are
any) for the field whose name is fullName:
<sf:errorspath="fullName"cssClass="error"/>
If there are multiple errors for a single field, they’ll all be displayed, separated by an
HTML <br/> tag. If you’d rather have them separated some other way, then you can
use the delimiter attribute. The following <sf:errors> snippet uses delimiter to
separate errors with a comma and a space:
<sf:errorspath="fullName"delimiter=","
cssClass="error"/>
Note that there are four <sf:errors> tags in this JSP, one on each of the fields for
which we declared validation rules. The cssClass attribute refers to a class that’s
declared in CSS to display in red so that it catches the user’s attention.
With these in place, errors will be displayed on the page if any validation errors
occur. For example, figure 7.7 shows what the form would look like if the user were to
submit the form without filling in any of the fields.
Figure 7.7 With the <sf:errors> JSP tag on the registration page, validation problems
will be shown to the user for them to fix and try again.