我是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替代方法?
谢谢?
PropertyModel
会做你想做的事.当a PropertyModel
查询其值时,它会在两个位置查找:
如果给定属性存在"getter"方法,则PropertyModel
调用getter来检索属性的值.具体来说,PropertyModel
查找名为的方法get
,其中
是传递给PropertyModel
构造函数的属性表达式,如果存在,则使用反射调用该方法.
如果不存在"getter"方法,则PropertyModel
直接返回属性字段的值.具体来说,PropertyModel
uses反射找到一个与传递给PropertyModel
构造函数的属性表达式匹配的字段.如果找到匹配的字段,则PropertyModel
返回字段的值.请注意,PropertyModel
除了匹配的公共字段外,还将检查私有字段和受保护字段.
在您的情况下,PropertyModel
构造函数中使用的属性表达式是"password"
,因此PropertyModel
将首先在被user
调用的对象上查找方法getPassword
.如果不存在这样的方法,PropertyModel
则将返回私有password
字段的值.
因为在你的情况下,PropertyModel
返回私有字段的值而不是调用"getter",你很可能错误地输入了User
类中getter的名称.例如,如果您意外键入getPasssword
(使用3秒),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())); } }