本文主要讲述如何使用hibernate validator来校验入参,避免在业务代码里进行每一个接口进行入参校验,提搞代码的简洁及欣赏性。 主要涉及针对接口方法的入参简单校验,不涉及使用group进行的组合校验及其余。java
<!-- 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
web
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(); } }
ValidatorFactory validatorFactory = Validation.byProvider(HibernateValidator.class) .configure() .failFast(true) .buildValidatorFactory(); Validator validator = validatorFactory.getValidator();
failFast
默认为false
,即会校验彻底部参数后再返回所有参数的校验结果信息.failFast(true)
也可用.addProperty("hibernate.validator.fail_fast", "true")
替代,如果用的defaultProvider,即Validation.byDefaultProvider()
,则只能使用后者如果经过上面方法一实例化validator,则不须要手动校验spring
如果使用的方法二,则可经过下面方法来校验方法入参api
Set<ConstraintViolation<Object>> constraintViolationSet = validator.forExecutables().validateParameters(bean, method, args);
bean
是接口实现bean
,非入参bean
validator.validate(arg)
来遍历校验单个参数,但要求arg
不能为null
,有些接口方法是平铺入参,且部分入参可为null
的则不适应能够经过AOP或Filter来处理方法入参校验tomcat
javax.validation.ConstraintViolationException
异常便可,而后e.getConstraintViolations()
便可获取到Set<ConstraintViolation>
Set<ConstraintViolation>
// 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);
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(@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) { // .... } }
@Valid
注解,不然大参数里的属性不会校验@Validated
注解若不指定message,则会返回默认的message,即注解的message默认值,如@NotNull
注解默认message占位符是{javax.validation.constraints.NotNull.message}
,以下图
根据占位符可搜索到在hibernate-validator
包下的Resource配置文件中,以下图
里面有对应的中文版本,以下图
上图上有各类语言版本,针对中文版的内容使用ASCII码,可经过工具转成native查看具体的message。app
缘由是包冲突,根本缘由是引入hibernate-validator依赖包后出现了validation-api的1.1.0.Final版本,应用中依赖的spring-boot中声明了validation-api-1.1.0.Final
包,因此在引入时出现了冲突。 解决:能够显示在parent的POM中显示依赖validation-api-2.0.1.Final
便可。ide
缘由是没有依赖el相关包,增长以下包依赖便可spring-boot
<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>
可依赖如下包,即包含全部依赖,如有依赖包冲突则一样需单独处理工具
<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.Final
、tomcat-embed-el-8.5.31
和spring-boot-starter-1.5.13.RELEASE
3个包ui