Странность Wicket PropertyModel?
-
23-08-2019 - |
Вопрос
Я новичок в 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"));
С какой стати они реализовали это таким образом?И есть ли альтернатива PropertyModel, которая по умолчанию использует методы получения и установки?
Спасибо?
Решение
PropertyModel
уже сделаю то, что ты хочешь.Когда PropertyModel
запрашивается его значение, оно ищется в двух местах:
Если для данного свойства существует метод получения,
PropertyModel
вызывает метод получения для получения значения свойства.В частности,PropertyModel
ищет метод с именемget<Property>
, где<Property>
— это выражение свойства, передаваемое вPropertyModel
конструктор и вызывает метод, используя отражение, если оно существует.Если метода «получателя» не существует,
PropertyModel
возвращает значение поля свойства напрямую.В частности,PropertyModel
использует отражение, находит поле, соответствующее выражению свойства, переданному вPropertyModel
конструктор.Если соответствующее поле найдено,PropertyModel
возвращает значение поля.Обратите внимание, чтоPropertyModel
проверит частные и защищенные поля в дополнение к общедоступным полям на предмет совпадения.
В вашем случае выражение свойства, используемое в PropertyModel
конструктор "password"
, Итак PropertyModel
сначала будем искать метод на user
объект под названием getPassword
.Если такого метода не существует, PropertyModel
вернет значение частного password
поле вместо этого.
Поскольку в вашем случае PropertyModel
возвращает значение частного поля вместо вызова «геттера», вы, скорее всего, ошиблись в имени геттера в своем User
сорт.Например, если вы случайно набрали getPasssword
(с 3-мя буквами), PropertyModel
не найдет его и вернется к возврату частного поля.
РЕДАКТИРОВАТЬ
Если тебе не нравится PropertyModel
поведение по умолчанию, вы можете создать подкласс PropertyModel
это не позволит Wicket пытаться читать/записывать частные поля.Таким образом, вы можете заставить все обращения к свойствам осуществляться через геттеры и сеттеры.
я написал пример 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(){...}}
и реализовать правильное поведение, которое делает именно то, что вы хотите.