海外直邮购物网站/外贸网站推广
背景:
一般系统对表单的提交都会提供一定的校验,分为前台校验和后台校验,前台校验主要为了减轻服务器的负担,后台校验增加系统安全性。在公司项目里看到validation的使用,在此做个简单学习记录。
例子学习:
创建一个maven项目,pom.xml 如下
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.test</groupId><artifactId>validationTest</artifactId><version>0.0.1-SNAPSHOT</version><packaging>war</packaging><dependencies><dependency><groupId>javax.el</groupId><artifactId>javax.el-api</artifactId><version>2.2.4</version></dependency><dependency><groupId>org.hibernate</groupId><artifactId>hibernate-validator</artifactId><version>5.1.3.Final</version></dependency></dependencies>
</project>
创建一个实体类StudentInfo
public class StudentInfo {@NotBlank(message="用户名不能为空")private String userName;@NotBlank(message="年龄不能为空")@Pattern(regexp="^[0-9]{1,2}$",message="年龄是整数")private String age;/*** @Pattern的意思是,如果是空,则不校验,如果不为空,则校验*/@Pattern(regexp="^[0-9]{4}-[0-9]{2}-[0-9]{2}$",message="出生日期格式不正确")private String birthday;@NotBlank(message="学校不能为空")private String school;public String getUserName() {return userName;}public void setUserName(String userName) {this.userName = userName;}public String getAge() {return age;}public void setAge(String age) {this.age = age;}public String getBirthday() {return birthday;}public void setBirthday(String birthday) {this.birthday = birthday;}public String getSchool() {return school;}public void setSchool(String school) {this.school = school;}}
创建校验工具ValidatorUtil.java(这里写成工具类的形式便于使用)
public class ValidatorUtil{//创建静态校验工厂private static Validator validator = Validation.buildDefaultValidatorFactory().getValidator();public static <T> Map<String,StringBuffer> validate(T obj){//校验过程Set<ConstraintViolation<T>> set = validator.validate(obj,Default.class);//校验结果输出,可以自定义Map<String,StringBuffer> errorMap = null;if(set != null && set.size() >0 ){errorMap = new HashMap<String,StringBuffer>();String property = null;for(ConstraintViolation<T> cv : set){//这里循环获取错误信息,可以自定义格式property = cv.getPropertyPath().toString();if(errorMap.get(property) != null){errorMap.get(property).append("," + cv.getMessage());}else{StringBuffer sb = new StringBuffer();sb.append(cv.getMessage());errorMap.put(property, sb);}}}return errorMap;}
}
最后写个测试类ValidatorTest.java
public class ValidatorTest { public static void main(String[] args) {StudentInfo s = new StudentInfo();long startTime = System.currentTimeMillis();print(ValidatorUtil.validate(s));System.out.println("===============耗时(毫秒)=" + (System.currentTimeMillis() - startTime));s.setUserName("chenwb");s.setAge("a10");s.setBirthday("2016-9-1");startTime = System.currentTimeMillis();print(ValidatorUtil.validate(s));System.out.println("===============耗时(毫秒)=" + (System.currentTimeMillis() - startTime));}private static void print(Map<String,StringBuffer> errorMap){if(errorMap != null){for(Map.Entry<String, StringBuffer> m : errorMap.entrySet()){System.out.println(m.getKey() + ":" + m.getValue().toString());}}}
}------------------------------------------------------------------------------------
测试结果:
school:学校不能为空
userName:用户名不能为空
age:年龄不能为空
===============耗时(毫秒)=298
birthday:出生日期格式不正确
school:学校不能为空
age:年龄是整数
===============耗时(毫秒)=4
总结:
对于这个例子相信主要的问题是在这个工具类上,目前已知的是校验过程在
//校验过程
Set<ConstraintViolation<T>> set = validator.validate(obj,Default.class);这句话中,validate()是Validator类的方法,返回的是Set<ConstraintViolation<T>>集合。
看一下这个接口的注释:(Validates all constraints on {@code object})
/*** Validates all constraints on {@code object}.** @param object object to validate* @param groups the group or list of groups targeted for validation (defaults to* {@link Default})* @return constraint violations or an empty set if none* @throws IllegalArgumentException if object is {@code null}* or if {@code null} is passed to the varargs groups* @throws ValidationException if a non recoverable error happens* during the validation process*/<T> Set<ConstraintViolation<T>> validate(T object, Class<?>... groups);
ConstraintViolation类源码:
public interface ConstraintViolation<T> {/*** @return the interpolated error message for this constraint violation*/String getMessage();/*** @return the non-interpolated error message for this constraint violation*/String getMessageTemplate();/*** Returns the root bean being validated. For method validation, returns* the object the method is executed on.* <p/>* Returns {@code null} when:* <ul>* <li>the {@code ConstraintViolation} is returned after calling* {@link Validator#validateValue(Class, String, Object, Class[])}</li>* <li>the {@code ConstraintViolation} is returned after validating a* constructor.</li>* </ul>** @return the validated object, the object hosting the validated element or {@code null}*/T getRootBean();/*** Returns the class of the root bean being validated.* For method validation, this is the object class the* method is executed on.* For constructor validation, this is the class the constructor* is declared on.** @return the class of the root bean or of the object hosting the validated element*/Class<T> getRootBeanClass();/*** Returns:* <ul>* <li>the bean instance the constraint is applied on if it is* a bean constraint</li>* <li>the bean instance hosting the property the constraint* is applied on if it is a property constraint</li>* <li>{@code null} when the {@code ConstraintViolation} is returned* after calling {@link Validator#validateValue(Class, String, Object, Class[])}* </li>* <li>the object the method is executed on if it is* a method parameter, cross-parameter or return value constraint</li>* <li>{@code null} if it is a constructor parameter or* cross-parameter constraint</li>* <li>the object the constructor has created if it is a* constructor return value constraint</li>* </ul>** @return the leaf bean*/Object getLeafBean();/*** Returns an {@code Object[]} representing the constructor or method invocation* arguments if the {@code ConstraintViolation} is returned after validating the* method or constructor parameters.* Returns {@code null} otherwise.** @return parameters of the method or constructor invocation or {@code null}** @since 1.1*/Object[] getExecutableParameters();/*** Returns the return value of the constructor or method invocation* if the {@code ConstraintViolation} is returned after validating the method* or constructor return value.* <p/>* Returns {@code null} if the method has no return value.* Returns {@code null} otherwise.** @return the method or constructor return value or {@code null}** @since 1.1*/Object getExecutableReturnValue();/*** @return the property path to the value from {@code rootBean}*/Path getPropertyPath();/*** Returns the value failing to pass the constraint.* For cross-parameter constraints, an {@code Object[]} representing* the method invocation arguments is returned.** @return the value failing to pass the constraint*/Object getInvalidValue();/*** Returns the constraint metadata reported to fail.* The returned instance is immutable.** @return constraint metadata*/ConstraintDescriptor<?> getConstraintDescriptor();/*** Returns an instance of the specified type allowing access to* provider-specific APIs. If the Bean Validation provider* implementation does not support the specified class,* {@link ValidationException} is thrown.** @param type the class of the object to be returned* @return an instance of the specified class* @throws ValidationException if the provider does not support the call** @since 1.1*/<U> U unwrap(Class<U> type);
}
例子中主要用到了getMessage()和getPropertyPath()