您的位置:首页 > 编程语言 > Java开发

Spring学习笔记-springMVC校验框架

2015-08-08 12:41 435 查看
输入校验是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 name
price.required=Please enter a price
productiondate.required=Please enter a production date
productiondate.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:
*/
@Controller
public 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:
*/
@Controller
public 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 long
Past.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>


哦了,搞定,就这么用。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: