5

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

class User {
   private String password;

   ...

   public void setPassword(String password) {
     this.password = MD5.encode(password);
   }
   ...
}

在尝试使用以下绑定到密码并发现 PropertyModel 的默认实现是默认绑定到字段后,而不是属性(奇怪的名字吧?)

add(new PasswordTextField("password", new PropertyModel(user, "password"));

为什么他们会以这种方式实施它?是否有默认使用 getter 和 setter 的 PropertyModel 替代方案?

谢谢?

4

2 回答 2

11

PropertyModel会做你想做的事。当PropertyModel查询 a 的值时,它会在两个地方查找:

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

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

在您的情况下,PropertyModel构造函数中使用的属性表达式是"password",因此将首先在名为 的对象PropertyModel上查找方法。如果不存在这样的方法,则将返回私有字段的值。usergetPasswordPropertyModelpassword

由于在您的情况下PropertyModel返回私有字段的值而不是调用“getter”,因此您很可能在User类中输入了错误的 getter 名称。例如,如果您不小心输入getPasssword了(使用 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()));
    }
}
于 2009-02-14T05:33:39.130 回答
3

迈克·斯普罗斯(mike spross)的好回答!一个小小的补充:

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

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

并实施正确的行为,这正是您想要的。

于 2009-02-18T14:07:47.757 回答