当前位置: 首页 > news >正文

小架构step系列27:Hibernate提供的validator

1 概述

直接使用Spring提供的Validation机制来校验请求参数比较麻烦,还好hibernate-validator包提供了注解的方式,在参数对象的属性上加上对应的注解,即可进行校验,这样就方便多了。本文来了解一下hibernate-validator是如何把Spring的Validation机制扩展成用注解这种便利方式的。

2 原理

2.1 加载过程

1) 先依赖hibernate-validator包:

<dependency><groupId>org.hibernate.validator</groupId><artifactId>hibernate-validator</artifactId>
</dependency><!-- 在spring-boot-dependencies里有管理配置 -->
<properties><hibernate-validator.version>6.2.5.Final</hibernate-validator.version>
</properties>
<dependency><groupId>org.hibernate.validator</groupId><artifactId>hibernate-validator</artifactId><version>${hibernate-validator.version}</version>
</dependency>

2) 在hibernate-validator包里包含了文件/META-INF/services/javax.validation.spi.ValidationProvider,文件里配置了HibernateValidator类

org.hibernate.validator.HibernateValidator

Spring里提供了专门加载/META-INF/services目录的方法,正是通过这种方式可以支持第三方包来扩展。

3) 加载过程:

// 在spring-boot-autoconfigure包里有ValidationAutoConfiguration类,是一个带@AutoConfiguration注解的配置类。
// 当检测到classpath下有META-INF/services/javax.validation.spi.ValidationProvider时,
// 会触发ValidationAutoConfiguration这个配置类的加载。
// 源码位置:org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration
@AutoConfiguration
@ConditionalOnClass(ExecutableValidator.class)
@ConditionalOnResource(resources = "classpath:META-INF/services/javax.validation.spi.ValidationProvider")
@Import(PrimaryDefaultValidatorPostProcessor.class)
public class ValidationAutoConfiguration {@Bean@Role(BeanDefinition.ROLE_INFRASTRUCTURE)@ConditionalOnMissingBean(Validator.class)public static LocalValidatorFactoryBean defaultValidator(ApplicationContext applicationContext) {// 1. 创建一个LocalValidatorFactoryBean对象,把对象作为bean//    LocalValidatorFactoryBean实现了InitializingBean接口,bean创建完成后执行afterPropertiesSet()LocalValidatorFactoryBean factoryBean = new LocalValidatorFactoryBean();MessageInterpolatorFactory interpolatorFactory = new MessageInterpolatorFactory(applicationContext);factoryBean.setMessageInterpolator(interpolatorFactory.getObject());return factoryBean;}// 省略其它代码
}// 源码位置:org.springframework.validation.beanvalidation.LocalValidatorFactoryBean
public void afterPropertiesSet() {Configuration<?> configuration;if (this.providerClass != null) {ProviderSpecificBootstrap bootstrap = Validation.byProvider(this.providerClass);if (this.validationProviderResolver != null) {bootstrap = bootstrap.providerResolver(this.validationProviderResolver);}configuration = bootstrap.configure();}else {// 2. 加载默认的GenericBootstrap,其实现类为GenericBootstrapImplGenericBootstrap bootstrap = Validation.byDefaultProvider();if (this.validationProviderResolver != null) {bootstrap = bootstrap.providerResolver(this.validationProviderResolver);}// 3. 进行配置configuration = bootstrap.configure();}if (this.applicationContext != null) {try {Method eclMethod = configuration.getClass().getMethod("externalClassLoader", ClassLoader.class);ReflectionUtils.invokeMethod(eclMethod, configuration, this.applicationContext.getClassLoader());}catch (NoSuchMethodException ex) {}}MessageInterpolator targetInterpolator = this.messageInterpolator;if (targetInterpolator == null) {targetInterpolator = configuration.getDefaultMessageInterpolator();}configuration.messageInterpolator(new LocaleContextMessageInterpolator(targetInterpolator));if (this.traversableResolver != null) {configuration.traversableResolver(this.traversableResolver);}ConstraintValidatorFactory targetConstraintValidatorFactory = this.constraintValidatorFactory;if (targetConstraintValidatorFactory == null && this.applicationContext != null) {targetConstraintValidatorFactory =new SpringConstraintValidatorFactory(this.applicationContext.getAutowireCapableBeanFactory());}if (targetConstraintValidatorFactory != null) {configuration.constraintValidatorFactory(targetConstraintValidatorFactory);}if (this.parameterNameDiscoverer != null) {configureParameterNameProvider(this.parameterNameDiscoverer, configuration);}List<InputStream> mappingStreams = null;if (this.mappingLocations != null) {mappingStreams = new ArrayList<>(this.mappingLocations.length);for (Resource location : this.mappingLocations) {try {InputStream stream = location.getInputStream();mappingStreams.add(stream);configuration.addMapping(stream);}catch (IOException ex) {closeMappingStreams(mappingStreams);throw new IllegalStateException("Cannot read mapping resource: " + location);}}}this.validationPropertyMap.forEach(configuration::addProperty);if (this.configurationInitializer != null) {this.configurationInitializer.accept(configuration);}postProcessConfiguration(configuration);try {this.validatorFactory = configuration.buildValidatorFactory();setTargetValidator(this.validatorFactory.getValidator());}finally {closeMappingStreams(mappingStreams);}
}// 源码位置:javax.validation.Validation.GenericBootstrapImpl
public Configuration<?> configure() {// ValidationProviderResolver为DefaultValidationProviderResolverValidationProviderResolver resolver = this.resolver == null ? this.getDefaultValidationProviderResolver() : this.resolver;List<ValidationProvider<?>> validationProviders;try {// 4. 加载所有ValidationProvidervalidationProviders = resolver.getValidationProviders();} catch (ValidationException e) {throw e;} catch (RuntimeException re) {throw new ValidationException("Unable to get available provider resolvers.", re);}if (validationProviders.isEmpty()) {String msg = "Unable to create a Configuration, because no Jakarta Bean Validation provider could be found. Add a provider like Hibernate Validator (RI) to your classpath.";throw new NoProviderFoundException(msg);} else {try {Configuration<?> config = ((ValidationProvider)resolver.getValidationProviders().get(0)).createGenericConfiguration(this);return config;} catch (RuntimeException re) {throw new ValidationException("Unable to instantiate Configuration.", re);}}
}// 源码位置:javax.validation.Validation.DefaultValidationProviderResolver
public List<ValidationProvider<?>> getValidationProviders() {// 5. 加载ValidationProvider列表return Validation.GetValidationProviderListAction.getValidationProviderList();
}// 源码位置:javax.validation.Validation.GetValidationProviderListAction
public static synchronized List<ValidationProvider<?>> getValidationProviderList() {// 5. 执行run()方法加载,INSTANCE就是Validation.GetValidationProviderListAction的对象return System.getSecurityManager() != null ? (List)AccessController.doPrivileged(INSTANCE) : INSTANCE.run();
}// 源码位置:javax.validation.Validation.GetValidationProviderListAction
public List<ValidationProvider<?>> run() {ClassLoader classloader = Thread.currentThread().getContextClassLoader();List<ValidationProvider<?>> cachedContextClassLoaderProviderList = this.getCachedValidationProviders(classloader);if (cachedContextClassLoaderProviderList != null) {return cachedContextClassLoaderProviderList;} else {    // 6. 使用ClassLoader去加载List<ValidationProvider<?>> validationProviderList = this.loadProviders(classloader);if (validationProviderList.isEmpty()) {classloader = DefaultValidationProviderResolver.class.getClassLoader();List<ValidationProvider<?>> cachedCurrentClassLoaderProviderList = this.getCachedValidationProviders(classloader);if (cachedCurrentClassLoaderProviderList != null) {return cachedCurrentClassLoaderProviderList;}validationProviderList = this.loadProviders(classloader);}// 加载到的类会缓存起来this.cacheValidationProviders(classloader, validationProviderList);return validationProviderList;}
}// 源码位置:javax.validation.Validation.GetValidationProviderListAction
private List<ValidationProvider<?>> loadProviders(ClassLoader classloader) {// 7. ServiceLoader就是Spring提供的专门加载所有jar内META-INF/services/目录指定类型类的加载器,//    hibernate-validator包里有/META-INF/services/javax.validation.spi.ValidationProvider文件,//    该文件里配置的org.hibernate.validator.HibernateValidator类就是ValidationProvider类型的ServiceLoader<ValidationProvider> loader = ServiceLoader.load(ValidationProvider.class, classloader);Iterator<ValidationProvider> providerIterator = loader.iterator();List<ValidationProvider<?>> validationProviderList = new ArrayList();while(providerIterator.hasNext()) {try {validationProviderList.add(providerIterator.next());} catch (ServiceConfigurationError var6) {}}// 这里列表里只有一个HibernateValidator对象return validationProviderList;
}// 回到GenericBootstrapImpl的configure()继续处理
// 源码位置:javax.validation.Validation.GenericBootstrapImpl
public Configuration<?> configure() {// ValidationProviderResolver为DefaultValidationProviderResolverValidationProviderResolver resolver = this.resolver == null ? this.getDefaultValidationProviderResolver() : this.resolver;List<ValidationProvider<?>> validationProviders;try {// 4. 加载所有ValidationProvidervalidationProviders = resolver.getValidationProviders();} catch (ValidationException e) {throw e;} catch (RuntimeException re) {throw new ValidationException("Unable to get available provider resolvers.", re);}if (validationProviders.isEmpty()) {String msg = "Unable to create a Configuration, because no Jakarta Bean Validation provider could be found. Add a provider like Hibernate Validator (RI) to your classpath.";throw new NoProviderFoundException(msg);} else {try {// 8. 取出第一个ValidationProvider进行创建配置信息Configuration<?> config = ((ValidationProvider)resolver.getValidationProviders().get(0)).createGenericConfiguration(this);return config;} catch (RuntimeException re) {throw new ValidationException("Unable to instantiate Configuration.", re);}}
}// 源码位置:org.hibernate.validator.HibernateValidator
public Configuration<?> createGenericConfiguration(BootstrapState state) {// 9. 创建HibernateValidator的ConfigurationImpl配置信息return new ConfigurationImpl( state );
}// 回到LocalValidatorFactoryBean的afterPropertiesSet()继续处理
// 源码位置:org.springframework.validation.beanvalidation.LocalValidatorFactoryBean
public void afterPropertiesSet() {Configuration<?> configuration;if (this.providerClass != null) {ProviderSpecificBootstrap bootstrap = Validation.byProvider(this.providerClass);if (this.validationProviderResolver != null) {bootstrap = bootstrap.providerResolver(this.validationProviderResolver);}configuration = bootstrap.configure();}else {// 2. 加载默认的GenericBootstrap,其实现类为GenericBootstrapImplGenericBootstrap bootstrap = Validation.byDefaultProvider();if (this.validationProviderResolver != null) {bootstrap = bootstrap.providerResolver(this.validationProviderResolver);}// 3. 进行配置configuration = bootstrap.configure();}if (this.applicationContext != null) {try {Method eclMethod = configuration.getClass().getMethod("externalClassLoader", ClassLoader.class);ReflectionUtils.invokeMethod(eclMethod, configuration, this.applicationContext.getClassLoader());}catch (NoSuchMethodException ex) {}}// 省略部分代码try {// 10. 调用HibernateValidator的ConfigurationImpl配置信息的buildValidatorFactory()方法创建个工厂类,this.validatorFactory = configuration.buildValidatorFactory();// 11. 通过工厂类对象的getValidator()去创建ValidatorsetTargetValidator(this.validatorFactory.getValidator());}finally {closeMappingStreams(mappingStreams);}
}
// 源码位置:org.hibernate.validator.HibernateValidator
public ValidatorFactory buildValidatorFactory(ConfigurationState configurationState) {return new ValidatorFactoryImpl( configurationState );
}
// 源码位置:org.hibernate.validator.internal.engine.ValidatorFactoryImpl
public Validator getValidator() {// 12. 创建Validatorreturn createValidator(constraintCreationContext.getConstraintValidatorManager().getDefaultConstraintValidatorFactory(),constraintCreationContext,validatorFactoryScopedContext,methodValidationConfiguration);
}
// 源码位置:org.hibernate.validator.internal.engine.ValidatorFactoryImpl
Validator createValidator(ConstraintValidatorFactory constraintValidatorFactory,ConstraintCreationContext constraintCreationContext,ValidatorFactoryScopedContext validatorFactoryScopedContext,MethodValidationConfiguration methodValidationConfiguration) {// 省略部分代码// 13. 创建Validator(ValidatorImpl)//     org.hibernate.validator.internal.engine.ValidatorImpl为hibernate-validator包提供的Validator类,//     ValidatorImpl实现了javax.validation.Validator接口return new ValidatorImpl(constraintValidatorFactory,beanMetaDataManager,constraintCreationContext.getValueExtractorManager(),constraintCreationContext.getConstraintValidatorManager(),validationOrderGenerator,validatorFactoryScopedContext);
}// 回到LocalValidatorFactoryBean的afterPropertiesSet()继续处理
// 源码位置:org.springframework.validation.beanvalidation.LocalValidatorFactoryBean
public void afterPropertiesSet() {Configuration<?> configuration;if (this.providerClass != null) {ProviderSpecificBootstrap bootstrap = Validation.byProvider(this.providerClass);if (this.validationProviderResolver != null) {bootstrap = bootstrap.providerResolver(this.validationProviderResolver);}configuration = bootstrap.configure();}else {// 2. 加载默认的GenericBootstrap,其实现类为GenericBootstrapImplGenericBootstrap bootstrap = Validation.byDefaultProvider();if (this.validationProviderResolver != null) {bootstrap = bootstrap.providerResolver(this.validationProviderResolver);}// 3. 进行配置configuration = bootstrap.configure();}if (this.applicationContext != null) {try {Method eclMethod = configuration.getClass().getMethod("externalClassLoader", ClassLoader.class);ReflectionUtils.invokeMethod(eclMethod, configuration, this.applicationContext.getClassLoader());}catch (NoSuchMethodException ex) {}}// 省略部分代码try {// 10. 调用HibernateValidator的ConfigurationImpl配置信息的buildValidatorFactory()方法创建个工厂类,//     然后通过工厂创建出HibernateValidator对象this.validatorFactory = configuration.buildValidatorFactory();// 11. 通过工厂类对象的getValidator()去创建Validator// 14. 通过setTargetValidator()设置validator,注意当前类是LocalValidatorFactoryBean,继承了SpringValidatorAdapter,//     SpringValidatorAdapter的setTargetValidator()就是把validator赋值给targetValidatorsetTargetValidator(this.validatorFactory.getValidator());}finally {closeMappingStreams(mappingStreams);}
}// 源码位置:org.springframework.validation.beanvalidation.SpringValidatorAdapter
void setTargetValidator(javax.validation.Validator targetValidator) {// 15. 把创建的Validator(ValidatorImpl)赋值给targetValidatorthis.targetValidator = targetValidator;
}
public void validate(Object target, Errors errors) {// 16. 最终校验的时候,用targetValidator来校验if (this.targetValidator != null) {processConstraintViolations(this.targetValidator.validate(target), errors);}
}

从上面看,Spring还提供了一种通过javax.validation.spi.ValidationProvider来扩展的方式,ValidationProvider提供一个接口得以指定一个Validator的工厂类,通过这个工厂类则创建出实际的Validator,把该Validator指到SpringValidatorAdapter里的targetValidator,这样就可以跟SpringMVC里使用Validator的流程接上。

2.2 查找配置了要校验的属性

在SpringMVC使用Validator进行校验的流程上,最终使用Validator的validate()方法进行校验。hibernate-validator包提供了一套注解,通过这些注解就很容易指定一些基础的校验,比如@NotNull注解就可以校验属性值不能为null,@Max就可以校验整形数字的最大范围,在javax.validation.constraints包里还提供了各种各样的注解来帮助校验一些通用的规则。当然如果是具体业务的校验,则可以自己校验或者自定义注解来完成校验。

要实现这种便利的校验,第一步就是要找到指定了这些注解的地方,称为Constraint。

// 源码位置:org.hibernate.validator.internal.engine.ValidatorImpl
public final <T> Set<ConstraintViolation<T>> validate(T object, Class<?>... groups) {Contracts.assertNotNull( object, MESSAGES.validatedObjectMustNotBeNull() );sanityCheckGroups( groups );Class<T> rootBeanClass = (Class<T>) object.getClass();// 1. 获取参数对象的Meta信息,包含所有方法和属性BeanMetaData<T> rootBeanMetaData = beanMetaDataManager.getBeanMetaData( rootBeanClass );if ( !rootBeanMetaData.hasConstraints() ) {return Collections.emptySet();}BaseBeanValidationContext<T> validationContext = getValidationContextBuilder().forValidate( rootBeanClass, rootBeanMetaData, object );ValidationOrder validationOrder = determineGroupValidationOrder( groups );BeanValueContext<?, Object> valueContext = ValueContexts.getLocalExecutionContextForBean(validatorScopedContext.getParameterNameProvider(),object,validationContext.getRootBeanMetaData(),PathImpl.createRootPath());return validateInContext( validationContext, valueContext, validationOrder );
}// 中间略过以下步骤,直接到AnnotationMetaDataProvider的retrieveBeanConfiguration
//    org.hibernate.validator.internal.metadata.BeanMetaDataManagerImpl#getBeanMetaData
//    org.hibernate.validator.internal.metadata.BeanMetaDataManagerImpl#createBeanMetaData
//    org.hibernate.validator.internal.metadata.BeanMetaDataManagerImpl#getBeanConfigurationForHierarchy
//    org.hibernate.validator.internal.metadata.provider.AnnotationMetaDataProvider#getBeanConfiguration
// 源码位置:org.hibernate.validator.internal.metadata.provider.AnnotationMetaDataProvider
private <T> BeanConfiguration<T> retrieveBeanConfiguration(Class<T> beanClass) {// 2. 先获取属性的Meta信息Set<ConstrainedElement> constrainedElements = getFieldMetaData( beanClass );constrainedElements.addAll( getMethodMetaData( beanClass ) );constrainedElements.addAll( getConstructorMetaData( beanClass ) );Set<MetaConstraint<?>> classLevelConstraints = getClassLevelConstraints( beanClass );if ( !classLevelConstraints.isEmpty() ) {ConstrainedType classLevelMetaData =new ConstrainedType(ConfigurationSource.ANNOTATION,beanClass,classLevelConstraints);constrainedElements.add( classLevelMetaData );}return new BeanConfiguration<>(ConfigurationSource.ANNOTATION,beanClass,constrainedElements,getDefaultGroupSequence( beanClass ),getDefaultGroupSequenceProvider( beanClass ));
}// 源码位置:org.hibernate.validator.internal.metadata.provider.AnnotationMetaDataProvider
private Set<ConstrainedElement> getFieldMetaData(Class<?> beanClass) {Set<ConstrainedElement> propertyMetaData = newHashSet();for ( Field field : run( GetDeclaredFields.action( beanClass ) ) ) {if ( Modifier.isStatic( field.getModifiers() ) || field.isSynthetic() ) {continue;}JavaBeanField javaBeanField = javaBeanHelper.field( field );if ( annotationProcessingOptions.areMemberConstraintsIgnoredFor( javaBeanField ) ) {continue;}// 3. 遍历类里的所有DeclaredFields,获取Field的meta信息propertyMetaData.add( findPropertyMetaData( javaBeanField ) );}return propertyMetaData;
}// 源码位置:org.hibernate.validator.internal.metadata.provider.AnnotationMetaDataProvider
private ConstrainedField findPropertyMetaData(JavaBeanField javaBeanField) {// 4. 获取Field的Constraint信息Set<MetaConstraint<?>> constraints = convertToMetaConstraints(findConstraints( javaBeanField, ConstraintLocationKind.FIELD ),javaBeanField);CascadingMetaDataBuilder cascadingMetaDataBuilder = findCascadingMetaData( javaBeanField );Set<MetaConstraint<?>> typeArgumentsConstraints = findTypeAnnotationConstraints( javaBeanField );return new ConstrainedField(ConfigurationSource.ANNOTATION,javaBeanField,constraints,typeArgumentsConstraints,cascadingMetaDataBuilder);
}
private List<ConstraintDescriptorImpl<?>> findConstraints(JavaBeanAnnotatedConstrainable constrainable, ConstraintLocationKind kind) {// 5. 获取Field的Constraint信息,constrainable为Fieldreturn findConstraints( constrainable, constrainable, kind );
}
private List<ConstraintDescriptorImpl<?>> findConstraints(Constrainable constrainable, JavaBeanAnnotatedElement annotatedElement, ConstraintLocationKind kind) {List<ConstraintDescriptorImpl<?>> metaData = newArrayList();for ( Annotation annotation : annotatedElement.getDeclaredAnnotations() ) {// 6. 遍历Field的所有注解,从注解里获取Constraint信息metaData.addAll( findConstraintAnnotations( constrainable, annotation, kind ) );}return metaData;
}// 源码位置:org.hibernate.validator.internal.metadata.provider.AnnotationMetaDataProvider
protected <A extends Annotation> List<ConstraintDescriptorImpl<?>> findConstraintAnnotations(Constrainable constrainable,A annotation,ConstraintLocationKind type) {// 7. 如果注解的包路径是以"java."、"jdk.internal"这两种开头,则不算Constraint,返回空列表if ( constraintCreationContext.getConstraintHelper().isJdkAnnotation( annotation.annotationType() ) ) {return Collections.emptyList();}List<Annotation> constraints = newArrayList();Class<? extends Annotation> annotationType = annotation.annotationType();// 8. 判断是否是Constraint注解,Helper为ConstraintHelperif ( constraintCreationContext.getConstraintHelper().isConstraintAnnotation( annotationType ) ) {constraints.add( annotation );}else if ( constraintCreationContext.getConstraintHelper().isMultiValueConstraint( annotationType ) ) {constraints.addAll( constraintCreationContext.getConstraintHelper().getConstraintsFromMultiValueConstraint( annotation ) );}return constraints.stream().map( c -> buildConstraintDescriptor( constrainable, c, type ) ).collect( Collectors.toList() );
}// 源码位置:org.hibernate.validator.internal.metadata.core.ConstraintHelper
public boolean isConstraintAnnotation(Class<? extends Annotation> annotationType) {// 9. 判断是否是内置的Constraint注解if ( isBuiltinConstraint( annotationType ) ) {return true;}if ( annotationType.getAnnotation( Constraint.class ) == null ) {return false;}return externalConstraints.computeIfAbsent( annotationType, a -> {assertMessageParameterExists( a );assertGroupsParameterExists( a );assertPayloadParameterExists( a );assertValidationAppliesToParameterSetUpCorrectly( a );assertNoParameterStartsWithValid( a );return Boolean.TRUE;} );
}
private boolean isBuiltinConstraint(Class<? extends Annotation> annotationType) {// 10. 判断是否是内置的Constraint注解Map里return BuiltinConstraint.isBuiltin( annotationType.getName() );
}// 源码位置:org.hibernate.validator.internal.metadata.core.BuiltinConstraint
static boolean isBuiltin(String constraint) {// 11. 判断注解的名称是否在内置Constraint注解Map里return CONSTRAINT_MAPPING.containsKey( constraint );
}
// CONSTRAINT_MAPPING里初始化了50种Constraint,常见的如NotNull、NotEmpty、Min、Max等
enum BuiltinConstraint {// Specification constraintsJAVAX_VALIDATION_CONSTRAINTS_ASSERT_FALSE("javax.validation.constraints.AssertFalse"),JAVAX_VALIDATION_CONSTRAINTS_ASSERT_TRUE("javax.validation.constraints.AssertTrue"),JAVAX_VALIDATION_CONSTRAINTS_DECIMAL_MAX("javax.validation.constraints.DecimalMax"),JAVAX_VALIDATION_CONSTRAINTS_DECIMAL_MIN("javax.validation.constraints.DecimalMin"),JAVAX_VALIDATION_CONSTRAINTS_DIGITS("javax.validation.constraints.Digits"),JAVAX_VALIDATION_CONSTRAINTS_EMAIL("javax.validation.constraints.Email"),JAVAX_VALIDATION_CONSTRAINTS_FUTURE("javax.validation.constraints.Future"),JAVAX_VALIDATION_CONSTRAINTS_FUTURE_OR_PRESENT("javax.validation.constraints.FutureOrPresent"),JAVAX_VALIDATION_CONSTRAINTS_MIN("javax.validation.constraints.Min"),JAVAX_VALIDATION_CONSTRAINTS_MAX("javax.validation.constraints.Max"),JAVAX_VALIDATION_CONSTRAINTS_NEGATIVE("javax.validation.constraints.Negative"),JAVAX_VALIDATION_CONSTRAINTS_NEGATIVE_OR_ZERO("javax.validation.constraints.NegativeOrZero"),JAVAX_VALIDATION_CONSTRAINTS_NOT_BLANK("javax.validation.constraints.NotBlank"),JAVAX_VALIDATION_CONSTRAINTS_NOT_EMPTY("javax.validation.constraints.NotEmpty"),JAVAX_VALIDATION_CONSTRAINTS_NOT_NULL("javax.validation.constraints.NotNull"),JAVAX_VALIDATION_CONSTRAINTS_NULL("javax.validation.constraints.Null"),JAVAX_VALIDATION_CONSTRAINTS_PAST("javax.validation.constraints.Past"),JAVAX_VALIDATION_CONSTRAINTS_PAST_OR_PRESENT("javax.validation.constraints.PastOrPresent"),JAVAX_VALIDATION_CONSTRAINTS_PATTERN("javax.validation.constraints.Pattern"),JAVAX_VALIDATION_CONSTRAINTS_POSITIVE("javax.validation.constraints.Positive"),JAVAX_VALIDATION_CONSTRAINTS_POSITIVE_OR_ZERO("javax.validation.constraints.PositiveOrZero"),JAVAX_VALIDATION_CONSTRAINTS_SIZE("javax.validation.constraints.Size"),// Hibernate Validator specific constraintsORG_HIBERNATE_VALIDATOR_CONSTRAINTS_CODE_POINT_LENGTH("org.hibernate.validator.constraints.CodePointLength"),ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_CURRENCY("org.hibernate.validator.constraints.Currency"),ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_EMAIL("org.hibernate.validator.constraints.Email", Arrays.asList( JAVAX_VALIDATION_CONSTRAINTS_PATTERN ) ),ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_ISBN("org.hibernate.validator.constraints.ISBN"),ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_LENGTH("org.hibernate.validator.constraints.Length"),ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_LUHN_CHECK("org.hibernate.validator.constraints.LuhnCheck"),ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_CREDIT_CARD_NUMBER("org.hibernate.validator.constraints.CreditCardNumber", Arrays.asList( ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_LUHN_CHECK ) ),ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_MOD10_CHECK("org.hibernate.validator.constraints.Mod10Check"),ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_MOD11_CHECK("org.hibernate.validator.constraints.Mod11Check"),ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_MOD_CHECK("org.hibernate.validator.constraints.ModCheck"),ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_NORMALIZED("org.hibernate.validator.constraints.Normalized"),ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_EAN("org.hibernate.validator.constraints.EAN", Arrays.asList( ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_MOD10_CHECK ) ),ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_NOT_BLANK("org.hibernate.validator.constraints.NotBlank", Arrays.asList( JAVAX_VALIDATION_CONSTRAINTS_NOT_NULL ) ),ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_NOT_EMPTY("org.hibernate.validator.constraints.NotEmpty", Arrays.asList( JAVAX_VALIDATION_CONSTRAINTS_NOT_NULL, JAVAX_VALIDATION_CONSTRAINTS_SIZE )),ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_PARAMETER_SCRIPT_ASSERT("org.hibernate.validator.constraints.ParameterScriptAssert"),ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_RANGE("org.hibernate.validator.constraints.Range", Arrays.asList( JAVAX_VALIDATION_CONSTRAINTS_MIN, JAVAX_VALIDATION_CONSTRAINTS_MAX )),ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_SCRIPT_ASSERT("org.hibernate.validator.constraints.ScriptAssert"),ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_URL("org.hibernate.validator.constraints.URL", Arrays.asList( JAVAX_VALIDATION_CONSTRAINTS_PATTERN )),ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_UNIQUE_ELEMENTS("org.hibernate.validator.constraints.UniqueElements"),ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_BR_CNPJ("org.hibernate.validator.constraints.br.CNPJ", Arrays.asList( JAVAX_VALIDATION_CONSTRAINTS_PATTERN )),ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_BR_CPF("org.hibernate.validator.constraints.br.CPF", Arrays.asList( JAVAX_VALIDATION_CONSTRAINTS_PATTERN )),ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_BR_TITULO_ELEITORAL("org.hibernate.validator.constraints.br.TituloEleitoral", Arrays.asList( JAVAX_VALIDATION_CONSTRAINTS_PATTERN, ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_MOD11_CHECK ) ),ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_PL_NIP("org.hibernate.validator.constraints.pl.NIP"),ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_PL_PESEL("org.hibernate.validator.constraints.pl.PESEL"),ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_PL_REGON("org.hibernate.validator.constraints.pl.REGON"),ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_RU_INN("org.hibernate.validator.constraints.ru.INN"),ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_TIME_DURATION_MAX("org.hibernate.validator.constraints.time.DurationMax"),ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_TIME_DURATION_MIN("org.hibernate.validator.constraints.time.DurationMin");private static final Map<String, Set<BuiltinConstraint>> CONSTRAINT_MAPPING;// 省略其它代码
}// 回到ConstraintHelper的isConstraintAnnotation()继续处理
// 源码位置:org.hibernate.validator.internal.metadata.core.ConstraintHelper
public boolean isConstraintAnnotation(Class<? extends Annotation> annotationType) {// 9. 判断是否是内置的Constraint注解if ( isBuiltinConstraint( annotationType ) ) {return true;}// 12. 也可以自定义注解,并用Constraint注解标记,细节自行探索if ( annotationType.getAnnotation( Constraint.class ) == null ) {return false;}return externalConstraints.computeIfAbsent( annotationType, a -> {assertMessageParameterExists( a );assertGroupsParameterExists( a );assertPayloadParameterExists( a );assertValidationAppliesToParameterSetUpCorrectly( a );assertNoParameterStartsWithValid( a );return Boolean.TRUE;} );
}// 回到AnnotationMetaDataProvider的findConstraintAnnotations()继续处理
// 源码位置:org.hibernate.validator.internal.metadata.provider.AnnotationMetaDataProvider
protected <A extends Annotation> List<ConstraintDescriptorImpl<?>> findConstraintAnnotations(Constrainable constrainable,A annotation,ConstraintLocationKind type) {// 7. 如果注解的包路径是以"java."、"jdk.internal"这两种开头,则不算Constraint,返回空列表if ( constraintCreationContext.getConstraintHelper().isJdkAnnotation( annotation.annotationType() ) ) {return Collections.emptyList();}List<Annotation> constraints = newArrayList();Class<? extends Annotation> annotationType = annotation.annotationType();// 8. 判断是否是Constraint注解,Helper为ConstraintHelperif ( constraintCreationContext.getConstraintHelper().isConstraintAnnotation( annotationType ) ) {constraints.add( annotation );}else if ( constraintCreationContext.getConstraintHelper().isMultiValueConstraint( annotationType ) ) {constraints.addAll( constraintCreationContext.getConstraintHelper().getConstraintsFromMultiValueConstraint( annotation ) );}// 13. 组装ConstraintDescriptorImplreturn constraints.stream().map( c -> buildConstraintDescriptor( constrainable, c, type ) ).collect( Collectors.toList() );
}// 源码位置:org.hibernate.validator.internal.metadata.provider.AnnotationMetaDataProvider
private <A extends Annotation> ConstraintDescriptorImpl<A> buildConstraintDescriptor(Constrainable constrainable, A annotation, ConstraintLocationKind type) {// 14. 创建ConstraintDescriptorImplreturn new ConstraintDescriptorImpl<>(constraintCreationContext.getConstraintHelper(),constrainable,new ConstraintAnnotationDescriptor<>( annotation ),type);
}// 回到AnnotationMetaDataProvider的findPropertyMetaData()
// 源码位置:org.hibernate.validator.internal.metadata.provider.AnnotationMetaDataProvider
private ConstrainedField findPropertyMetaData(JavaBeanField javaBeanField) {// 4. 获取Field的Constraint信息Set<MetaConstraint<?>> constraints = convertToMetaConstraints(findConstraints( javaBeanField, ConstraintLocationKind.FIELD ),javaBeanField);CascadingMetaDataBuilder cascadingMetaDataBuilder = findCascadingMetaData( javaBeanField );Set<MetaConstraint<?>> typeArgumentsConstraints = findTypeAnnotationConstraints( javaBeanField );// 15. 把找到的Constraint信息放到ConstrainedFieldField中,如果没有Constraint信息则constraints为空//     Contraint信息最终包装到MetaData信息中return new ConstrainedField(ConfigurationSource.ANNOTATION,javaBeanField,constraints,typeArgumentsConstraints,cascadingMetaDataBuilder);
}

2.3 校验属性值

找到了配置要校验的注解的属性之后,每种注解都有相应的ConstraintValidator,用于实现具体的校验逻辑。比如@Notnull对应的Validator就要实现对象值不允许为null。

// 回到ValidatorImpl的validate()继续处理
// 源码位置:org.hibernate.validator.internal.engine.ValidatorImpl
public final <T> Set<ConstraintViolation<T>> validate(T object, Class<?>... groups) {Contracts.assertNotNull( object, MESSAGES.validatedObjectMustNotBeNull() );sanityCheckGroups( groups );Class<T> rootBeanClass = (Class<T>) object.getClass();// 1. 获取参数对象的Meta信息,包含所有方法和属性BeanMetaData<T> rootBeanMetaData = beanMetaDataManager.getBeanMetaData( rootBeanClass );if ( !rootBeanMetaData.hasConstraints() ) {return Collections.emptySet();}BaseBeanValidationContext<T> validationContext = getValidationContextBuilder().forValidate( rootBeanClass, rootBeanMetaData, object );ValidationOrder validationOrder = determineGroupValidationOrder( groups );BeanValueContext<?, Object> valueContext = ValueContexts.getLocalExecutionContextForBean(validatorScopedContext.getParameterNameProvider(),object,validationContext.getRootBeanMetaData(),PathImpl.createRootPath());// 16. 校验参数值return validateInContext( validationContext, valueContext, validationOrder );
}// 源码位置:org.hibernate.validator.internal.engine.ValidatorImpl
private <T, U> Set<ConstraintViolation<T>> validateInContext(BaseBeanValidationContext<T> validationContext, BeanValueContext<U, Object> valueContext, ValidationOrder validationOrder) {if ( valueContext.getCurrentBean() == null ) {return Collections.emptySet();}BeanMetaData<U> beanMetaData = valueContext.getCurrentBeanMetaData();if ( beanMetaData.isDefaultGroupSequenceRedefined() ) {validationOrder.assertDefaultGroupSequenceIsExpandable( beanMetaData.getDefaultGroupSequence( valueContext.getCurrentBean() ) );}Iterator<Group> groupIterator = validationOrder.getGroupIterator();while ( groupIterator.hasNext() ) {Group group = groupIterator.next();valueContext.setCurrentGroup( group.getDefiningClass() );// 17. 根据Contraint校验validateConstraintsForCurrentGroup( validationContext, valueContext );if ( shouldFailFast( validationContext ) ) {return validationContext.getFailingConstraints();}}// 省略部分代码return validationContext.getFailingConstraints();
}
private void validateConstraintsForCurrentGroup(BaseBeanValidationContext<?> validationContext, BeanValueContext<?, Object> valueContext) {if ( !valueContext.validatingDefault() ) {validateConstraintsForNonDefaultGroup( validationContext, valueContext );}else {// 18. 在默认组下校验,Hibernate validation不是纯给Spring使用的,有Group等更复杂的概念,这里忽略validateConstraintsForDefaultGroup( validationContext, valueContext );}
}// 源码位置:org.hibernate.validator.internal.engine.ValidatorImpl
private <U> void validateConstraintsForDefaultGroup(BaseBeanValidationContext<?> validationContext, BeanValueContext<U, Object> valueContext) {// 19. 从Context里取出参数对象的BeanMetaData信息final BeanMetaData<U> beanMetaData = valueContext.getCurrentBeanMetaData();final Map<Class<?>, Class<?>> validatedInterfaces = new HashMap<>();for ( Class<? super U> clazz : beanMetaData.getClassHierarchy() ) {BeanMetaData<? super U> hostingBeanMetaData = beanMetaDataManager.getBeanMetaData( clazz );boolean defaultGroupSequenceIsRedefined = hostingBeanMetaData.isDefaultGroupSequenceRedefined();if ( defaultGroupSequenceIsRedefined ) {// 省略部分代码}else {// 取出参数对象里配置的Contraint信息(列表),如加了@NotNull注解时,则Contraint为包含这个注解、加注解属性等信息Set<MetaConstraint<?>> metaConstraints = hostingBeanMetaData.getDirectMetaConstraints();// 20. 校验validateConstraintsForSingleDefaultGroupElement( validationContext, valueContext, validatedInterfaces, clazz, metaConstraints, Group.DEFAULT_GROUP );validationContext.markCurrentBeanAsProcessed( valueContext );}if ( defaultGroupSequenceIsRedefined ) {break;}}
}// 源码位置:org.hibernate.validator.internal.engine.ValidatorImpl
private <U> boolean validateConstraintsForSingleDefaultGroupElement(BaseBeanValidationContext<?> validationContext, ValueContext<U, Object> valueContext, final Map<Class<?>, Class<?>> validatedInterfaces,Class<? super U> clazz, Set<MetaConstraint<?>> metaConstraints, Group defaultSequenceMember) {boolean validationSuccessful = true;valueContext.setCurrentGroup( defaultSequenceMember.getDefiningClass() );for ( MetaConstraint<?> metaConstraint : metaConstraints ) {final Class<?> declaringClass = metaConstraint.getLocation().getDeclaringClass();if ( declaringClass.isInterface() ) {Class<?> validatedForClass = validatedInterfaces.get( declaringClass );if ( validatedForClass != null && !validatedForClass.equals( clazz ) ) {continue;}validatedInterfaces.put( declaringClass, clazz );}// 21. 校验boolean tmp = validateMetaConstraint( validationContext, valueContext, valueContext.getCurrentBean(), metaConstraint );if ( shouldFailFast( validationContext ) ) {return false;}validationSuccessful = validationSuccessful && tmp;}return validationSuccessful;
}// 源码位置:org.hibernate.validator.internal.engine.ValidatorImpl
private boolean validateMetaConstraint(BaseBeanValidationContext<?> validationContext, ValueContext<?, Object> valueContext, Object parent, MetaConstraint<?> metaConstraint) {BeanValueContext.ValueState<Object> originalValueState = valueContext.getCurrentValueState();valueContext.appendNode( metaConstraint.getLocation() );boolean success = true;if ( isValidationRequired( validationContext, valueContext, metaConstraint ) ) {if ( parent != null ) {valueContext.setCurrentValidatedValue( valueContext.getValue( parent, metaConstraint.getLocation() ) );}// 22. 执行metaConstraint(MetaConstraint)的validateConstraint()方法进行校验success = metaConstraint.validateConstraint( validationContext, valueContext );validationContext.markConstraintProcessed( valueContext.getCurrentBean(), valueContext.getPropertyPath(), metaConstraint );}valueContext.resetValueState( originalValueState );return success;
}// 源码位置:org.hibernate.validator.internal.metadata.core.MetaConstraint
public boolean validateConstraint(ValidationContext<?> validationContext, ValueContext<?, Object> valueContext) {boolean success = true;if ( valueExtractionPath != null ) {Object valueToValidate = valueContext.getCurrentValidatedValue();if ( valueToValidate != null ) {TypeParameterValueReceiver receiver = new TypeParameterValueReceiver( validationContext, valueContext, valueExtractionPath );ValueExtractorHelper.extractValues( valueExtractionPath.getValueExtractorDescriptor(), valueToValidate, receiver );success = receiver.isSuccess();}}else {// 23. 做普通的校验success = doValidateConstraint( validationContext, valueContext );}return success;
}
private boolean doValidateConstraint(ValidationContext<?> executionContext, ValueContext<?, ?> valueContext) {valueContext.setConstraintLocationKind( getConstraintLocationKind() );// 24. 委托给constraintTree(org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree)进行校验boolean validationResult = constraintTree.validateConstraints( executionContext, valueContext );return validationResult;
}// 源码位置:org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree
public final boolean validateConstraints(ValidationContext<?> validationContext, ValueContext<?, ?> valueContext) {List<ConstraintValidatorContextImpl> violatedConstraintValidatorContexts = new ArrayList<>( 5 );// 25. 进行校验,SimpleConstraintTree继承于ConstraintTree,这里调的是SimpleConstraintTree的validateConstraints()validateConstraints( validationContext, valueContext, violatedConstraintValidatorContexts );if ( !violatedConstraintValidatorContexts.isEmpty() ) {for ( ConstraintValidatorContextImpl constraintValidatorContext : violatedConstraintValidatorContexts ) {for ( ConstraintViolationCreationContext constraintViolationCreationContext : constraintValidatorContext.getConstraintViolationCreationContexts() ) {validationContext.addConstraintFailure(valueContext, constraintViolationCreationContext, constraintValidatorContext.getConstraintDescriptor());}}return false;}return true;
}// 源码位置:org.hibernate.validator.internal.engine.constraintvalidation.SimpleConstraintTree
protected void validateConstraints(ValidationContext<?> validationContext, ValueContext<?, ?> valueContext,Collection<ConstraintValidatorContextImpl> violatedConstraintValidatorContexts) {// 省略部分代码// 26. 获取Contraint对应的Validator,getInitializedConstraintValidator()获取的Validator会在先初始化ConstraintValidator<B, ?> validator = getInitializedConstraintValidator( validationContext, valueContext );ConstraintValidatorContextImpl constraintValidatorContext = validationContext.createConstraintValidatorContextFor(descriptor, valueContext.getPropertyPath());if ( validateSingleConstraint( valueContext, constraintValidatorContext, validator ).isPresent() ) {violatedConstraintValidatorContexts.add( constraintValidatorContext );}
}// 27. 提前初始化好Validator
// 源码位置:org.hibernate.validator.internal.metadata.core.ConstraintHelper
private ConstraintHelper(Set<BuiltinConstraint> enabledBuiltinConstraints) {// 省略部分代码if ( enabledBuiltinConstraints.contains( JAVAX_VALIDATION_CONSTRAINTS_NOT_BLANK ) ) {putBuiltinConstraint( tmpConstraints, NotBlank.class, NotBlankValidator.class );}if ( enabledBuiltinConstraints.contains( JAVAX_VALIDATION_CONSTRAINTS_NOT_EMPTY ) ) {List<Class<? extends ConstraintValidator<NotEmpty, ?>>> notEmptyValidators = new ArrayList<>( 11 );notEmptyValidators.add( NotEmptyValidatorForCharSequence.class );notEmptyValidators.add( NotEmptyValidatorForCollection.class );notEmptyValidators.add( NotEmptyValidatorForArray.class );notEmptyValidators.add( NotEmptyValidatorForMap.class );notEmptyValidators.add( NotEmptyValidatorForArraysOfBoolean.class );notEmptyValidators.add( NotEmptyValidatorForArraysOfByte.class );notEmptyValidators.add( NotEmptyValidatorForArraysOfChar.class );notEmptyValidators.add( NotEmptyValidatorForArraysOfDouble.class );notEmptyValidators.add( NotEmptyValidatorForArraysOfFloat.class );notEmptyValidators.add( NotEmptyValidatorForArraysOfInt.class );notEmptyValidators.add( NotEmptyValidatorForArraysOfLong.class );notEmptyValidators.add( NotEmptyValidatorForArraysOfShort.class );putBuiltinConstraints( tmpConstraints, NotEmpty.class, notEmptyValidators );}if ( enabledBuiltinConstraints.contains( JAVAX_VALIDATION_CONSTRAINTS_NOT_NULL ) ) {putBuiltinConstraint( tmpConstraints, NotNull.class, NotNullValidator.class );}if ( enabledBuiltinConstraints.contains( JAVAX_VALIDATION_CONSTRAINTS_NULL ) ) {putBuiltinConstraint( tmpConstraints, Null.class, NullValidator.class );}// 省略部分代码
}
private static <A extends Annotation> void putBuiltinConstraints(Map<Class<? extends Annotation>, List<ConstraintValidatorDescriptor<?>>> validators,Class<A> constraintType, List<Class<? extends ConstraintValidator<A, ?>>> validatorTypes) {List<ConstraintValidatorDescriptor<?>> descriptors = new ArrayList<>( validatorTypes.size() );for ( Class<? extends ConstraintValidator<A, ?>> validatorType : validatorTypes ) {descriptors.add( ConstraintValidatorDescriptor.forBuiltinClass( validatorType, constraintType ) );}// 以注解作为Key,Validator列表作为Valuevalidators.put( constraintType, CollectionHelper.toImmutableList( descriptors ) );
}
private static <A extends Annotation> void putBuiltinConstraint(Map<Class<? extends Annotation>, List<ConstraintValidatorDescriptor<?>>> validators,Class<A> constraintType, Class<? extends ConstraintValidator<A, ?>> validatorType) {validators.put( constraintType, Collections.singletonList( ConstraintValidatorDescriptor.forBuiltinClass( validatorType, constraintType ) ) );
}// 回到SimpleConstraintTree的validateConstraints()继续处理
// 源码位置:org.hibernate.validator.internal.engine.constraintvalidation.SimpleConstraintTree
protected void validateConstraints(ValidationContext<?> validationContext, ValueContext<?, ?> valueContext,Collection<ConstraintValidatorContextImpl> violatedConstraintValidatorContexts) {// 省略部分代码// 26. 获取Contraint对应的Validator,getInitializedConstraintValidator()获取的Validator会在先初始化ConstraintValidator<B, ?> validator = getInitializedConstraintValidator( validationContext, valueContext );ConstraintValidatorContextImpl constraintValidatorContext = validationContext.createConstraintValidatorContextFor(descriptor, valueContext.getPropertyPath());// 28. 用获取到的Validator进行校验if ( validateSingleConstraint( valueContext, constraintValidatorContext, validator ).isPresent() ) {violatedConstraintValidatorContexts.add( constraintValidatorContext );}
}// 源码位置:org.hibernate.validator.internal.engine.constraintvalidation.SimpleConstraintTree
protected final <V> Optional<ConstraintValidatorContextImpl> validateSingleConstraint(ValueContext<?, ?> valueContext,ConstraintValidatorContextImpl constraintValidatorContext,ConstraintValidator<A, V> validator) {boolean isValid;try {// 29. 取出参数对象的属性值V validatedValue = (V) valueContext.getCurrentValidatedValue();// 30. 使用Validator的isValid()方法进行校验isValid = validator.isValid( validatedValue, constraintValidatorContext );}catch (RuntimeException e) {if ( e instanceof ConstraintDeclarationException ) {throw e;}throw LOG.getExceptionDuringIsValidCallException( e );}if ( !isValid ) {//We do not add these violations yet, since we don't know how they are//going to influence the final boolean evaluationreturn Optional.of( constraintValidatorContext );}return Optional.empty();
}// 源码位置:javax.validation.ConstraintValidator
public interface ConstraintValidator<A extends Annotation, T> {default void initialize(A constraintAnnotation) {}boolean isValid(T value, ConstraintValidatorContext context);
}

2.4 常见的几个ConstraintValidator

ConstraintValidator也是一个可扩展的设计,通过几个常见的ConstraintValidator来了解一下ConstraintValidator是如何实现的。

// 源码位置:org.hibernate.validator.internal.constraintvalidators.bv.NullValidator
public class NullValidator implements ConstraintValidator<Null, Object> {@Overridepublic boolean isValid(Object object, ConstraintValidatorContext constraintValidatorContext) {// 对象值为null则通过校验return object == null;}
}// 源码位置:org.hibernate.validator.internal.constraintvalidators.bv.NotNullValidator
public class NotNullValidator implements ConstraintValidator<NotNull, Object> {@Overridepublic boolean isValid(Object object, ConstraintValidatorContext constraintValidatorContext) {// 对象值不为null则通过校验return object != null;}
}// 源码位置:org.hibernate.validator.internal.constraintvalidators.bv.NotBlankValidator
public class NotBlankValidator implements ConstraintValidator<NotBlank, CharSequence> {@Overridepublic boolean isValid(CharSequence charSequence, ConstraintValidatorContext constraintValidatorContext) {// 对象值不为null且长度大于0才通过校验if ( charSequence == null ) {return false;}return charSequence.toString().trim().length() > 0;}
}// 源码位置:org.hibernate.validator.internal.constraintvalidators.bv.number.bound.MaxValidatorForInteger
public class MaxValidatorForInteger extends AbstractMaxValidator<Integer> {// 子类没有isValid方法,由父类AbstractMaxValidator提供isValid()@Overrideprotected int compare(Integer number) {return NumberComparatorHelper.compare( number.longValue(), maxValue );}
}
// 源码位置:org.hibernate.validator.internal.constraintvalidators.bv.number.bound.AbstractMaxValidator
public abstract class AbstractMaxValidator<T> implements ConstraintValidator<Max, T> {protected long maxValue;@Overridepublic void initialize(Max maxValue) {this.maxValue = maxValue.value();}@Overridepublic boolean isValid(T value, ConstraintValidatorContext constraintValidatorContext) {if ( value == null ) {return true;}// 数字比较的时候要小于等于才校验通过return compare( value ) <= 0;}protected abstract int compare(T number);
}
// 源码位置:org.hibernate.validator.internal.constraintvalidators.bv.number.bound.NumberComparatorHelper
public static int compare(Long number, long value) {return number.compareTo( value );
}// 源码位置:org.hibernate.validator.internal.constraintvalidators.bv.number.bound.MinValidatorForInteger
public class MinValidatorForInteger extends AbstractMinValidator<Integer> {// 子类没有isValid方法,由父类AbstractMaxValidator提供isValid()@Overrideprotected int compare(Integer number) {return NumberComparatorHelper.compare( number.longValue(), minValue );}
}
// 源码位置:org.hibernate.validator.internal.constraintvalidators.bv.number.bound.AbstractMinValidator
public abstract class AbstractMinValidator<T> implements ConstraintValidator<Min, T> {protected long minValue;@Overridepublic void initialize(Min maxValue) {this.minValue = maxValue.value();}@Overridepublic boolean isValid(T value, ConstraintValidatorContext constraintValidatorContext) {if ( value == null ) {return true;}return compare( value ) >= 0;}protected abstract int compare(T number);
}

3 架构一小步

引入hibernate-validator包,使用@NotNull等注解来简化一些通用的校验。

http://www.lryc.cn/news/601860.html

相关文章:

  • 「mysql」Mac osx彻底删除mysql
  • Java面试宝典:MySQL性能优化
  • uart通信
  • JVM类加载机制全流程详解
  • 从MySQL的information_schema系统数据库中获取表的元数据信息
  • MySQL - 索引(B+树)
  • Cgroup 控制组学习(三)在容器中使用 CGroups
  • MySQL - 主从复制与读写分离
  • Cline与Cursor深度实战指南:AI编程助手的革命性应用
  • 基于CNN图像特征提取流程(简化版)
  • Linux实战:从零搭建基于LNMP+NFS+DNS的WordPress博客系统
  • Flink窗口:解锁流计算的秘密武器
  • QT---概览
  • 使用frp实现免费内网穿透
  • Triton Shared编译
  • 【前后端】node mock.js+json-server
  • LeetCode Hot 100 括号生成
  • 力扣热题100----------41.缺少的第一个正数
  • NodeJs接入腾讯云存储COS
  • PROFINET转CAN通讯协议转换速通汽车制造
  • 解析json异常, ObjectMapper注册的问题
  • 生成式召回-TIGER范式
  • BUG记录——Request接传Json数据中文乱码
  • C语言——————学习笔记(自己看)
  • Oracle 19C RU 19.28 升级和安装
  • Frontiers in Psychology投稿LaTeX(三)
  • Python异常处理:金融风控系统中的救命盾牌
  • 设备分配与回收
  • 6.Pinia快速入门
  • 3.JDK+JRE组件构成与协作