Калитка PropertyModel странность? - PullRequest
5 голосов
/ 14 февраля 2009

Я новичок в 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, которая использует getter и setters по умолчанию?

Спасибо?

Ответы [ 2 ]

11 голосов
/ 14 февраля 2009

PropertyModel будет делать то, что вы уже хотите. Когда PropertyModel запрашивается его значение, оно выглядит в двух местах:

  • Если для данного свойства существует метод «getter», PropertyModel вызывает метод getter для получения значения свойства. В частности, PropertyModel ищет метод с именем get<Property>, где <Property> - выражение свойства, переданное конструктору PropertyModel, и вызывает метод с использованием отражения, если он существует.

  • Если метод «getter» не существует, PropertyModel возвращает значение поля свойства напрямую. В частности, PropertyModel использует отражение найти поле, которое соответствует выражению свойства, переданному конструктору PropertyModel. Если соответствующее поле найдено, PropertyModel возвращает значение поля. Обратите внимание, что PropertyModel будет проверять личные и защищенные поля в дополнение к общедоступным полям на соответствие.

В вашем случае выражение свойства, используемое в конструкторе PropertyModel, равно "password", поэтому PropertyModel сначала будет искать метод для объекта user с именем getPassword. Если такого метода не существует, PropertyModel вернет значение частного поля password.

Поскольку в вашем случае PropertyModel возвращает значение приватного поля вместо вызова "getter", вы, скорее всего, опечатали имя получателя в своем классе User. Например, если вы случайно набрали getPasssword (с 3 с), PropertyModel не найдет его и вернется к возвращению приватного поля.


EDIT

Если вам не нравится поведение 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()));
    }
}
3 голосов
/ 18 февраля 2009

отличный ответ Майка Спросса! хотя одно небольшое дополнение:

Я бы не использовал модель свойств в этом случае. просто напишите

 new Model<String>(){ getObject(){...} setObject(){...}}

и реализуйте правильное поведение, которое делает именно то, что вы хотите.

...