Wicket PropertyModel stranezza?
-
23-08-2019 - |
Domanda
Sono nuovo di Wicket e stavo provando la seguente configurazione:
class User {
private String password;
...
public void setPassword(String password) {
this.password = MD5.encode(password);
}
...
}
Dopo aver provato a utilizzare quanto segue per associarsi alla password e aver scoperto che l'implementazione predefinita di PropertyModel è per impostazione predefinita associata al campo, non alla proprietà (nome strano eh?)
add(new PasswordTextField("password", new PropertyModel(user, "password"));
Perché mai avrebbero dovuto implementarlo in questo modo?Ed esiste un'alternativa PropertyModel che utilizza getter e setter per impostazione predefinita?
Grazie?
Soluzione
PropertyModel
farà già quello che vuoi.Quando un PropertyModel
viene interrogato il suo valore, cerca in due posti:
Se esiste un metodo "getter" per la proprietà data, il file
PropertyModel
chiama il getter per recuperare il valore della proprietà.Nello specifico, ilPropertyModel
cerca un metodo denominatoget<Property>
, Dove<Property>
è l'espressione della proprietà passata aPropertyModel
costruttore e chiama il metodo utilizzando la riflessione, se esiste.Se non esiste alcun metodo "getter", il file
PropertyModel
restituisce direttamente il valore del campo della proprietà.Nello specifico, ilPropertyModel
usa la riflessione trova un campo che corrisponda all'espressione della proprietà passata aPropertyModel
costruttore.Se viene trovato un campo corrispondente, il filePropertyModel
restituisce il valore del campo.Si noti che ilPropertyModel
controllerà la corrispondenza nei campi privati e protetti oltre ai campi pubblici.
Nel tuo caso, l'espressione di proprietà utilizzata nel file PropertyModel
il costruttore è "password"
, così il PropertyModel
cercherà prima un metodo sul file user
oggetto chiamato getPassword
.Se tale metodo non esiste, il PropertyModel
restituirà il valore del privato password
campo invece.
Poiché nel tuo caso il PropertyModel
sta restituendo il valore del campo privato invece di chiamare il "getter", molto probabilmente hai digitato erroneamente il nome del getter nel tuo User
classe.Ad esempio, se hai digitato accidentalmente getPasssword
(con 3 s), il PropertyModel
non lo troverà e tornerà al campo privato.
MODIFICARE
Se non ti piace PropertyModel
è il comportamento predefinito di, puoi creare una sottoclasse di PropertyModel
ciò impedirà a Wicket di tentare di leggere/scrivere nei campi privati.In questo modo, puoi forzare tutti gli accessi alle proprietà tramite getter e setter.
Ho scritto un esempio BeanPropertyModel
classe per dimostrarlo:
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()));
}
}
Altri suggerimenti
grande risposta da mike Spross! una piccola aggiunta però:
Non userei il modello di proprietà in questo caso. basta scrivere
new Model<String>(){ getObject(){...} setObject(){...}}
e attuare la bahavior corretta, che fa esattamente quello che vuoi.