zoukankan      html  css  js  c++  java
  • Hibernate Validator

    一、POM依赖

    <!-- dependency>
        <groupId>javax.validation</groupId>
        <artifactId>validation-api</artifactId>
        <version>2.0.1.Final</version>
    </dependency -->
    <dependency>
        <groupId>org.hibernate.validator</groupId>
        <artifactId>hibernate-validator</artifactId>
        <version>6.0.13.Final</version>
    </dependency>
    <dependency>
        <groupId>javax.el</groupId>
        <artifactId>javax.el-api</artifactId>
        <version>3.0.1-b06</version>
    </dependency>
    <dependency>
        <groupId>org.glassfish.web</groupId>
        <artifactId>javax.el</artifactId>
        <version>2.2.6</version>
    </dependency>
    

    注:hibernate-validator-6.0.13.Final本身依赖validation-api的版本即是2.0.1.Final,若无冲突,则无需单独显式依赖validation-api-2.0.1.Final

    二、初始化Validator

    2.1 方法一 注册Bean实现

    import org.hibernate.validator.HibernateValidator;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.validation.beanvalidation.MethodValidationPostProcessor;
    import javax.validation.Validation;
    import javax.validation.Validator;
    import javax.validation.ValidatorFactory;
    
    @Configuration
    public class ValidatorConfig {
    
        @Bean
        public MethodValidationPostProcessor methodValidationPostProcessor(@Qualifier("validator") Validator validator) {
            MethodValidationPostProcessor processor = new MethodValidationPostProcessor();
            processor.setValidator(validator);	// 若不定制validator,此处可不用set
            return processor;
        }
    
        @Bean
        public Validator validator() {
            ValidatorFactory validatorFactory = Validation.byProvider(HibernateValidator.class)
                    .configure()
                    .failFast(true)
                    .buildValidatorFactory();
            return validatorFactory.getValidator();
        }
    
    }
    

    2.2 方法二 手动实例化validator

    ValidatorFactory validatorFactory = Validation.byProvider(HibernateValidator.class)
        .configure()
        .failFast(true)
        .buildValidatorFactory();
    Validator validator = validatorFactory.getValidator();
    

    2.3 补充说明

    • failFast默认为false,即会校验完全部参数后再返回全部参数的校验结果信息
    • .failFast(true)也可用.addProperty("hibernate.validator.fail_fast", "true")替代,若是用的defaultProvider,即Validation.byDefaultProvider(),则只能使用后者

    三、校验接口方法入参

    3.1 方法一

    若是通过上面方法一实例化validator,则不需要手动校验

    3.2 方法二

    若是使用的方法二,则可通过下面方法来校验方法入参

    Set<ConstraintViolation<Object>> constraintViolationSet = validator.forExecutables().validateParameters(bean, method, args);
    
    • 入参bean是接口实现bean,非入参bean
    • 也可使用validator.validate(arg)来遍历校验单个参数,但要求arg不能为null,有些接口方法是平铺入参,且部分入参可为null的则不适应

    四、获取校验失败返回信息

    可以通过AOP或Filter来处理方法入参校验

    4.1 获取校验结果

    • 若是通过上面方法一,则直接捕捉javax.validation.ConstraintViolationException异常即可,然后e.getConstraintViolations()即可获取到Set<ConstraintViolation>
    • 若是通过上面方法二,则校验结果直接返回了Set<ConstraintViolation>

    4.2 拼装校验信息

    // constraintViolationSet = 上面校验结果Set
    if (constraintViolationSet.isEmpty()) {
        return null;
    }
    StringBuilder errorMsg = new StringBuilder();
    for (ConstraintViolation violation : constraintViolationSet) {
        errorMsg.append(";");
        errorMsg.append(violation.getMessage());
    }
    return errorMsg.substring(1);
    

    五、使用示例

    5.1 入参类

    import javax.validation.constraints.Min;
    import javax.validation.constraints.NotBlank;
    import javax.validation.constraints.NotNull;
    
    public class User {
    
        @NotBlank(message = "名称不能为空")
        private String name;
    
        @NotNull(message = "年龄不能为空")
        @Min(value = 1, message = "年龄不能小于{value}")
        private Integer age;
    
        // .... getters and setters
    
    }
    

    5.2 接口方法

    // 接口
    import javax.validation.Valid;
    import javax.validation.constraints.NotBlank;
    import javax.validation.constraints.NotNull;
    
    public interface UserService {
    
        void register1(@NotNull(message = "请求入参不能为空") @Valid User user);
    
        void register2(@NotBlank(message = "名称不能为空") String name, Integer age);
    
    }
    
    // 实现类
    import org.springframework.validation.annotation.Validated;
    
    @Validated
    public class UserServiceImpl implements UserService {
    
        public void register1(User user) {
    		// ....
    	}
    
        public void register2(String name, Integer age) {
    		// ....
    	}
    
    }
    
    • 若入参是个大参数,如register1的入参,则必须加@Valid注解,否则大参数里的属性不会校验
    • 实现类上必须加@Validated注解

    六、FAQ

    6.1 若不指定校验失败的message,则会返回什么

    若不指定message,则会返回默认的message,即注解的message默认值,如@NotNull注解默认message占位符是{javax.validation.constraints.NotNull.message},如下图 
    根据占位符可搜索到在hibernate-validator包下的Resource配置文件中,如下图 
    里面有对应的中文版本,如下图 
    上图上有各种语言版本,针对中文版的内容使用ASCII码,可通过工具转成native查看具体的message。

    6.2 报错“Caused by: java.lang.NoClassDefFoundError: org/hibernate/validator/internal/engine/DefaultClockProvider”

    原因是包冲突,根本原因是引入hibernate-validator依赖包后出现了validation-api的1.1.0.Final版本,应用中依赖的spring-boot中声明了validation-api-1.1.0.Final包,所以在引入时出现了冲突。 解决:可以显示在parent的POM中显示依赖validation-api-2.0.1.Final即可。

    6.3 报错“HV000183: Unable to initialize 'javax.el.ExpressionFactory'. Check that you have the EL dependencies on the classpath, or use ParameterMessageInterpolator instead”

    原因是没有依赖el相关包,增加如下包依赖即可

    <dependency>
        <groupId>javax.el</groupId>
        <artifactId>javax.el-api</artifactId>
        <version>3.0.1-b06</version>
    </dependency>
    <dependency>
        <groupId>org.glassfish.web</groupId>
        <artifactId>javax.el</artifactId>
        <version>2.2.6</version>
    </dependency>
    

    6.4 如何依赖一个包即可包含上面包的所有依赖

    可依赖以下包,即包含所有依赖,若有依赖包冲突则同样需单独处理

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-validation</artifactId>
        <version>2.1.0.RELEASE</version>
    </dependency>
    

    上面spring-boot-starter-validation包无其他逻辑,仅单纯依赖了hibernate-validator-6.0.13.Finaltomcat-embed-el-8.5.31spring-boot-starter-1.5.13.RELEASE3个包

  • 相关阅读:
    PHP获取指定分钟数的下一个整数倍
    phpspreadsheet
    澳大利亚 主要城市列表
    db2编目抽取
    openssl实现CA自签证书和颁发数字证书
    基于Docker的redis集群搭建
    Python测试DB2连通性
    在Vim中查看文件编码
    搭建redis集群
    Python(十)之GUI编程
  • 原文地址:https://www.cnblogs.com/hyl8218/p/10912290.html
Copyright © 2011-2022 走看看