Hibernate Validator简单使用

使用的主要的作用:进行注解式的参数校验——让代码更少、更加专注于业务逻辑

参数验证是一个常见的问题,例如验证用户输入的密码是否为空、邮箱是否合法等。但是无论是前端还是后台,都需对用户输入进行验证,以此来保证系统数据的正确性。对于web来说,有些人可能理所当然的想在前端验证就行了,但这样是非常错误的做法,前台的验证一般是通过JavaScript,js代码是可以被禁用和篡改的,所以相对后台检验而言,安全性会低一些。前端代码对于用户来说是透明的,稍微有点技术的人就可以绕过这个验证,直接提交数据到后台。无论是前端网页提交的接口,还是提供给外部的接口,参数验证随处可见,也是必不可少的。总之,一切用户的输入都是不可信的。

基于这样的常识,在后端的代码开发中,参数校验是一个永远也绕不开的话题。然而编写参数校验代码的过程是一个技术含量不高,及其耗时,繁琐的过程。比如极大多数的参数校验代码就是:判断一下用户名是否已经存在、用户名长度是否满足要求、用户填写的邮箱是否合法。年龄参数是不是一个整数等等。为了减少重复代码的开发,许多有技术积淀的公司,一般都会提供一套或多套特有的参数校验工具类。以此减少代码量。这种做法在项目中非常普遍,有了这些工具类库,程序员在编写业务代码的过程中,工作效率可以大大提升。

然而,即便聪明如上述做法,我们的业务逻辑中依然还是可以见到大量的参数校验逻辑,倘若项目架构的不够合理,这些与参数校验逻辑有关的代码量会更多,真是XXX的裹脚布,又臭又长。大量繁杂的参数校验代码混杂在业务逻辑中,一来降低了代码的可读性;二是让人对业务本身的理解难度加大,很多刚加入公司的人往往是通过读码来理解业务的,公司的一些业务培训一般只能讲个大概,然而在阅读代码的过程中稍有不慎便会被这些“额外”的代码扰乱思路,对于新手,那更是异常噩梦,倘若老员工辞职了,撒手抛给新来的,这样的项目能不能维护下去都是个问题了。

以上参考:http://blog.csdn.net/nmgrd/article/details/57088192

Hibernate Validator

Express validation rules in a standardized way using annotation-based constraints and benefit from transparent integration with a wide variety of frameworks.(标准化方式使用基于注释的约束来表达验证规则,并从与各种框架的透明集成中受益),可以扩展,可自定义约束的类型。Hibernate Validator 5.x is the reference implementation Bean Validation 1.1!。hibernate Validator是 Bean Validation 的参考实现,Hibernate Validator 提供了 JSR 303 规范中所有内置 constraint 的实现,除此之外还有一些附加的 constraint(约束)。为了满足特定的需求,用户还可以自实现更多的constraint以便满足特定的需求。
网址:http://hibernate.org/validator/
参考文档:http://docs.jboss.org/hibernate/stable/validator/reference/en-US/html_single/#validator-gettingstarted-createproject

实际的场景

在后台的业务逻辑中,对数据值的校验在各层都存在(展示层,业务层,数据访问层等),并且各层校验的规则又不尽相同,在各层中重复的校验逻辑既导致了不必要的资源消耗,还使得逻辑不够单一(每层都夹杂着校验的逻辑),JSR 303 Bean Validation就是在这种背景下产生的一个数据验证的J2EE规范。使用起来非常的简单规范,而且校验的规则的代码都是一样的,都是基于JavaBean的注解的校验。

实际的使用

** 引入需要的maven配置

       <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>5.4.0.Final</version>
        </dependency>
        <dependency>
            <groupId>javax.el</groupId>
            <artifactId>el-api</artifactId>
            <version>2.2</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.glassfish.web</groupId>
            <artifactId>javax.el</artifactId>
            <version>2.2.6</version>
        </dependency>

* 创建需要校验的类*

package com.common.utils.Hibernatevalidatedemo;

import org.hibernate.validator.constraints.Email;

import javax.validation.constraints.*;
import java.util.Date;

/**
 * descrption: 测试类,看看Validate
 * authohr: wangji
 * date: 2017-08-12 10:36
 */
public class ValidateInfoBean {

    @NotNull(message = "姓名不能为空!")
    @Min(value = 1, message = "Id只能大于等于1,小于等于10")
    @Max(value = 10, message = "Id只能大于等于1,小于等于10")
    private Integer id;

    @NotNull(message = "姓名不能为空!")
    @Size(min = 2, max = 4, message = "姓名长度必须在{min}和{max}之间")
    @Pattern(regexp = "[\u4e00-\u9fa5]+", message = "名称只能输入是中文字符")
    private String userName;

    @NotNull(message = "密码不能为空!")
    @Size(min = 6, max = 12, message = "密码长度必须在{min}和{max}之间")
    private String passWord;

    @NotNull(message = "日期不能为空!")
    @Past(message = "你只能输入过去的日期")
    private Date birthday;

    @NotNull(message = "邮件不能为空!")
    @Email(message = "邮件格式不正确")
    private String email;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getPassWord() {
        return passWord;
    }

    public void setPassWord(String passWord) {
        this.passWord = passWord;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }
}

其中该类中用到Max,Min,NotNull,Size等都是JSR 303中内置的约束条件(constraint),还有一些是Hibernate扩充的约束,我们自己也是可以扩充这个约束进行使用。下面看看如何验证吧。

开始校验首先获取校验器

  ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();
    Validator validator = validatorFactory.getValidator();

创建一个校验类的实例

        ValidateInfoBean infoBean = new ValidateInfoBean();
        infoBean.setId(-1);
        infoBean.setUserName("中国wj");
        infoBean.setPassWord("12345");
        infoBean.setEmail("testt.com");
        infoBean.setBirthday(new Date(2015,3,2));

校验一共有几种校验的方式(返回的都是违反约束的字段的集合)

 //特定类实例,然后分组(就是一个校验的标识,确定先后顺序,是否校验等)
 <T> Set<ConstraintViolation<T>> validate(T object, Class< ?>... groups);

 //特定实例上的某个字段
<T> Set<ConstraintViolation<T>> validateProperty(T object,
                                                     String propertyName,
                                                     Class< ?>... groups);

 //使用某个类上的某个字段进行校验
 <T> Set<ConstraintViolation<T>> validateValue(Class<T> beanType,
                                                  String propertyName,
                                                  Object value,
                                                  Class<?>... groups);

输出函数:

public static void pringValidateStr(Set<ConstraintViolation<ValidateInfoBean>> set2) {
        for (ConstraintViolation<ValidateInfoBean> constraintViolation : set2){
            log.info("错误:" + constraintViolation.getMessage());
            log.info("字段:"+constraintViolation.getPropertyPath().toString());

        }
    }

校验所有的字段

  Set<ConstraintViolation<ValidateInfoBean>> set = validator.validate(infoBean);
        pringValidateStr(set);

    2017-08-12 13:54:50,931  INFO [Version.java:30] : HV000001: Hibernate Validator 5.4.0.Final
    2017-08-12 13:54:51,251  INFO [ValidateTest.java:52] : 错误:你只能输入过去的日期
    2017-08-12 13:54:51,251  INFO [ValidateTest.java:53] : 字段:birthday
    2017-08-12 13:54:51,251  INFO [ValidateTest.java:52] : 错误:Id只能大于等于1,小于等于10
    2017-08-12 13:54:51,252  INFO [ValidateTest.java:53] : 字段:id
    2017-08-12 13:54:51,252  INFO [ValidateTest.java:52] : 错误:名称只能输入是中文字符
    2017-08-12 13:54:51,253  INFO [ValidateTest.java:53] : 字段:userName
    2017-08-12 13:54:51,253  INFO [ValidateTest.java:52] : 错误:邮件格式不正确
    2017-08-12 13:54:51,253  INFO [ValidateTest.java:53] : 字段:email
    2017-08-12 13:54:51,253  INFO [ValidateTest.java:52] : 错误:密码长度必须在612之间
    2017-08-12 13:54:51,253  INFO [ValidateTest.java:53] : 字段:passWord

特定实例上的某个字段

Set<ConstraintViolation<ValidateInfoBean>> set3 =validator.validateProperty(infoBean,"userName");
        pringValidateStr(set3);
    2017-08-12 13:59:14,262  INFO [Version.java:30] : HV000001: Hibernate Validator 5.4.0.Final
    2017-08-12 13:59:14,556  INFO [ValidateTest.java:52] : 错误:名称只能输入是中文字符
    2017-08-12 13:59:14,557  INFO [ValidateTest.java:53] : 字段:userName

使用某个类上的某个字段进行校验

 Set<ConstraintViolation<ValidateInfoBean>> set2 =validator.validateValue(ValidateInfoBean.class,"userName","中国lihai");
        pringValidateStr(set2);
    2017-08-12 14:00:32,533  INFO [Version.java:30] : HV000001: Hibernate Validator 5.4.0.Final
    2017-08-12 14:00:33,136  INFO [ValidateTest.java:52] : 错误:名称只能输入是中文字符
    2017-08-12 14:00:33,136  INFO [ValidateTest.java:53] : 字段:userName
    2017-08-12 14:00:33,137  INFO [ValidateTest.java:52] : 错误:姓名长度必须在24之间
    2017-08-12 14:00:33,137  INFO [ValidateTest.java:53] : 字段:userName

还有很多这样的约束

  @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(value) 被注释的元素必须符合指定的正则表达式
   表 2. Hibernate Validator 附加的 constraint
   @Email 被注释的元素必须是电子邮箱地址
   @Length 被注释的字符串的大小必须在指定的范围内
   @NotEmpty 被注释的字符串的必须非空
   @Range 被注释的元素必须在合适的范围内

还有校验分组,确定校验哪些,校验的顺序,就是一个简单的标识,可以随便创建一个标识的类的信息。这里创建了两个空的接口。除此之外还有很多的使用,比如继承,级联,详情见官网,这里仅仅简单的查看如何使用。

package com.common.utils.Hibernatevalidatedemo;

import lombok.extern.slf4j.Slf4j;

import javax.validation.*;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Past;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
import java.util.Date;
import java.util.Set;

/**
 * descrption: 校验分组
 * authohr: wangji
 * date: 2017-08-12 14:04
 */
@GroupSequence({First.class,Second.class,ValidateGroup.class})//类界别校验的顺序
@Slf4j
public class ValidateGroup {

    @NotNull(message = "姓名不能为空!", groups = {First.class})
    @Size(min = 2, max = 4, message = "姓名长度必须在{min}和{max}之间",groups = {First.class})
    @Pattern(regexp = "[\u4e00-\u9fa5]+", message = "名称只能输入是中文字符",groups = {First.class})
    private String userName;

    @NotNull(message = "密码不能为空!",groups = {Second.class})
    @Size(min = 6, max = 12, message = "密码长度必须在{min}和{max}之间",groups = {Second.class})
    private String passWord;

    @NotNull(message = "日期不能为空!")
    @Past(message = "你只能输入过去的日期")
    private Date birthday;

    public static void main(String[] args) {
        ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();
        Validator validator = validatorFactory.getValidator();
        ValidateGroup testFirst = new ValidateGroup();
        testFirst.setUserName("wangji");
        //下面这里使用来分类进行校验,通过Group唯一标识进行区别,也可以使用多个进行先后顺序的校验
        //还可以进行类界别的校验顺序@GroupSequence,如果没有定义Group那么就会使用,当前类进行标识
       // pringValidateStr(validator.validate(testFirst,First.class));
//        2017-08-12 14:22:13,899  INFO [ValidateGroup.java:44] : 错误:姓名长度必须在2和4之间
//        2017-08-12 14:22:13,900  INFO [ValidateGroup.java:45] : 字段:userName
//        2017-08-12 14:22:13,900  INFO [ValidateGroup.java:44] : 错误:名称只能输入是中文字符
//        2017-08-12 14:22:13,900  INFO [ValidateGroup.java:45] : 字段:userName


//        通过@GroupSequence指定验证顺序:
//        先验证First分组,如果有错误立即返回
//        而不会验证Second分组,接着如果First分组验证通过了,
//        那么才去验证Second分组,最后指定User.class表示那些没有分组的在最后。
//        这样我们就可以实现按顺序验证分组了。
         pringValidateStr(validator.validate(testFirst));
//        输出的只是第一个校验错误,其他的不继续校验了
//        2017-08-12 14:27:46,378  INFO [Version.java:30] : HV000001: Hibernate Validator 5.4.0.Final
//        2017-08-12 14:27:46,649  INFO [ValidateGroup.java:55] : 错误:姓名长度必须在2和4之间
//        2017-08-12 14:27:46,650  INFO [ValidateGroup.java:56] : 字段:userName
//        2017-08-12 14:27:46,650  INFO [ValidateGroup.java:55] : 错误:名称只能输入是中文字符
//        2017-08-12 14:27:46,650  INFO [ValidateGroup.java:56] : 字段:userName


    }
    public static void pringValidateStr(Set<ConstraintViolation<ValidateGroup>> set2) {
        for (ConstraintViolation<ValidateGroup> constraintViolation : set2){
            log.info("错误:" + constraintViolation.getMessage());
            log.info("字段:"+constraintViolation.getPropertyPath().toString());

        }
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getPassWord() {
        return passWord;
    }

    public void setPassWord(String passWord) {
        this.passWord = passWord;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }
}

以上就是简单的使用,还有很多的新特性,可以参考官方上的说明进行简单的查看。

网址: https://github.com/WangJi92/mybatits-study/blob/master/mybatis-study/study-6-spring-Hibernate/src/main/java/com/common/utils/Hibernatevalidatedemo/ValidateInfoBean.java

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
HibernateValidatorJSR303的参考实现使用指南.pdf JSR 303 的参考实现 使用指南 由 Hardy Ferentschik和Gunnar Morling and thanks to Shaozhuang Liu 4.3.1.Final 版权 © 2009 - 2011 Red Hat, Inc. & Gunnar Morling June 20, 2011 序言 1. 开始入门 1.1. 第一个Maven项目 1.2. 添加约束 1.3. 校验约束 1.4. 更进一步 2. Validation step by step 2.1. 定义约束 2.1.1. 字段级(field level) 约束 2.1.2. 属性级别约束 2.1.3. 类级别约束 2.1.4. 约束继承 2.1.5. 对象图 2.2. 校验约束 2.2.1. 获取一个Validator的实例 2.2.2. Validator中的方法 2.2.3. ConstraintViolation 中的方法 2.2.4. 验证失败提示信息解析 2.3. 校验组 2.3.1. 校验组序列 2.3.2. 对一个类重定义其默认校验组 2.4. 内置的约束条件 2.4.1. Bean Validation constraints 2.4.2. Additional constraints 3. 创建自己的约束规则 3.1. 创建一个简单的约束条件 3.1.1. 约束标注 3.1.2. 约束校验器 3.1.3. 校验错误信息 3.1.4. 应用约束条件 3.2. 约束条件组合 4. XML configuration 4.1. validation.xml 4.2. 映射约束 5. Bootstrapping 5.1. Configuration 和 ValidatorFactory 5.2. ValidationProviderResolver 5.3. MessageInterpolator 5.3.1. ResourceBundleLocator 5.4. TraversableResolver 5.5. ConstraintValidatorFactory 6. Metadata API 6.1. BeanDescriptor 6.2. PropertyDescriptor 6.3. ElementDescriptor 6.4. ConstraintDescriptor 7. 与其他框架集成 7.1. OSGi 7.2. 与数据库集成校验 7.3. ORM集成 7.3.1. 基于Hibernate事件模型的校验 7.3.2. JPA 7.4. 展示层校验 8. Hibernate Validator Specifics 8.1. Public API 8.2. Fail fast mode 8.3. Method validation 8.3.1. Defining method-level constraints 8.3.2. Evaluating method-level constraints 8.3.3. Retrieving method-level constraint meta data 8.4. Programmatic constraint definition 8.5. Boolean composition for constraint composition 9. Annotation Processor 9.1. 前提条件 9.2. 特性 9.3. 配置项 9.4. 使用标注处理器 9.4.1. 命令行编译 9.4.2. IDE集成 9.5. 已知问题 10. 进一步阅读

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值