HibernateValidator6.2.0.Final-JakartaBeanValidationReferenceImplementation参考指南HardyFerentschik,GunnarMorling,GuillaumeSmet2020-12-23目录前言..............................................................................................1第1章入门......................................................................................31.1.项目创建...................................................................................31.1.1.统一的EL表达式.......................................................................31.1.2.CDI...................................................................................41.1.3.与安全管理器运行.....................................................................41.1.4.使用WildFly更新HibernateValidator...................................................51.1.5.在Java9上运行..........................................................................61.2.应用约束..................................................................................71.3.验证约束.................................................................................81.4.接下来要去哪里?..........................................................................9第2章声明和验证bean约束......................................................................112.1.声明bean约束..............................................................................112.1.1.字段级别的约束.......................................................................112.1.2.属性级别约束.........................................................................122.1.3.容器元素约束.........................................................................132.1.3.1.使用Iterable..................................................................142.1.3.2.使用List.......................................................................152.1.3.3.使用Map........................................................................162.1.3.4.使用java.util.Optional.....................................................182.1.3.5.使用自定义容器类型............................................................192.1.3.6.嵌套容器元素....................................................................202.1.4.类级别的约束........................................................................212.1.5.约束继承...........................................................................212.1.6.对象图..............................................................................222.2.验证bean约束...........................................................................252.2.1.获取Validator实例..................................................................252.2.2.Validator验证器方法...............................................................252.2.2.1.Validator#validate().......................................................252.2.2.2.Validator#validateProperty()............................................262.2.2.3.Validator#validateValue()................................................262.2.3.ConstraintViolation............................................................272.2.3.1.ConstraintViolation方法...................................................272.2.3.2.利用属性路径..................................................................282.3.内置约束................................................................................282.3.1.JakartaBean验证约束...............................................................282.3.2.其他约束............................................................................352.3.2.1.国家特定的约束.................................................................39第3章声明和验证方法约束.....................................................................433.1.声明方法约束.............................................................................433.1.1.参数约束...........................................................................433.1.1.1.交叉参数约束....................................................................443.1.2.返回值约束..........................................................................463.1.3.级联验证...........................................................................473.1.4.继承层次结构中的方法约束...........................................................483.2.验证方法约束............................................................................513.2.1.获取ExecutableValidator实例........................................................523.2.2.ExecutableValidator方法.......................................................523.2.2.1.ExecutableValidator#validateParameters().............................533.2.2.2.ExecutableValidator#validateReturnValue()...........................543.2.2.3.ExecutableValidator#validateConstructorParameters()...............543.2.2.4.ExecutableValidator#validateConstructorReturnValue().............553.2.3.用于方法验证的ConstraintViolation方法.............................................553.3.内置方法约束............................................................................56第4章内插约束错误消息........................................................................584.1.默认消息插值.............................................................................584.1.1.特殊字符.............................................................................594.1.2.消息表达式的插值...................................................................594.1.3.示例.................................................................................604.2.自定义消息插值..........................................................................624.2.1.ResourceBundleLocator..........................................................63第5章分组约束.................................................................................655.1.请求组...................................................................................655.2.组继承...................................................................................695.3.定义组序列..............................................................................705.4.重新定义默认的组顺序....................................................................715.4.1.@GroupSequence....................................................................715.4.2.@GroupSequenceProvider.........................................................735.5.组转换..................................................................................74第6章创建自定义约束..........................................................................786.1.创建一个简单的约束......................................................................786.1.1.约束注释.............................................................................786.1.2.约束验证器...........................................................................816.1.2.1.ConstraintValidatorContext................................................826.1.2.2.HibernateConstraintValidator扩展........................................846.1.2.3.将有效负载传递给约束验证器....................................................856.1.3.错误消息............................................................................876.1.4.使用约束............................................................................886.2.类级别的约束............................................................................896.2.1.自定义属性路径.....................................................................906.3.交叉参数约束..........................................................................916.4.约束组成................................................................................95第7章值提取...................................................................................977.1.内置值提取器.............................................................................977.2.实现一个ValueExtractor..............................................................977.3.非通用容器..............................................................................1007.4.JavaFX值提取器.........................................................................1027.5.注册ValueExtractor.................................................................1027.6.解析算法................................................................................103第8章通过XML配置...........................................................................1048.1.在validation.xml中配置验证器工厂........................................................1048.2.通过constraint-mappings来映射约束.................................................107第九章自举.....................................................................................1149.1.检索ValidatorFactory和Validator..............................................1149.1.1.ValidationProviderResolver....................................................1159.2.配置ValidatorFactory...............................................................1169.2.1.MessageInterpolator............................................................1169.2.2.TraversableResolver............................................................1179.2.3.ConstraintValidatorFactory...................................................1199.2.4.ParameterNameProvider.........................................................1209.2.5.ClockProvider和时间验证容限......................................................1219.2.6.注册ValueExtractors...............................................................1239.2.7.添加映射流..........................................................................1249.2.8.提供器特定的设置................................................................1249.2.9.配置ScriptEvaluatorFactory..................................................1259.2.9.1.XML配置....................................................................1259.2.9.2.程序配置.......................................................................1259.2.9.3.自定义ScriptEvaluatorFactory实现示例........................................1269.3.配置验证器.............................................................................131第10章使用约束元数据........................................................................13310.1.BeanDescriptor......................................................................13510.2.PropertyDescriptor.................................................................13710.3.MethodDescriptor和ConstructorDescriptor.....................................13810.4.ElementDescriptor..................................................................14010.5.ContainerDescriptor和ContainerElementTypeDescriptor.....................14310.6.GroupConversionDescriptor........................................................14410.7.ConstraintDescriptor..............................................................145第11章与其他框架集成.........................................................................14611.1.ORM整合.............................................................................14611.1.1.数据库架构级验证.............................................................14611.1.2.HibernateORM基于事件的验证...................................................14611.1.3.JPA................................................................................14711.2.JSF和Seam...........................................................................14811.3.CDI....................................................................................14811.3.1.Dependencyinjection(依赖注入).................................................14911.3.2.方法验证.........................................................................15111.3.2.1.验证的可执行类型............................................................15311.4.JavaEE................................................................................15511.5.JavaFX.................................................................................156第12章HibernateValidator的详细信息..........................................................15712.1.公开API...............................................................................15712.2.快速失败模式..........................................................................15912.3.放宽对在类层次结构中的方法验证的要求............................................16012.4.程序约束定义和声明.....................................................................16112.5.将程序约束声明应用于默认验证器工厂...................................................16412.6.高级约束组合功能......................................................................16512.6.1.纯粹构成约束的验证目标规范.......................................................16512.6.2.约束的布尔组成....................................................................16612.7.路径API的扩展..........................................................................16712.8.动态有效载荷作为ConstraintViolation的一部分......................................16812.9.启用表达式语言功能....................................................................17012.10.ParameterMessageInterpolator....................................................17112.11.ResourceBundleLocator.............................................................17212.12.自定义语言环境解析...................................................................17212.13.自定义上下文.........................................................................17312.13.1.HibernateConstraintValidatorContext......................................17312.13.2.HibernateMessageInterpolatorContext......................................17812.14.基于Paranamer的ParameterNameProvider.........................................17912.15.提供约束定义..........................................................................18012.15.1.通过ServiceLoader的约束定义..................................................18012.15.2.以编程方式添加约束定义...........................................................18112.16.自定义类加载.........................................................................18212.17.自定义getter属性选择策略..............................................................18312.18.自定义属性名称解析以解决约束冲突....................................................186第13章注释处理器..............................................................................19113.1.先决条件................................................................................19113.2.特征...................................................................................19113.3.选项...................................................................................19213.4.使用注释处理器.........................................................................19213.4.1.命令行构建........................................................................19213.4.1.1.Maven.........................................................................19213.4.1.2.Gradle........................................................................19313.4.1.3.ApacheAnt...................................................................19313.4.1.4.javac..........................................................................19413.4.2.IDE构建..........................................................................19413.4.2.1.Eclipse........................................................................19413.4.2.2.IntelliJIDEA..................................................................19513.4.2.3.NetBeans.....................................................................19613.5.已知的问题.............................................................................197第14章进一步阅读.............................................................................198前言验证数据是一项常见的任务,遍历从表示层到持久层的所有应用程序层。通常,在每个层中都实现相同的验证逻辑,这既耗时又容易出错。为了避免重复这些验证,开发人员通常将验证逻辑直接捆绑到域模型中,从而使域类与验证代码杂乱无章,而验证代码实际上是有关类本身的元数据。JakartaBeanValidation2.0-定义用于实体和方法验证的元数据模型和API。默认的元数据源是注释,能够通过使用XML覆盖和扩展元数据。API不受特定应用程序层或编程模型的约束。它特别不与Web层或持久性层绑定,并且可用于服务器端应用程序编程以及富客户端Swing应用程序开发人员。1HibernateValidator是JakartaBean验证的参考实现,该实现本身以及JakartaBean验证API和TCK均在ApacheSoftwareLicense2.0下提供和分发。HibernateValidator6和JakartaBeanValidation2.0需要Java8或更高版本。2第1章入门本章将向您展示如何开始使用HibernateValidator,它是JakartaBeanValidation的参考实现(RI)。对于以下快速入门,您需要:•JDK8•ApacheMaven•Internet连接(Maven必须下载所有必需的库)1.1.项目创建为了在Maven项目中使用HibernateValidator,只需将以下依赖项添加到pom.xml中:例1.1:HibernateValidatorMaven依赖项<dependency><groupId>org.hibernate.validator</groupId><artifactId>hibernate-validator</artifactId><version>6.2.0.Final</version></dependency>这将依赖关系传递给JakartaBeanValidationAPI(jakarta.validation:jakarta.validation-api:2.0.2).1.1.1.统一的EL表达式HibernateValidator需要Jakarta表达式语言的实现,用于评估约束违反消息中的动态表达式(请参见第4.1节“默认消息插值”)。当您的应用程序在JBossAS等JavaEE容器中运行时,该容器已经提供了EL实现。但是,在JavaSE环境中,您必须将实现添加为对POM文件的依赖。例如,您可以添加以下依赖项以使用JakartaEL参考实现:示例1.2:UnifiedEL参考实现的Maven依赖关系<dependency><groupId>org.glassfish</groupId><artifactId>jakarta.el</artifactId><version>3.0.3</version></dependency>3对于无法提供EL实现的环境,HibernateValidator提供了第12.10节“ParameterMessageInterpolator”。但是,此插值器的使用不符合JakartaBean验证规范。1.1.2.CDIJakartaBean验证使用CDI(JakartaEE的上下文和依赖注入)定义集成点。如果您的应用程序在未提供此集成的环境中运行,则可以通过将以下Maven依赖项添加到POM中来使用HibernateValidatorCDI可移植扩展:例1.3:HibernateValidatorCDI可移植扩展Maven依赖项<dependency><groupId>org.hibernate.validator</groupId><artifactId>hibernate-validator-cdi</artifactId><version>6.2.0.Final</version></dependency>请注意,对于在JavaEE应用程序服务器上运行的应用程序,通常不需要添加此依赖关系。您可以在第11.3节“CDI”中了解有关JakartaBean验证和CDI集成的更多信息。1.1.3.与安全管理器运行HibernateValidator支持在启用安全管理器的情况下运行。为此,您必须为HibernateValidator的代码库,JakartaBean验证API,Classmate和JBossLogging以及调用JakartaBean验证的代码库分配多个权限。下面显示了如何通过Java默认策略实现处理的策略文件来执行此操作:4例1.4:通过安全管理器使用HibernateValidator的策略文件grantcodeBase"file:path/to/hibernate-validator-6.2.0.Final.jar"{permissionjava.lang.reflect.ReflectPermission"suppressAccessChecks";permissionjava.lang.RuntimePermission"accessDeclaredMembers";permissionjava.lang.RuntimePermission"setContextClassLoader";permissionorg.hibernate.validator.HibernateValidatorPermission"accessPrivateMembers";//OnlyneededwhenworkingwithXMLdescriptors(validation.xmlorXMLconstraintmappings)permissionjava.util.PropertyPermission"mapAnyUriToUri","read";};grantcodeBase"file:path/to/jakarta.validation-api-2.0.2.jar"{permissionjava.io.FilePermission"path/to/hibernate-validator-6.2.0.Final.jar","read";};grantcodeBase"file:path/to/jboss-logging-3.4.1.Final.jar"{permissionjava.util.PropertyPermission"org.jboss.logging.provider","read";permissionjava.util.PropertyPermission"org.jboss.logging.locale","read";};grantcodeBase"file:path/to/classmate-1.5.1.jar"{permissionjava.lang.RuntimePermission"accessDeclaredMembers";};grantcodeBase"file:path/to/validation-caller-x.y.z.jar"{permissionorg.hibernate.validator.HibernateValidatorPermission"accessPrivateMembers";};1.1.4.使用WildFly更新HibernateValidatorWildFly应用程序服务器包含开箱即用的HibernateValidator。为了将JakartaBean验证API和HibernateValidator的服务器模块更新到最新和最大的版本,可以使用WildFly的补丁机制。您可以使用以下依赖关系从SourceForge或MavenCentral下载补丁文件:示例1.5:WildFly19.0.0.Final补丁文件的Maven依赖关系<dependency><groupId>org.hibernate.validator</groupId><artifactId>hibernate-validator-modules</artifactId><version>6.2.0.Final</version><classifier>wildfly-19.0.0.Final-patch</classifier><type>zip</type></dependency>我们还为WildFly18.0.1.Final提供了一个补丁:5示例1.6:WildFly18.0.1.Final补丁文件的Maven依赖关系<dependency><groupId>org.hibernate.validator</groupId><artifactId>hibernate-validator-modules</artifactId><version>6.2.0.Final</version><classifier>wildfly-18.0.1.Final-patch</classifier><type>zip</type></dependency>下载补丁文件后,您可以通过运行以下命令将其应用于WildFly:示例1.7:应用WildFly补丁$JBOSS_HOME/bin/jboss-cli.shpatchapplyhibernate-validator-modules-6.2.0.Final-wildfly-19.0.0.Final-patch.zip如果您要撤消补丁程序并返回到服务器最初附带的HibernateValidator版本,请运行以下命令:示例1.8:回滚WildFly补丁$JBOSS_HOME/bin/jboss-cli.shpatchrollback--reset-configuration=true您可以在hereandhere大致了解有关WildFly修补基础结构的更多信息。1.1.5.在Java9上运行从HibernateValidator6.2.0.Final开始,对Java9和Java平台模块系统(JPMS)的支持正在试验中。尚未提供JPMS模块描述符,但是HibernateValidator可用作自动模块。这些是使用“自动模块名称”标头声明的模块名称:•JakartaBeanValidationAPI:java.validation•HibernateValidatorcore:org.hibernate.validator•HibernateValidatorCDIextension:org.hibernate.validator.cdi•HibernateValidatortestutilities:org.hibernate.validator.testutils•HibernateValidatorannotationprocessor:org.hibernate.validator.annotationprocessor这些模块名称是初步的,在将来的版本中提供实际的模块描述符时可能会更改。6将HibernateValidator与CDI一起使用时,请注意不要启用JDK的java.xml.ws.annotation模块。该模块包含Jakarta注释的子集,但是缺少一些注释,例如javax.annotation.Priority。这会导致未注册HibernateValidator的方法验证拦截器,即方法验证将不起作用。而是将完整的JakartaAnnotationsAPI添加到未命名的模块(即classpath),例如通过引入jakarta.annotation:jakarta.annotation-api依赖项(依赖于org.hibernate.validator:hibernate-validator-cdi时,已经存在对JakartaAnnotationsAPI的传递性依赖项)。如果出于某种原因需要启用java.xml.ws.annotation模块,则应通过附加--patch-modulejava.xml.ws.annotation=/path/to/complete-jakarta.annotation-api.jar到您的Java调用。1.2.应用约束让我们直接看一个例子,看看如何应用约束。例1.9:用约束注释的ClassCarpackageorg.hibernate.validator.referenceguide.chapter01;importjavax.validation.constraints.Min;importjavax.validation.constraints.NotNull;importjavax.validation.constraints.Size;publicclassCar{@NotNullprivateStringmanufacturer;@NotNull@Size(min=2,max=14)privateStringlicensePlate;@Min(2)privateintseatCount;publicCar(Stringmanufacturer,StringlicencePlate,intseatCount){this.manufacturer=manufacturer;this.licensePlate=licencePlate;this.seatCount=seatCount;}//gettersandsetters...}@NotNull,@Size和@Min注解用于声明应应用于Car实例的字段的约束:7•manufacturer不能为null•licensePlate不能为null并且必须介于2到14个字符之间•seatCount必须至少为2您可以在GitHub上的HibernateValidator源存储库中找到本参考指南中使用的所有示例的完整源代码。1.3.验证约束要执行这些约束的验证,请使用Validator实例。让我们来看看Car的单元测试:例1.10:CarTest类,显示验证示例packageorg.hibernate.validator.referenceguide.chapter01;importjava.util.Set;importjavax.validation.ConstraintViolation;importjavax.validation.Validation;importjavax.validation.Validator;importjavax.validation.ValidatorFactory;importorg.junit.BeforeClass;importorg.junit.Test;importstaticorg.junit.Assert.assertEquals;publicclassCarTest{privatestaticValidatorvalidator;@BeforeClasspublicstaticvoidsetUpValidator(){ValidatorFactoryfactory=Validation.buildDefaultValidatorFactory();validator=factory.getValidator();}@TestpublicvoidmanufacturerIsNull(){Carcar=newCar(null,"DD-AB-123",4);Set<ConstraintViolation<Car>>constraintViolations=validator.validate(car);assertEquals(1,constraintViolations.size());assertEquals("mustnotbenull",constraintViolations.iterator().next().getMessage());}@TestpublicvoidlicensePlateTooShort(){Carcar=newCar("Morris","D",4);Set<ConstraintViolation<Car>>constraintViolations=validator.validate(car);assertEquals(1,constraintViolations.size());assertEquals(8"sizemustbebetween2and14",constraintViolations.iterator().next().getMessage());}@TestpublicvoidseatCountTooLow(){Carcar=newCar("Morris","DD-AB-123",1);Set<ConstraintViolation<Car>>constraintViolations=validator.validate(car);assertEquals(1,constraintViolations.size());assertEquals("mustbegreaterthanorequalto2",constraintViolations.iterator().next().getMessage());}@TestpublicvoidcarIsValid(){Carcar=newCar("Morris","DD-AB-123",2);Set<ConstraintViolation<Car>>constraintViolations=validator.validate(car);assertEquals(0,constraintViolations.size());}}在setUp()方法中,从ValidatorFactory中检索Validator对象。Validator实例是线程安全的,并且可以多次重用。因此,它可以安全地存储在静态字段中,并用于测试方法中以验证不同的Car实例。validate()方法返回一组ConstraintViolation实例,您可以对其进行迭代以查看发生了哪些验证错误。前三种测试方法显示了一些预期的约束违规:•The@NotNullconstraintonmanufacturerisviolatedinmanufacturerIsNull()•The@SizeconstraintonlicensePlateisviolatedinlicensePlateTooShort()•The@MinconstraintonseatCountisviolatedinseatCountTooLow()如果对象验证成功,validate()将返回一个空集,如在carIsValid()中看到的那样。请注意,仅使用包javax.validation中的类。这些是从Bean验证API提供的。没有直接引用HibernateValidator中的类,从而导致了可移植代码。1.4.接下来要去哪里?结束了整个5分钟的HibernateValidator和JakartaBeanValidation之旅。继续探索代码示例,或查看第14章“进一步阅读”中引用的其他示例。9要了解有关bean和属性验证的更多信息,只需继续阅读第2章,声明和验证bean约束。如果您有兴趣使用JakartaBean验证来验证方法的前提条件和后置条件,请参阅第3章,声明和验证方法约束。如果您的应用程序有特定的验证要求,请参阅第6章,创建自定义约束。10第2章声明和验证bean约束在本章中,您将学习如何声明(请参见第2.1节,“声明bean约束”)和验证(请参见第2.2节,“验证bean约束”)。第2.3节“内置约束”概述了HibernateValidator附带的所有内置约束。如果您有兴趣将约束应用于方法参数和返回值,请参阅第3章,声明和验证方法约束。2.1.声明bean约束JakartaBean验证中的约束通过Java注释表示。在本节中,您将学习如何使用这些注释来增强对象模型。bean约束有四种类型:•fieldconstraints(字段约束)•propertyconstraints(属性约束)•containerelementconstraints(容器元素约束)•classconstraints(类约束)并非所有约束都可以放在所有这些级别上。实际上,JakartaBeanValidation定义的默认约束都不能放在类级别。约束注释本身中的java.lang.annotation.Target注释确定约束可以放置在哪些元素上。有关更多信息,请参见第6章,创建自定义约束。2.1.1.字段级别的约束可以通过注释类的字段来表达约束。例2.1“字段级约束”显示了一个字段级配置示例:11示例2.1:字段级约束packageorg.hibernate.validator.referenceguide.chapter02.fieldlevel;publicclassCar{@NotNullprivateStringmanufacturer;@AssertTrueprivatebooleanisRegistered;publicCar(Stringmanufacturer,booleanisRegistered){this.manufacturer=manufacturer;this.isRegistered=isRegistered;}//gettersandsetters...}使用字段级约束时,将使用字段访问策略来访问要验证的值。这意...