输入验证是Spring处理的最重要的Web开发任务之一
验证器属于Object级,它决定某一个对象中的所有field是否均是有效的,以及是否遵循某些规则
1.Spring的验证器
要实现org.springframework.validation.Validator接口
1 public interface Validator{ 2 boolean supports(Class<?> clazz); 3 void validate(Object target,Errors errors); 4 }
如果验证器可以处理指定的Class,supports方法将返回true,
validate方法会验证目标对象,并将验证错误填入Errors对象
给Errors对象添加错误的最容易方法是
调用reject,往FieldError中添加一个ObjectError和rejectError
只给reject或者rejectValue传入一个错误码,Spring就会在属性文件中查找错误码,
获得相应的信息
2.ValidateUtils类
org.springframework.validation.ValidationUtils类是一个工具类
有助于编写Spring验证器,
不需要
1 if(firstName==null || firstName.isEmpty()){ 2 errors.rejectValue("price"); 3 } 4 5 可以用 6 ValidateUtils.rejectIfEmpty("price");
3.Spring的Validate范例
1 package app07a.domain; 2 import java.io.Serializable; 3 import java.util.Date; 4 5 public class Product implements Serializable { 6 private static final long serialVersionUID = 748392348L; 7 private String name; 8 private String description; 9 private Float price; 10 private Date productionDate; 11 12 public String getName() { 13 return name; 14 } 15 public void setName(String name) { 16 this.name = name; 17 } 18 public String getDescription() { 19 return description; 20 } 21 public void setDescription(String description) { 22 this.description = description; 23 } 24 public Float getPrice() { 25 return price; 26 } 27 public void setPrice(Float price) { 28 this.price = price; 29 } 30 public Date getProductionDate() { 31 return productionDate; 32 } 33 public void setProductionDate(Date productionDate) { 34 this.productionDate = productionDate; 35 } 36 37 }
1 package app07a.validator; 2 3 import java.util.Date; 4 5 import org.springframework.validation.Errors; 6 import org.springframework.validation.ValidationUtils; 7 import org.springframework.validation.Validator; 8 9 import app07a.domain.Product; 10 11 public class ProductValidator implements Validator { 12 13 @Override 14 public boolean supports(Class<?> klass) { 15 return Product.class.isAssignableFrom(klass); 16 } 17 18 @Override 19 public void validate(Object target, Errors errors) { 20 Product product = (Product) target; 21 ValidationUtils.rejectIfEmpty(errors, "name", "productname.required"); 22 ValidationUtils.rejectIfEmpty(errors, "price", "price.required"); 23 ValidationUtils.rejectIfEmpty(errors, "productionDate", "productiondate.required"); 24 25 Float price = product.getPrice(); 26 if (price != null && price < 0) { 27 errors.rejectValue("price", "price.negative"); 28 } 29 Date productionDate = product.getProductionDate(); 30 if (productionDate != null) { 31 // The hour,minute,second components of productionDate are 0 32 if (productionDate.after(new Date())) { 33 System.out.println("salah lagi"); 34 errors.rejectValue("productionDate", "productiondate.invalid"); 35 } 36 } 37 } 38 }
验证器不需要显示注册,但是如果想要某个属性文件中获取错误消息,
则需要通过声明messageSource bean,告诉Spring去哪找这个文件
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" 4 xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" 5 xsi:schemaLocation=" 6 http://www.springframework.org/schema/beans 7 http://www.springframework.org/schema/beans/spring-beans.xsd 8 http://www.springframework.org/schema/mvc 9 http://www.springframework.org/schema/mvc/spring-mvc.xsd 10 http://www.springframework.org/schema/context 11 http://www.springframework.org/schema/context/spring-context.xsd"> 12 13 <context:component-scan base-package="app07a.controller" /> 14 <context:component-scan base-package="app07a.formatter" /> 15 16 <mvc:annotation-driven conversion-service="conversionService" /> 17 18 <mvc:resources mapping="/css/**" location="/css/" /> 19 <mvc:resources mapping="/*.html" location="/" /> 20 21 <bean id="viewResolver" 22 class="org.springframework.web.servlet.view.InternalResourceViewResolver"> 23 <property name="prefix" value="/WEB-INF/jsp/" /> 24 <property name="suffix" value=".jsp" /> 25 </bean> 26 27 <bean id="messageSource" 28 class="org.springframework.context.support.ReloadableResourceBundleMessageSource"> 29 <property name="basename" value="/WEB-INF/resource/messages" /> 30 </bean> 31 32 <bean id="conversionService" 33 class="org.springframework.format.support.FormattingConversionServiceFactoryBean"> 34 <property name="formatters"> 35 <set> 36 <bean class="app07a.formatter.DateFormatter"> 37 <constructor-arg type="java.lang.String" value="MM-dd-yyyy" /> 38 </bean> 39 </set> 40 </property> 41 </bean> 42 </beans>
message.properties文件
1 productname.required.product.name=Please enter a product name 2 price.required=Please enter a price 3 productiondate.required=Please enter a production date 4 productiondate.invalid=Invalid production date. Please ensure the production date is not later than today.
Controller
1 package app07a.controller; 2 3 import org.apache.commons.logging.Log; 4 import org.apache.commons.logging.LogFactory; 5 import org.springframework.stereotype.Controller; 6 import org.springframework.ui.Model; 7 import org.springframework.validation.BindingResult; 8 import org.springframework.validation.FieldError; 9 import org.springframework.web.bind.annotation.ModelAttribute; 10 import org.springframework.web.bind.annotation.RequestMapping; 11 12 import app07a.domain.Product; 13 import app07a.validator.ProductValidator; 14 15 @Controller 16 public class ProductController { 17 18 private static final Log logger = LogFactory 19 .getLog(ProductController.class); 20 21 @RequestMapping(value = "/product_input") 22 public String inputProduct(Model model) { 23 model.addAttribute("product", new Product()); 24 return "ProductForm"; 25 } 26 27 @RequestMapping(value = "/product_save") 28 public String saveProduct(@ModelAttribute Product product, 29 BindingResult bindingResult, Model model) { 30 logger.info("product_save"); 31 System.out.println("prod save"); 32 ProductValidator productValidator = new ProductValidator(); 33 productValidator.validate(product, bindingResult); 34 35 if (bindingResult.hasErrors()) { 36 FieldError fieldError = bindingResult.getFieldError(); 37 logger.info("Code:" + fieldError.getCode() + ", field:" 38 + fieldError.getField()); 39 40 return "ProductForm"; 41 } 42 43 // save product here 44 45 model.addAttribute("product", product); 46 return "ProductDetails"; 47 } 48 }
测试验证器
http://localhost:8080/app07a/product_input