(笔记)Spring MVC学习指南_验证器

来源:互联网 发布:期权模拟交易软件 编辑:程序博客网 时间:2024/06/05 10:56

在Spring MVC中,有两种方式可以验证输入,即利用Spring自带的验证框架,或者利用JSR 303实现。
1.验证概览
Converter和Formatter作用于field级。在MVC应用程序中,它们将String转换或格式化成另一种Java类型。验证器则作用于object级。它决定某一个对象中的所有field是否均是有效的,以及是否遵循某些规则。
如果一个应用程序中即使用了Formatter,又有validator(验证器),那么,它们的事件顺序是这样的:在调用Controller期间,将会有一个或者多个Formatter,试图将输入字符串转换成domain对象中的field值。一旦格式化成功,验证器就会介入。
2.Spring验证器
为了创建Spring验证器,要实现org.springframework.validation.Validator接口。

package org.springframework.validation;public interface Validator {    boolean supports(Class<?> clazz);    void validate(Object target, Errors errors);}

如果验证器可以处理指定的Class,supports方法将返回true。validate方法会验证目标对象,并将验证错误填入Errors对象。
Errors对象是org.springframework.validation.Errors接口的一个实例。Errors对象中包含了一系列FieldError和ObjectError对象。FieldError表示与被验证对象中的某个属性相关的一个错误。
编写验证器时,不需要直接创建Error对象,因为实例化ObjectError或FieldError花费了大量的编程精力。给Errors对象添加错误的最容易的方法是:在Errors对象上调用一个reject或者rejectValue方法。

void reject(String errorCode)void reject(String errorCode, String defaultMessage)void rejectValue(String field, String errorCode)void rejectValue(String field, String errorCode, String defaultMessage)

大多数时候,只给reject或者rejectValue方法传入一个错误码,Spring就会在属性文件中查找错误码,获得相应的错误消息。还可以传入一个默认消息,当没有找到指定的错误码时,就会使用默认消息。
Errors对象中的错误消息,可以利用表单标签库的Errors标签显示在HTML页面中。
3.ValidationUtils类
org.springframework.validation.ValidationUtils类是一个工具,有助于编写Spirng验证器。
4.Spring的Validator范例

package app07a.validator;import java.util.Date;import org.springframework.validation.Errors;import org.springframework.validation.ValidationUtils;import org.springframework.validation.Validator;import app07a.domain.Product;public class ProductValidator implements Validator{    @Override    public boolean supports(Class<?> clazz)    {        return Product.class.isAssignableFrom(clazz);    }    @Override    public void validate(Object target, Errors errors)    {        Product product = (Product)target;        ValidationUtils.rejectIfEmpty(errors, "name", "productname.required");        ValidationUtils.rejectIfEmpty(errors, "price", "price.required");        ValidationUtils.rejectIfEmpty(errors, "productionDate", "productiondate.required");        Float price = product.getPrice();        if (price != null && price < 0)        {            errors.rejectValue("price", "price.negative");        }        Date productionDate = product.getProductionDate();        if (productionDate != null)        {            if (productionDate.after(new Date()))            {                errors.rejectValue("productionDate", "productiondate.invalid");            }        }    }}

验证器不需要显式注册,但是如果想要从某个属性文件中获取错误信息,则需要通过声明messageSource bean,告诉Spring要去哪里查找这个文件。

    <bean id="messageSource"        class="org.springframework.context.support.ReloadableResourceBundleMessageSource">        <property name="basename" value="/WEB-INF/resource/messages" />    </bean>

messages.properties

productname.required=Please enter a product nameprice.required=Please enter a priceproductiondate.required=Please enter a production dateprice.negative=Invalid price.Please enter a price greater than zeroproductiondate.invalid=Invalid production date.Please ensure the production date is not later than today

使用Spring验证器的另一种方法是:在Controller中编写initBinder方法,并将验证器传到WebDataBinder,并调用其validate方法。

    @org.springframework.web.bind.annotation.InitBinder    public void InitBinder(WebDataBinder binder)    {        binder.setValidator(new ProductValidator());        binder.validate();    }

8.JSR 303验证
对于JSR bean validation,目前有两个实现。第一个实现时Hibernate Validator,第二个实现时Apache BVal。
JSR 303不需要编写验证器,但要利用JSR 303标注类型嵌入约束。

属性 描述 @AssertFalse 应用于boolean属性,该属性值必须为False @AssertTrue 应用于boolean属性,该属性值必须为True @DecimalMax 该属性值必须为小于或等于指定值的小数 @DecimalMin 该属性值必须为大于或等于指定值的小数 @Digits 该属性值必须在指定范围内。integer属性定义该数值的最大整数部分,fraction属性定义该数值的最大小数部分 @Future 该属性值必须是一个未来的日期 @Max 该属性值必须是一个小于或等于指定值的整数 @Min 该属性值必须是一个大于或等于指定值的整数 @NotNull 该属性值不能为Null @Null 该属性值必须为Null @Past 该属性值必须是过去的一个日期 @Pattern 该属性值必须与指定的常规表达式相匹配 @Size 该属性值必须在指定范围内

9.JSR 303 Validator范例
jar包
需要导入jar包

    <mvc:annotation-driven validator="validator" />    <bean id="validator"        class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">        <property name="providerClass" value="org.hibernate.validator.HibernateValidator" />        <property name="validationMessageSource" ref="messageSource" />    </bean>    <bean id="messageSource"        class="org.springframework.context.support.ReloadableResourceBundleMessageSource">        <property name="basename" value="/WEB-INF/resource/messages" />    </bean>
@RequestMapping(value = "/product_save")    public String saveProduct(@Valid @ModelAttribute Product product, BindingResult bindingResult,                              Model model)
package app07b.domain;import java.io.Serializable;import java.util.Date;import javax.validation.constraints.Past;import javax.validation.constraints.Size;import com.sun.istack.internal.NotNull;public class Product implements Serializable{    private static final long serialVersionUID = -164834188493691288L;    @Size(min = 1, max = 10)    private String name;    @NotNull    private String description;    private Float price;    @Past    private Date productionDate;    public String getName()    {        return name;    }    public void setName(String name)    {        this.name = name;    }    public String getDescription()    {        return description;    }    public void setDescription(String description)    {        this.description = description;    }    public Float getPrice()    {        return price;    }    public void setPrice(Float price)    {        this.price = price;    }    public Date getProductionDate()    {        return productionDate;    }    public void setProductionDate(Date productionDate)    {        this.productionDate = productionDate;    }}

由于JSR 303是正式的Java规范,因此新项目建议使用JSR 303验证器。

0 0