Spring学习笔记-springMVC校验框架

来源:互联网 发布:Java encodeurl 编辑:程序博客网 时间:2024/06/03 17:44

输入校验是Web开发最重要的任务之一。SpringMVC作为当今最流行的MVC框架,自然也对输入校验做了很好的支持。

在SpringMVC中可以用两种方式来进行输入校验
1)利用SpringMVC自带的校验框架
2)利用JSR 303

下面我们对着两种校验方式做详细的描述。

  • Spring验证框架
    spring的验证框架入口为Validator接口,该接口的签名是这样的:
public interface Validator {     boolean supports(Class<?> clazz);     void validate(Object target, Errors errors);}

Spring在完成校验动作时,首先会调用supoorts()方法,判断当前的object在不在校验队列中,如果在,则紧接着调用validate方法,进行校验。
在应用校验框架是,我们最常用的可能就是Errors接口了,这个接口有一些实现类,我们可以吧它理解为一个存放错误信息的容器,里面存放着一系列的域错误(FieldError)和对象错误(ObjectError),同时,它还提供了获取错误信息和加入错误信息的方法,例如:

void reject(String errorCode, Object[] errorArgs, String defaultMessage);void rejectValue(String field, String errorCode, Object[] errorArgs, String defaultMessage);boolean hasFieldErrors();List<FieldError> getFieldErrors();List<ObjectError> getAllErrors();......

利用这些方法,我们就可以在这个“错误容器”里方便的存取错误数据。

在进行数据校验时,我们以往经常要写很多向下面这样 代码:

if(firstName == null && firstName.isEmpty())        errors.rejectValue("price");

或者

if(firstName == null || firstName.trim().isEmpty())     errors.rejectValue("price");

这样的代码虽然是必须的,但是大量的重复往往令人头疼,幸好,Spring为我们提供了一个工具类,可以很好的解决上面的问题,ValidtionUtils,利用这个工具类就可以吧具有上面功能 代码写的很优雅:

ValidationUtils.rejectIfEmpty("price");ValidationUtils.rejectIfEmptyOrWhitespace("price");

该工具类还保护很多重载方法,大家可以自己查看API文档。
看起来也是蛮强大的吧……

下面,我们就用一个简单是范例,来说明一下Spring校验框架的基本用法。

1)首先,创建一个POJO类

@SuppressWarnings("serial")public class Product implements Serializable{    private String name;    private String description;    private Float price;    private Date productionDate;    setter/getter....}

2)编写一个实现了Validator接口的校验器

public class ProductValidator implements Validator{    Logger logger = Logger.getLogger(ProductValidator.class);    //spring通过调用该方法确定是否对某个对象进行校验(validate(target,errors))    @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(   //验证null 和  "" 空字符串                errors,                 "name",  //域名称                "productname.required"       //错误编码                );        ValidationUtils.rejectIfEmpty(                    errors,                     "price",                     "price.required"                  );        ValidationUtils.rejectIfEmpty(errors,                  "productionDate", "productionDate.required");        //手动向errors中添加错信息的示例        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())){                logger.info(" productDate error");                errors.rejectValue("productionDate", "productiondate.invalid");            }        }    }}

3)创建一个用于显示错误信息的资源文件(.properties)

productname.required.product.name=Please enter a product nameprice.required=Please enter a priceproductiondate.required=Please enter a production dateproductiondate.invalid=Invalid production date. Please ensure the production date is not later than today

4)紧接着,要把这个资源文件注册到spring环境中,这样在检验器中才能得到具体的错误提示。

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

5)最后,要编写一个应用了校验器的Controller来完成校验任务。

/** * @Description: 校验框架测试 controller. * @Author:Zander * @CreateDate:Aug 8, 2015 * @Company: */@Controllerpublic class ProductController {    private static final Logger logger = Logger.getLogger(ProductController.class);    @RequestMapping(value="/product_input")    public String inutProduct(Model model){        model.addAttribute("product", new Product());        return "productionForm";    }    public String saveProduct(@ModelAttribute Product product,            BindingResult bindingResult, Model model){        ProductValidator productValidator = new ProductValidator();        productValidator.validate(product, bindingResult);   //调用校验器        //校验未通过        if(bindingResult.hasErrors()){            //得到校验是写入的错误信息            FieldError fieldError = bindingResult.getFieldError();            logger.info("Code:" + fieldError.getCode() + ", field:" + fieldError.getField());            //返回表单视图            return "productForm";        }        //校验通过        model.addAttribute("product", product);        return "productDetails";    }}

完成。

  • 利用JSR 303进行校验。
    首先要说明的是,JSR是一系列的规范,它本身并没有使用意义,如果想在JSR规范的基础上完成校验,则需要导入它的实现。目前JSR303的实现有两种:Hibernate Validator 和 Apache BVal。

下面先说明一下JSR 303的规范。

 @AssertFalse    应用于boolean属性,该属性值必须为False        @AssertFalse boolean hasChildern @AssertTrue     应用于boolean属性,该属性值必须为True            @AssertTrue boolean isEmpty @DecimalMax     该属性必须为小于或等于指定的小树                           @DecimalMax("1.1") BigDecimal price @DecimalMin     该属性必须大于或等于指定值的小数                           @DecimalMin("0.04") @Digits         该属性必须在指定的范围内                          @Digits(integer=5,fraction=2)      BigDecimal price; @Future         该属性值必须是未来的一个日期                              @Future  Date shippingDate @Max            该属性值必须是一个小于或等于指定数值的整数                   @Max(150) int age @Min            该属性值必须是一个大于或等于指定数值的整数                @Min(150)  int age@NotNull  String firstName@Null           该值必须为null                                @Null String testString@Past           该值必须为过去的一个时间                                   @Past Date birthDate@Pattern        该属性hi必须与指定的常规表达式匹配                          @Pattern(regext="\\d{3}")@Size            该属性值必须在制定范围内                                  @Size(min=2,max=140) String description

利用这些注解直接表述bean中的域就可以方便的实现校验。

下面我们还是通过一个小例子,来看一下它的具体用法。
1)创建JavaBean,利用JSR注解标注

/** * @Description: JSR校验 * @Author:Zander * @CreateDate:Aug 8, 2015 * @Company: */public class Product2 {    @Size(min=1,max=10)    private String name;    private String description;    private Float price;    @Past    private Date productionDate;    geter()/setter()    ...}

2)创建Controller,不用实现校验器了哦!这是重点。

/** * @Description: JSR 校验测试Controller. * @Author:Zander * @CreateDate:Aug 8, 2015 * @Company: */@Controllerpublic class ProductController2 {    private static final Logger logger = Logger.getLogger(ProductController2.class);    public String inutProduct(Model model){        model.addAttribute("product", new Product2());        return "productForm";    }    public String saveProduct(@Valid @ModelAttribute Product2 product2,            BindingResult bingBindingResult, Model model){        //判断是否通过校验   此处利用@Valid 注解 加上  JSR注解 就不用显示的创建校验器        if(bingBindingResult.hasErrors()){            FieldError fieldError = bingBindingResult.getFieldError();            logger.info("Code:" + fieldError.getCode() + ", object:" + fieldError.getObjectName() +                      ", field : " + fieldError.getField());            return "productForm";        }        //save product        model.addAttribute("product", product2);        return "productDetails";    }}

3)配置一个资源文件,用于提示信息的显示。

Size.product.name=Product name mast be 1 to 10 characters longPast.product.productionDate=Production date must a past time

4)再像上面的那样,注册资源文件到spring容器。

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

哦了,搞定,就这么用。

0 0
原创粉丝点击