Data binding Wicket PropertyModel奇怪?

Data binding Wicket PropertyModel奇怪?,data-binding,wicket,Data Binding,Wicket,我是Wicket的新手,正在尝试以下配置: class User { private String password; ... public void setPassword(String password) { this.password = MD5.encode(password); } ... } 尝试使用以下内容绑定到密码并发现PropertyModel的默认实现默认绑定到字段,而不是属性(奇怪的名称eh?) 他们究竟为什么要这样实施呢?是否

我是Wicket的新手,正在尝试以下配置:

class User {
   private String password;

   ...

   public void setPassword(String password) {
     this.password = MD5.encode(password);
   }
   ...
}
尝试使用以下内容绑定到密码并发现PropertyModel的默认实现默认绑定到字段,而不是属性(奇怪的名称eh?)

他们究竟为什么要这样实施呢?是否有默认使用getter和setter的PropertyModel替代方案


谢谢?

PropertyModel
已经可以满足您的需求了。当查询
PropertyModel
的值时,它会在两个位置查找:

  • 如果给定属性存在“getter”方法,则
    PropertyModel
    调用getter来检索属性的值。具体来说,
    PropertyModel
    查找名为
    get
    的方法,其中
    是传递给
    PropertyModel
    构造函数的属性表达式,如果存在,则使用反射调用该方法

  • 如果不存在“getter”方法,
    PropertyModel
    直接返回属性字段的值。具体来说,
    PropertyModel
    使用反射查找与传递给
    PropertyModel
    构造函数的属性表达式匹配的字段。如果找到匹配的字段,
    PropertyModel
    将返回该字段的值。请注意,
    PropertyModel
    除了检查公共字段外,还会检查私有字段和受保护字段是否匹配

在您的例子中,
PropertyModel
构造函数中使用的属性表达式是
“password”
,因此
PropertyModel
将首先在名为
getPassword
user
对象上查找方法。如果不存在这样的方法,
PropertyModel
将返回private
password
字段的值

因为在您的例子中,
PropertyModel
返回私有字段的值,而不是调用“getter”,所以您很可能在
User
类中键入了getter的名称。例如,如果您不小心键入了
getPassSwarm
(带有3个s),则
PropertyModel
将找不到它,并返回私有字段


编辑

如果您不喜欢
PropertyModel
的默认行为,可以创建
PropertyModel
的子类,以防止Wicket尝试读取/写入私有字段。通过这种方式,您可以强制通过getter和setter进行所有属性访问

我编写了一个示例
BeanPropertyModel
类来演示这一点:

import org.apache.wicket.WicketRuntimeException;
import org.apache.wicket.model.PropertyModel;

/**
 * A custom implementation of {@link org.apache.wicket.model.PropertyModel}
 * that can only be bound to properties that have a public getter or setter method.
 * 
 * @author mspross
 *
 */
public class BeanPropertyModel extends PropertyModel {

    public BeanPropertyModel(Object modelObject, String expression) {
        super(modelObject, expression);
    }

    @Override
    public Object getObject() {
        if(getPropertyGetter() == null)
            fail("Missing getter");
        return super.getObject();               
    }

    @Override
    public void setObject(Object modelObject) {
        if(getPropertySetter() == null)
            fail("Missing setter");
        super.setObject(modelObject);
    }

    private void fail(String message) {

        throw new WicketRuntimeException(
                String.format("%s. Property expression: '%s', class: '%s'.",
                        message,
                        getPropertyExpression(),
                        getTarget().getClass().getCanonicalName()));
    }
}

迈克·斯普罗斯的回答很好! 不过,还有一个小小的补充:

在这种情况下,我不会使用属性模型。只要写

 new Model<String>(){ getObject(){...} setObject(){...}}
newmodel(){getObject(){…}setObject(){…}

并实现正确的bahavior,这正是您想要的。

回答得很好!非常感谢你为我澄清这一点。我一直在做的不是提供一个getter,而是希望它能被称为setter。原因是我不希望用户对象具有getPassword()方法。它仍然会调用setter,因为您定义了一个,但当Wicket呈现密码字段时,它会尝试“获取”模型值,并最终检索私有字段。如果要防止出现这种情况,可以重写getObject()以返回null或“*”字符字符串,或其他任何形式。+1-如果这是“一次性”的,这是获得所需功能的最简单方法。
 new Model<String>(){ getObject(){...} setObject(){...}}