我是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
的值时,它看起来在两个地方:
PropertyModel
调用getter来检索属性的值。具体来说,PropertyModel
寻找一个名为get<Property>
的方法,其中<Property>
是传递给PropertyModel
构造函数的属性表达式,并在存在的情况下使用反射调用该方法。 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()));
}
}