Hibernate Validator 中文操作指南
8. Configuring via XML
到目前为止,我们已经为 Jakarta Bean Validation 使用了默认的配置源,即注解。但是,还存在两种允许通过 XML 进行配置的 XML 描述符。第一个描述符描述了通用的 Jakarta Bean Validation 行为,并作为 META-INF/validation.xml 提供。第二个描述符描述了约束声明,并且与通过注解的约束声明方法完全匹配。让我们看看这两个文档类型。
XSD 文件在 https://jakarta.ee/xml/ns/validation/ 页面上可用。 |
8.1. Configuring the validator factory in validation.xml
为 Hibernate 验证器启用 XML 配置的关键文件是 META-INF/validation.xml。如果此文件存在于 classpath 上,则会在创建 ValidatorFactory 时应用其配置。 Figure 1, “Validation configuration schema” 展示了 validation.xml 必须遵守的 XML 模式的模型视图。
Example 8.1, “validation.xml” 展示了 validation.xml 的几个配置选项。所有设置都是可选的,并且相同的配置选项也可以通过 jakarta.validation.Configuration 以编程方式获得。事实上,将通过编程 API 明确指定的值覆盖 XML 配置。甚至可以通过 Configuration#ignoreXmlConfiguration() 完全忽略 XML 配置。另请参见 Section 9.2, “Configuring a ValidatorFactory” 。
<validation-config
xmlns="https://jakarta.ee/xml/ns/validation/configuration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/validation/configuration
https://jakarta.ee/xml/ns/validation/validation-configuration-3.0.xsd"
version="3.0">
<default-provider>com.acme.ValidationProvider</default-provider>
<message-interpolator>com.acme.MessageInterpolator</message-interpolator>
<traversable-resolver>com.acme.TraversableResolver</traversable-resolver>
<constraint-validator-factory>
com.acme.ConstraintValidatorFactory
</constraint-validator-factory>
<parameter-name-provider>com.acme.ParameterNameProvider</parameter-name-provider>
<clock-provider>com.acme.ClockProvider</clock-provider>
<value-extractor>com.acme.ContainerValueExtractor</value-extractor>
<executable-validation enabled="true">
<default-validated-executable-types>
<executable-type>CONSTRUCTORS</executable-type>
<executable-type>NON_GETTER_METHODS</executable-type>
<executable-type>GETTER_METHODS</executable-type>
</default-validated-executable-types>
</executable-validation>
<constraint-mapping>META-INF/validation/constraints-car.xml</constraint-mapping>
<property name="hibernate.validator.fail_fast">false</property>
</validation-config>
类路径中只能有一个名为 META-INF/validation.xml 的文件。如果找到多个,将引发异常。
节点 default-provider 允许选择 Jakarta Bean Validation 提供程序。如果类路径上有多个提供程序,这将会很有用。 message-interpolator 、 traversable-resolver 、 constraint-validator-factory 、 parameter-name-provider 和 clock-provider 允许自定义 jakarta.validation 包中定义的接口 MessageInterpolator 、 TraversableResolver 、 ConstraintValidatorFactory 、 ParameterNameProvider 和 ClockProvider 的已用实现。有关这些接口的更多信息,请参阅 Section 9.2, “Configuring a ValidatorFactory” 的子部分。
value-extractor 允许声明其他值提取器,以从自定义容器类型中提取值或覆盖内置的值提取器。有关如何实现 jakarta.validation.valueextraction.ValueExtractor 的更多信息,请参见 Chapter 7, Value extraction 。
executable-validation 及其子节点为方法验证定义了默认值。Jakarta Bean Validation 规范将构造函数和非 getter 方法定义为默认值。enabled 属性充当全局开关,用于打开和关闭方法验证(参见 Chapter 3, Declaring and validating method constraints )。
通过 constraint-mapping 元素,您可以列出任意数量包含实际约束配置的其他 XML 文件。映射文件名必须使用其在类路径上的完全限定名称指定。有关编写映射文件的详细信息,请参见下一节。
最后但并非最不重要的一点是,你可以在 property 节点中指定提供者特定的属性。在示例中,我们正在使用 Hibernate 验证器特定的 hibernate.validator.fail_fast 属性(参见 Section 12.2, “Fail fast mode”)。
8.2. Mapping constraints via constraint-mappings
通过遵循 Figure 2, “Validation mapping schema” 中模式的文件可以表达 XML 中的约束。请注意,仅当通过 validation.xml 中的 constraint-mapping 列出时,才会处理这些映射文件。
Example 8.2, “Bean constraints configured via XML” 展示了来自 Example 5.3, “Car” 和 Example 5.9, “Class RentalCar with redefined default group” 的 Car 和 RentalCar 类如何在 XML 中映射。
<constraint-mappings
xmlns="https://jakarta.ee/xml/ns/validation/mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/validation/mapping
https://jakarta.ee/xml/ns/validation/validation-mapping-3.0.xsd"
version="3.0">
<default-package>org.hibernate.validator.referenceguide.chapter05</default-package>
<bean class="Car" ignore-annotations="true">
<field name="manufacturer">
<constraint annotation="jakarta.validation.constraints.NotNull"/>
</field>
<field name="licensePlate">
<constraint annotation="jakarta.validation.constraints.NotNull"/>
</field>
<field name="seatCount">
<constraint annotation="jakarta.validation.constraints.Min">
<element name="value">2</element>
</constraint>
</field>
<field name="driver">
<valid/>
</field>
<field name="partManufacturers">
<container-element-type type-argument-index="0">
<valid/>
</container-element-type>
<container-element-type type-argument-index="1">
<container-element-type>
<valid/>
<constraint annotation="jakarta.validation.constraints.NotNull"/>
</container-element-type>
</container-element-type>
</field>
<getter name="passedVehicleInspection" ignore-annotations="true">
<constraint annotation="jakarta.validation.constraints.AssertTrue">
<message>The car has to pass the vehicle inspection first</message>
<groups>
<value>CarChecks</value>
</groups>
<element name="max">10</element>
</constraint>
</getter>
</bean>
<bean class="RentalCar" ignore-annotations="true">
<class ignore-annotations="true">
<group-sequence>
<value>RentalCar</value>
<value>CarChecks</value>
</group-sequence>
</class>
</bean>
<constraint-definition annotation="org.mycompany.CheckCase">
<validated-by include-existing-validators="false">
<value>org.mycompany.CheckCaseValidator</value>
</validated-by>
</constraint-definition>
</constraint-mappings>
Example 8.3, “Method constraints configured via XML”显示了来自 Example 3.1, “Declaring method and constructor parameter constraints”、 Example 3.4, “Declaring method and constructor return value constraints”和 Example 3.3, “Specifying a constraint’s target”的约束如何表示在 XML 中。
<constraint-mappings
xmlns="https://jakarta.ee/xml/ns/validation/mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/validation/mapping
https://jakarta.ee/xml/ns/validation/validation-mapping-3.0.xsd"
version="3.0">
<default-package>org.hibernate.validator.referenceguide.chapter08</default-package>
<bean class="RentalStation" ignore-annotations="true">
<constructor>
<return-value>
<constraint annotation="ValidRentalStation"/>
</return-value>
</constructor>
<constructor>
<parameter type="java.lang.String">
<constraint annotation="jakarta.validation.constraints.NotNull"/>
</parameter>
</constructor>
<method name="getCustomers">
<return-value>
<constraint annotation="jakarta.validation.constraints.NotNull"/>
<constraint annotation="jakarta.validation.constraints.Size">
<element name="min">1</element>
</constraint>
</return-value>
</method>
<method name="rentCar">
<parameter type="Customer">
<constraint annotation="jakarta.validation.constraints.NotNull"/>
</parameter>
<parameter type="java.util.Date">
<constraint annotation="jakarta.validation.constraints.NotNull"/>
<constraint annotation="jakarta.validation.constraints.Future"/>
</parameter>
<parameter type="int">
<constraint annotation="jakarta.validation.constraints.Min">
<element name="value">1</element>
</constraint>
</parameter>
</method>
<method name="addCars">
<parameter type="java.util.List">
<container-element-type>
<valid/>
<constraint annotation="jakarta.validation.constraints.NotNull"/>
</container-element-type>
</parameter>
</method>
</bean>
<bean class="Garage" ignore-annotations="true">
<method name="buildCar">
<parameter type="java.util.List"/>
<cross-parameter>
<constraint annotation="ELAssert">
<element name="expression">...</element>
<element name="validationAppliesTo">PARAMETERS</element>
</constraint>
</cross-parameter>
</method>
<method name="paintCar">
<parameter type="int"/>
<return-value>
<constraint annotation="ELAssert">
<element name="expression">...</element>
<element name="validationAppliesTo">RETURN_VALUE</element>
</constraint>
</return-value>
</method>
</bean>
</constraint-mappings>
XML 配置紧密反映编程 API。因此,仅添加一些注释就足够了。default-package 用于所有需要类名的字段。如果指定的类不是完全限定的,则将使用配置的默认包。然后每个映射文件可以有多个 bean 节点,每个节点描述具有指定类名的实体上的约束。
一个特定的类在所有配置文件中只能配置一次。对给定约束注释的约束定义同样适用。它仅能出现在一个映射文件中。如果违反这些规则,将抛出 ValidationException。
将 ignore-annotations 设置为 true 表示忽略放置在配置的 Bean 中的约束注解。此值默认设置为 true。ignore-annotations 也可用于 class、fields、getter、constructor、method、parameter、cross-parameter 和 return-value 节点。如果没有在此类级别上明确指定,则应用配置的 Bean 值。
class、field、getter、container-element-type、constructor 和 method 节点(及其子节点参数)确定约束放置在哪个级别。valid 节点用于启用级联验证,constraint 节点用于在相应级别上添加约束。每个约束定义都必须通过 annotation 属性定义类。Jakarta Bean Validation 规范所需的约束属性(message、groups 和 payload)具有专用的节点。所有其他特定于约束的属性都使用 element 节点配置。
container-element-type 允许定义级联验证行为和容器元素的约束。在上面的示例中,您可以看到嵌套在 Map 值中的 List 上的嵌套容器元素约束的示例。type-argument-index 用于精确指出 Map 的哪个类型参数涉及配置。如果类型只有一个类型参数(例如,我们示例中的 List),则可以省略它。 |
class_节点还允许通过 _group-sequence_节点重新配置默认的组顺序(参见 Section 5.4, “Redefining the default group sequence”)。在示例中未显示的是 _convert-group_的使用,用于指定组转换(参见 Section 5.5, “Group conversion”)。此节点在 _field、getter、container-element-type、_parameter_和 _return-value_上可用,并指定属性 _from_和 _to_来指定组。
最后但并非最不重要的是,可以通過 constraint-definition 節點變更與給定約束相關聯的 ConstraintValidator 實例列表。annotation 屬性表示要變更的約束註釋。validated-by 元素表示與約束相關聯的 ConstraintValidator 實例的(已排序)列表。如果 include-existing-validator 設置為 false,則會忽略約束註釋上定義的驗證器。如果設置為 true,則 XML 中描述的約束驗證器列表會連接至註釋上指定的驗證器列表。
约束定义的一个用例是更改 @URL 的默认约束定义。从历史上看,Hibernate Validator 对此约束的默认约束验证器使用 java.net.URL 构造函数来验证 URL 是否有效。然而,还有一个基于纯正则表达式的版本,可以使用 XML 进行配置: |
使用 XML 注册基于正则表达式的约束定义以进行 @URL_ <constraint-definition annotation="org.hibernate.validator.constraints.URL"> <validated-by include-existing-validators="false"> <value>org.hibernate.validator.constraintvalidators.RegexpURLValidator</value> </validated-by></constraint-definition>_
使用 XML 注册基于正则表达式的约束定义以进行 @URL <constraint-definition annotation="org.hibernate.validator.constraints.URL"> <validated-by include-existing-validators="false"> <value>org.hibernate.validator.constraintvalidators.RegexpURLValidator</value> </validated-by> </constraint-definition>