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

class User {
   private String password;

   ...

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

尝试使用以下内容绑定(bind)到密码并发现默认情况下,PropertyModel的默认实现是绑定(bind)到字段,而不是属性(怪异名称eh?)
add(new PasswordTextField("password", new PropertyModel(user, "password"));

他们为什么在世界上会以这种方式实现它?是否有一个PropertyModel替代方案,默认情况下使用getter和setters?

谢谢?

最佳答案

PropertyModel将完成您想做的事情。当查询PropertyModel的值时,它看起来在两个地方:

  • 如果给定属性存在“getter”方法,则PropertyModel调用getter来检索属性的值。具体来说,PropertyModel寻找一个名为get<Property>的方法,其中<Property>是传递给PropertyModel构造函数的属性表达式,并在存在的情况下使用反射调用该方法。
  • 如果不存在“getter”方法,则PropertyModel直接返回属性字段的值。具体来说,PropertyModel使用反射查找与传递给PropertyModel构造函数的属性表达式匹配的字段。如果找到匹配的字段,则PropertyModel返回该字段的值。请注意,除了公共(public)字段外,PropertyModel还将检查私有(private)字段和 protected 字段是否匹配。

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

    由于在您的情况下PropertyModel返回的是私有(private)字段的值,而不是调用“getter”,因此您很可能在User类中键入了getter的名称。例如,如果您不小心键入了getPasssword(带有3 s),则PropertyModel将找不到它,并且会退回到返回私有(private)字段的位置。

    编辑

    如果您不喜欢PropertyModel的默认行为,则可以创建PropertyModel的子类,该子类将阻止Wicket尝试读取/写入私有(private)字段。这样,您可以强制所有属性访问都通过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()));
        }
    }
    

    10-03 00:32