如何使用 Hibernate Validator 验证重写的方法参数?
How to validate overridden methods parameters with Hibernate Validator?
关于 this doc I understand that if I have my GroupService which implements GroupManager and overrides its methods, then I cannot annotate with validation constraints since Hibernate Validator doesn't allow it (which turns out to be known as the Liskov substitution principle)。我的意思是做类似
的事情
public class GroupService implements GroupManager{
@Override
public List<String> findUsersInGroup(@NotNull String groupName) {
...
}
}
然后会引发一个ConstraintDeclarationException
,对吧?所以解决方案显然是将这些约束放在接口上,但在那种情况下:
- 我可能无法修改界面(在本例中
GroupManager
属于 Spring Security
)。那我该怎么做呢?
- 我认为这些验证约束不应该影响接口,因为它们是接口实现的一部分,所以如果我想要任何其他服务实现,我不应该将它与这些验证挂钩.也许有了这个新的我想实现另一种验证,并且
Hibernate Validator
迫使我 'dirty up' 接口
I could probably not have access to modificate interface (as this case where GroupManager belongs to Spring Security). How should i do in this case?
您可以使用 xml 配置,因为 JSR-303(Bean 验证)支持它。例如
<constraint-mappings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://jboss.org/xml/ns/javax/validation/mapping validation-mapping-1.0.xsd"
xmlns="http://jboss.org/xml/ns/javax/validation/mapping">
<default-package>org.springframework.security.provisioning</default-package>
<bean class="GroupManager" ignore-annotations="true">
<method name="findUsersInGroup">
<parameter type="java.lang.String">
<constraint annotation="javax.validation.constraints.NotNull"/>
</parameter>
</method>
</bean>
</constraint-mappings>
参见 hibernate doc 中的 xml 配置章节。
I have the thought that these validation constraints should not affect the interface since they are part of its implementation
正如休眠文档所说
When a method is overridden in sub-types method parameter constraints can only be declared at the base type. The reason for this restriction is that the preconditions to be fulfilled by a type's client must not be strengthened in sub-types (which may not even be known to the base type's client).
方法的先决条件不应由子类型加强。如果您说您的子类型 GroupService
不允许 null
参数,您可能会加强前提条件。例如。使用 GroupManager
的客户端可能不知道(也不应该知道)它是 GroupService
。 GroupManager
接口不对参数做任何限制。因此,如果您这样做,就会破坏以前合法的客户代码。这违反了 Liskov substitution principle.
遗憾的是 GroupManager
javadoc 没有限制参数。因此,法律实施必须处理所有情况。
通常...当我定义方法时,我会应用这些规则
- 如果一个方法定义了一个参数,那么它不能是
null
。
- 如果参数是可选的 - 创建重载方法并在内部处理可选参数。例如。通过使用 null object pattern.
这些简单的规则帮助我为客户创造一个清晰的api。
编辑
i think possible that i have impl "A" and impl "B" (both implementing same interface) where impl "A" has more (and different) validations than "B"
如果是这样,它们就没有相同的界面或 api。您看到的是两者具有相同的方法签名。但是两个相等的方法签名不能共享相同的 api 契约。当我谈论接口时,我会想到契约
而不仅仅是签名。想象一下下面的界面:
public class Container {
/**
* @return a non-empty collection of elements.
*/
public Collection<Element> getElements();
}
在这种情况下,合法的客户代码是
Container container = ....;
Element firstElement = container.getElements().iterator().next();
因为合约说它 returns 是一个非空集合。
如果我们更改 javadoc 并因此更改 post-条件...
/**
* @return a collection of elements.
*/
public Collection<Element> getElements();
以前合法的客户端代码将不再有效。
我只是做了这个例子来向你展示契约和方法签名之间的区别。
可以找到详细很好的解释here。
As GroupManager javadoc doesn't restrict the parameter ,a legal impl must handle every situation'? Is that validating params inside method?
是的。如果接口不对参数添加任何限制,则实现必须处理每个状态,因为客户端可能会传递参数
在任何状态下。
关于 this doc I understand that if I have my GroupService which implements GroupManager and overrides its methods, then I cannot annotate with validation constraints since Hibernate Validator doesn't allow it (which turns out to be known as the Liskov substitution principle)。我的意思是做类似
的事情public class GroupService implements GroupManager{
@Override
public List<String> findUsersInGroup(@NotNull String groupName) {
...
}
}
然后会引发一个ConstraintDeclarationException
,对吧?所以解决方案显然是将这些约束放在接口上,但在那种情况下:
- 我可能无法修改界面(在本例中
GroupManager
属于Spring Security
)。那我该怎么做呢? - 我认为这些验证约束不应该影响接口,因为它们是接口实现的一部分,所以如果我想要任何其他服务实现,我不应该将它与这些验证挂钩.也许有了这个新的我想实现另一种验证,并且
Hibernate Validator
迫使我 'dirty up' 接口
I could probably not have access to modificate interface (as this case where GroupManager belongs to Spring Security). How should i do in this case?
您可以使用 xml 配置,因为 JSR-303(Bean 验证)支持它。例如
<constraint-mappings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://jboss.org/xml/ns/javax/validation/mapping validation-mapping-1.0.xsd"
xmlns="http://jboss.org/xml/ns/javax/validation/mapping">
<default-package>org.springframework.security.provisioning</default-package>
<bean class="GroupManager" ignore-annotations="true">
<method name="findUsersInGroup">
<parameter type="java.lang.String">
<constraint annotation="javax.validation.constraints.NotNull"/>
</parameter>
</method>
</bean>
</constraint-mappings>
参见 hibernate doc 中的 xml 配置章节。
I have the thought that these validation constraints should not affect the interface since they are part of its implementation
正如休眠文档所说
When a method is overridden in sub-types method parameter constraints can only be declared at the base type. The reason for this restriction is that the preconditions to be fulfilled by a type's client must not be strengthened in sub-types (which may not even be known to the base type's client).
方法的先决条件不应由子类型加强。如果您说您的子类型 GroupService
不允许 null
参数,您可能会加强前提条件。例如。使用 GroupManager
的客户端可能不知道(也不应该知道)它是 GroupService
。 GroupManager
接口不对参数做任何限制。因此,如果您这样做,就会破坏以前合法的客户代码。这违反了 Liskov substitution principle.
遗憾的是 GroupManager
javadoc 没有限制参数。因此,法律实施必须处理所有情况。
通常...当我定义方法时,我会应用这些规则
- 如果一个方法定义了一个参数,那么它不能是
null
。 - 如果参数是可选的 - 创建重载方法并在内部处理可选参数。例如。通过使用 null object pattern.
这些简单的规则帮助我为客户创造一个清晰的api。
编辑
i think possible that i have impl "A" and impl "B" (both implementing same interface) where impl "A" has more (and different) validations than "B"
如果是这样,它们就没有相同的界面或 api。您看到的是两者具有相同的方法签名。但是两个相等的方法签名不能共享相同的 api 契约。当我谈论接口时,我会想到契约 而不仅仅是签名。想象一下下面的界面:
public class Container {
/**
* @return a non-empty collection of elements.
*/
public Collection<Element> getElements();
}
在这种情况下,合法的客户代码是
Container container = ....;
Element firstElement = container.getElements().iterator().next();
因为合约说它 returns 是一个非空集合。
如果我们更改 javadoc 并因此更改 post-条件...
/**
* @return a collection of elements.
*/
public Collection<Element> getElements();
以前合法的客户端代码将不再有效。
我只是做了这个例子来向你展示契约和方法签名之间的区别。
可以找到详细很好的解释here。
As GroupManager javadoc doesn't restrict the parameter ,a legal impl must handle every situation'? Is that validating params inside method?
是的。如果接口不对参数添加任何限制,则实现必须处理每个状态,因为客户端可能会传递参数 在任何状态下。