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

ValidatorFactory validatorFactory = Validation.byProvider(HibernateValidator.class)
    .configure()
    .failFast(true)  // 是否仅输出第一个校验失败的信息
    .buildValidatorFactory();
Validator validator = validatorFactory.getValidator();

上面的.failFast(true)也可用.addProperty("hibernate.validator.fail_fast", "true")替代,若是用的defaultProvider,即Validation.byDefaultProvider(),则只能使用后者

校验接口方法入参

Set<ConstraintViolation<Object>> constraintViolationSet = validator.forExecutables().validateParameters(bean, method, args);

if (constraintViolationSet.isEmpty()) {
    return null;
}

StringBuilder errorMsg = new StringBuilder();
for (ConstraintViolation violation : constraintViolationSet) {
    errorMsg.append(";");
    errorMsg.append(violation.getMessage());
}
return errorMsg.substring(1);
  • 也可使用validator.validate(arg)来遍历校验单个参数,但要求arg不能为null,有些接口方法是平铺入参,且部分入参可为null的则不适应
  • 校验入口可放在AOP或Filter中使用

使用示例

入参类

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

}

接口方法

import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;

public interface UserService {

    void register1(@Valid @NotNull(message = "请求入参不能为空") User user);

    void register2(@NotBlank(message = "名称不能为空") String name, Integer age);

}

注:若入参是个大参数,如register1的入参,则必须加@Valid注解,否则大参数里的属性不会校验

FAQ

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

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

报错“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即可。

报错“”

原因是没有依赖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>

TO BE CONTINUED...

  • config bean
  • spring-boot-starter-validation
11-08 18:41