Data binding Wicket PropertyModel奇怪?
我是Wicket的新手,正在尝试以下配置: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?) 他们究竟为什么要这样实施呢?是否
class User {
private String password;
...
public void setPassword(String password) {
this.password = MD5.encode(password);
}
...
}
尝试使用以下内容绑定到密码并发现PropertyModel的默认实现默认绑定到字段,而不是属性(奇怪的名称eh?)
他们究竟为什么要这样实施呢?是否有默认使用getter和setter的PropertyModel替代方案
谢谢?
PropertyModel
已经可以满足您的需求了。当查询PropertyModel
的值时,它会在两个位置查找:
- 如果给定属性存在“getter”方法,则
调用getter来检索属性的值。具体来说,PropertyModel
查找名为PropertyModel
的方法,其中get
是传递给
构造函数的属性表达式,如果存在,则使用反射调用该方法PropertyModel
- 如果不存在“getter”方法,
直接返回属性字段的值。具体来说,PropertyModel
使用反射查找与传递给PropertyModel
构造函数的属性表达式匹配的字段。如果找到匹配的字段,PropertyModel
将返回该字段的值。请注意,PropertyModel
除了检查公共字段外,还会检查私有字段和受保护字段是否匹配PropertyModel
PropertyModel
构造函数中使用的属性表达式是“password”
,因此PropertyModel
将首先在名为getPassword
的user
对象上查找方法。如果不存在这样的方法,PropertyModel
将返回privatepassword
字段的值
因为在您的例子中,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(){...}}