【问题标题】:How to validate overridden methods parameters with Hibernate Validator?如何使用 Hibernate Validator 验证覆盖的方法参数?
【发布时间】:2015-07-16 18:35:38
【问题描述】:

关于this doc 我知道如果我的 GroupService 实现了 GroupManager 并覆盖了它的方法,那么我不能使用验证约束进行注释,因为 Hibernate Validator 不允许它(结果被称为 @987654322 @)。我的意思是做类似的事情

public class GroupService implements GroupManager{

    @Override
    public List<String> findUsersInGroup(@NotNull String groupName) {
        ...
    }
}

然后会引发ConstraintDeclarationException,对吗?所以解决方案显然是将这些约束放在接口上,但在这种情况下:

  1. 我可能无法修改界面(因为在这种情况下GroupManager 属于Spring Security)。那我该怎么办呢?
  2. 我认为这些验证约束不应该影响接口,因为它们是其实现的一部分,所以如果我想要任何其他服务实现,我不应该将它与这些验证挂钩。也许有了这个新的,我想实现另一种验证,Hibernate Validator 迫使我“弄脏”界面

【问题讨论】:

    标签: java validation constraints hibernate-validator


    【解决方案1】:

    我可能无法访问修改接口(在这种情况下 GroupManager 属于 Spring Security)。这种情况我该怎么办?

    您可以使用 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配置章节。

    我认为这些验证约束不应该影响接口,因为它们是其实现的一部分

    正如休眠文档所说

    当方法在子类型中被重写时,方法参数约束只能在基类型中声明。这个限制的原因是一个类型的客户端必须满足的先决条件不能在子类型中得到加强(甚至可能不为基类型的客户端所知)。

    方法的前置条件不应该通过子类型来加强。如果您说您的子类型 GroupService 不允许使用 null 参数,您可能会加强前提条件。例如。使用GroupManager 的客户端可能不知道(也不应该知道)它是GroupServiceGroupManager 接口不对参数做任何限制。因此,如果您这样做,您会破坏以前合法的客户代码。这违反了Liskov substitution principle

    遗憾的是GroupManager javadoc 不限制参数。因此,法律实施必须处理所有情况。

    一般...当我定义方法时,我会应用这些规则

    • 如果一个方法定义了一个参数,那么它不能是null
    • 如果参数是可选的 - 创建重载方法并在内部处理可选参数。例如。通过使用null object pattern

    这些简单的规则帮助我为客户创建一个清晰的 api。

    编辑

    我认为我可能有 impl "A" 和 impl "B"(两者都实现相同的接口),其中 impl "A" 比 "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();
    

    因为合约说它返回一个非空集合。

    如果我们更改 javadoc 并因此更改后置条件...

     /**
      * @return a collection of elements. 
      */
      public Collection<Element> getElements();
    

    以前合法的客户端代码将不再起作用。

    我只是做了这个例子来告诉你合同和方法签名之间的区别。

    详细的很好的解释可以找到here

    由于 GroupManager javadoc 不限制参数,合法的 impl 必须处理所有情况'?那是方法内部的验证参数吗?

    是的。如果接口没有对参数添加任何限制,则实现必须处理每个状态,因为客户端可能会传递参数 任何状态。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-05
      相关资源
      最近更新 更多