但行好事  莫问前程

Hibernate validator的使用和自定义validator及与Spring MVC的整合

一. Hibernate validator的基本使用

1.1 Hibernate validator使用准备条件
使用之前需要导入validation-api-xxx.jar以及hibernate-validator-xxx.Final.jar,我使用的是和validation-api-1.1.0.Alpha1.jarhibernate-validator-5.0.0.Alpha1.jar,maven依赖是:

<!-- hibernate validator -->
    <dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>5.0.0.Alpha1</version>
   </dependency>

1.2 编写需要检查的java bean,Entity.java如下所示:

package org.light4j.validate;

import javax.validation.constraints.Max;
import org.hibernate.validator.constraints.Length;

public class Entity {    
    @Max(value=3)//最大值为3    
    private int age;    
    @Length(max=1) //字符串长度最大为1,hibernate 扩展的 
    private String name;    
    public int getAge() {    
        return age;    
    }    
    public void setAge(int age) {    
        this.age = age;    
    }    
    public String getName() {    
        return name;    
    }    
    public void setName(String name) {    
        this.name = name;    
    }    
}

1.3 编写测试类Test.java如下所示:

package org.light4j.validate;

import java.util.Iterator;
import java.util.Set;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;

public class Test {
    public static void main(String[] args) {  
        ValidatorFactory factory = Validation.buildDefaultValidatorFactory();  
        Validator validator = factory.getValidator();  

        Entity entity = new Entity();  
        entity.setAge(12);  
        entity.setName("admin");  
        Set<ConstraintViolation<Entity>> constraintViolations = validator.validate(entity);  
        for (ConstraintViolation<Entity> constraintViolation : constraintViolations) {  
            System.out.println("对象属性:"+constraintViolation.getPropertyPath());  
            System.out.println("国际化key:"+constraintViolation.getMessageTemplate());  
            System.out.println("错误信息:"+constraintViolation.getMessage());  
        }  

    }  
}

运行输出结果如下所示:

对象属性:age
国际化key:{javax.validation.constraints.Max.message}
错误信息:最大不能超过3
对象属性:name
国际化key:{org.hibernate.validator.constraints.Length.message}
错误信息:长度需要在0和1之间

这里有一个国际化的key值,国际化文件在org.hibernate.validator下面的一系列的properites文件里面,如果需要自定义那么可以拷贝出来放在src目录下,截图如下:
1
这里我们拷贝一个出来,新增一个key为maxlength=字符串长度最大不能超过{max} ,可以使用动态参数,这里的max值就是注解里面设定的值,然后修改Entity.java,name属性的message=”{maxlength}”

@Length(max=1,message="{maxlength}") //{maxlength}对应配置文件中的key. 必须有{}  
    private String name;

再次运行结果如下:
1
二. 自定义validator
2.1 首先自定义一个注解CannotContainSpaces (不能包含空格)

package org.light4j.validate;

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import javax.validation.Constraint;
import javax.validation.Payload;

@Constraint(validatedBy = CannotContainSpacesValidator.class)
// 具体的实现
@Target({ java.lang.annotation.ElementType.METHOD,
        java.lang.annotation.ElementType.FIELD })
@Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
@Documented
public @interface CannotContainSpaces {
    String message() default "{Cannot.contain.Spaces}"; // 提示信息,可以写死,可以填写国际化的key

    int length() default 5;

    // 下面这两个属性必须添加
    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};
}

2.2 编写具体实现类CannotContainSpacesValidator.java

package org.light4j.validate;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

public class CannotContainSpacesValidator implements ConstraintValidator<CannotContainSpaces, String> {    
    private int len;    
    /**  
     * 初始参数,获取注解中length的值  
     */    
    @Override    
    public void initialize(CannotContainSpaces arg0) {    
        this.len = arg0.length();    
    }    

    @Override    
    public boolean isValid(String str, ConstraintValidatorContext constraintValidatorContext) {    
        if(str != null){    
            if(str.indexOf(" ") < 0){    
                return true;    
            }    
        }else{    
            constraintValidatorContext.disableDefaultConstraintViolation();//禁用默认的message的值    
            //重新添加错误提示语句    
            constraintValidatorContext.buildConstraintViolationWithTemplate("字符串不能为空").addConstraintViolation();    
        }    
        return false;    
    }    

} 

2.3 使用的时候直接注解到对象的属性上面就可以了。

@CannotContainSpaces  
  private String name; 

测试当name包含空格的时候entity.setName(“xx xx”);
1
当name为null的时候
1

三. 整合Spring MVC使用

3.1 首先新增配置文件内容(实体类里面的注解与上面完全相同)

<!-- 国际化配置 -->  
<bean id="localeResolver"  
    class="org.springframework.web.servlet.i18n.CookieLocaleResolver" />  
<bean id="messageSource"  
    class="org.springframework.context.support.ReloadableResourceBundleMessageSource">  
    <property name="basenames">  
        <list>  
            <value>classpath:messages/messages</value>  
            <value>classpath:messages/Validation</value>  
        </list>  
    </property>  
    <property name="useCodeAsDefaultMessage" value="true" />  
</bean>  
<!-- 注册验证器 -->  
<mvc:annotation-driven validator="validator" />    

<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">    
      <property name="providerClass" value="org.hibernate.validator.HibernateValidator"/>    
      <!-- 这里配置将使用上面国际化配置的messageSource -->  
      <property name="validationMessageSource" ref="messageSource"/>    
  </bean>

3.2 在Spring MVC 控制器中方法属性如下

        /** 
         * 这里的@Valid必须书写, bindingResult参数也必须书写在后面,否则验证不通过就会返回400 
         * @param entity 
         * @param result 
         * @return 
         */  
        @RequestMapping(value="/valid")  
        public String validator(@Valid Entity entity,BindingResult result){  
            if(result.hasErrors()){  
                //如果严重没有通过,跳转提示  
                return "error";  
            }else{  
                //继续业务逻辑  
            }  
      return "success";  
 }

3.3 error.jsp中如下
导入spring标签库

<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%>

使用方式如下:

<!-- commandName 控制器参数中对象名称 -->  
<form:form commandName="entity">  
    <!-- 显示全部错误信息用* -->  
    <form:errors path="*"/>  
</form:form>  
<hr/>  
<!-- 对象名称.属性名称    如果该对象的指定属性没有通过校验那么显示错误信息(根据当前语言显示不同国家的文字) -->  
<form:errors path="entity.name"/>  

四. 校验注解说明

Bean Validation 中内置的 constraint     
@Null   被注释的元素必须为 null     
@NotNull    被注释的元素必须不为 null     
@AssertTrue     被注释的元素必须为 true     
@AssertFalse    被注释的元素必须为 false     
@Min(value)     被注释的元素必须是一个数字,其值必须大于等于指定的最小值     
@Max(value)     被注释的元素必须是一个数字,其值必须小于等于指定的最大值     
@DecimalMin(value)  被注释的元素必须是一个数字,其值必须大于等于指定的最小值     
@DecimalMax(value)  被注释的元素必须是一个数字,其值必须小于等于指定的最大值     
@Size(max=, min=)   被注释的元素的大小必须在指定的范围内     
@Digits (integer, fraction)     被注释的元素必须是一个数字,其值必须在可接受的范围内     
@Past   被注释的元素必须是一个过去的日期     
@Future     被注释的元素必须是一个将来的日期     
@Pattern(regex=,flag=)  被注释的元素必须符合指定的正则表达式     
Hibernate Validator 附加的 constraint     
@NotBlank(message =)   验证字符串非null,且长度必须大于0     
@Email  被注释的元素必须是电子邮箱地址     
@Length(min=,max=)  被注释的字符串的大小必须在指定的范围内     
@NotEmpty   被注释的字符串的必须非空     
@Range(min=,max=,message=)  被注释的元素必须在合适的范围内  

五. 注意

注意
①:在整合Spring MVC的时候,ValidationMessages_zh_CN.properties文件如果不是放在src目录下(如上面放在src/messages/下面) 那么在属性文件里面不能使用动态参数获取了(如${length} ${max}这些). 必须将hibernate validation的国际化属性全部放到src目录下面才可以(不晓得为什么,如果你能解决顺便留个言)

②:我这里使用的是spring 4.1 + hibernate validation 5.0 ,如果你使用的是spring 3.2 需要对于的hibernate validation版本是 4.x的 不然在配置

org.springframework.validation.beanvalidation.LocalValidatorFactoryBean 

这个的时候会报错。

打赏
欢迎关注人生设计师的微信公众账号
公众号ID:longjiazuoA

未经允许不得转载:人生设计师 » Hibernate validator的使用和自定义validator及与Spring MVC的整合

分享到:更多 ()

人生设计师-接受不同的声音

联系我关于我