Nach der offiziellen Veröffentlichung haben wir in Was ist mit den typischen Änderungen in Apache Wicket 8 passiert zusammengefasst.
Dieser Artikel ist für den 23.12. Von Java EE Adventskalender 2016.
Gestern @ HirofumiIwasakis "Zukünftiges Bild von Java EE 8 (überarbeitet) durch JavaOne 2016" -2016-java-ee-advent-kalender /). Morgen ist @kikutaro.
Das komponentenorientierte Webframework von Java ist heutzutage selten ein heißes Thema, aber JSF, Apache Wicket, Vaadin usw. sind typische Themen, die seit der zweiten Hälfte der 2000er Jahre kontinuierlich weiterentwickelt wurden. Kann erwähnt werden.
Apache Wicket-Anwendungsfälle sind hauptsächlich solche, die in Übersee veröffentlicht wurden https://twitter.com/apache_wicket, aber in Japan [Archivseite von Tagajo City](http :: Es gibt Berichte, dass es auch in //tagajo.irides.tohoku.ac.jp/index) und Meinungsfeld auf der Website der Polizeibehörde verwendet wird. Ich werde. Wicket selbst wird ebenfalls kontinuierlich von der Community weiterentwickelt, und Entwicklungsversionen von Wicket 8.0 für Java 8 werden ab sofort veröffentlicht.
Wicket 8.0 stellt Java 8 Lambda-Ausdrücke in Wicket-Komponenten und -Modellen zur Verfügung. Für Wicket-Benutzer, die sich in die Haltung eines Web-Frameworks verliebt haben, das für Java-Programmierer einfach zu entwickeln ist, kann dies als die lang erwartete Verbesserung bezeichnet werden, während sie sich fragen: "Wann wird es kommen?"
Vor diesem Hintergrund werden in diesem Artikel Wicket 8-Migrationshandbuch: Migration zu Wicket 8.0 und [ Ich möchte die Änderungen in der Art und Weise, wie Code aus Wicket 8.0 geschrieben wird, die in Zukunft veröffentlicht wird, unter Bezugnahme auf Dokumente des Kommissars auf der ApacheCon EU 2016 zusammenfassen.
Der Inhalt des Artikels basiert zum Zeitpunkt des Schreibens auf Wicket 8.0.0-M2 und kann sich in Zukunft ändern.
Wicket 8.0 requires at least Java 8 Wicket 8.0 requires Servlet 3.1 (Jetty 9.2+, Apache Tomcat 8+, JBoss WildFly 10+)
(Von der Migration zu Wicket 8.0)
Wicket 8.0 erfordert Java 8 als Umgebung. Gleichzeitig wurde das Basisservlet auf 3.1 aktualisiert, sodass auf die entsprechende Version des Servlet-Containers [^ 1] geachtet werden muss.
[^ 1]: Aber web.xml bleibt immer noch ...
LambdaModel
Eine wesentliche Änderung ist die Hinzufügung des Lambda-Modells.
Wie der Name schon sagt, handelt es sich um ein ** Modell, mit dem Sie die Getter / Setter-Verarbeitung für ModelObject mit ** Java 8 Lambda-Ausdrücken und Methodenreferenzen angeben können.
// Wicket 8.Beispiel eines Lambda-Modells von 0
Order order = new Order();
IModel<String> model = LambdaModel.of(order::getUserName, order::setUserName);
Auf diese Weise wird die Methodenreferenz des ersten Arguments als "getModelObject ()" behandelt, und die Methodenreferenz des zweiten Arguments wird als Verarbeitung innerhalb des Prozesses "setModelObject (String)" behandelt.
Dieses Modell scheint die Absicht zu haben, als Alternative zu ** PropertyModel ** verwendet zu werden.
//Bisherige Beispiele für Eigenschaftsmodelle
Order order = new Order();
IModel<String> model = new PropertyModel(order, "userName");
PropertyModel ist praktisch, da es mit Instanzfeldern und Setter / Getter verknüpft werden kann. Andererseits ist es schwierig, es zu erstellen und zu ändern, da die referenzierte Feldvariable als Zeichenfolge angegeben werden muss. Wenn Sie LambdaModel verwenden, können Sie dieses Problem lösen und das Gleiche tun wie [^ 2].
[^ 2]: Ich persönlich benutze CompoundPropertyModel trotzdem ...
Komponenten wie Label arbeiten, indem sie ein Modell (oder ein darin enthaltenes Objekt) übergeben. ** Lambda-Ausdrücke und Methodenreferenzen können auch verwendet werden, wenn das Modell oder Objekt einer Komponente übergeben wird **.
Order order = new Order();
//Bis jetzt (selbst wenn Sie getUserName direkt übergeben, wird es intern in Model eingeschlossen)
add(new Label("foo", Model.of(order.getUserName())));
add(new Label("foo", order.getUserName()));
// Wicket 8.Ab 0 können Sie ein Modell oder Objekt mit einer Methodenreferenz oder einem Lambda-Ausdruck übergeben
add(new Label("foo", order::getUserName));
add(new Label("foo", () -> {...}));
** Das Modell wird jetzt standardmäßig mit einer Werksmethode (von) geliefert **. Sie können Lambda-Ausdrücke und Methodenreferenzen in of verwenden.
IService service = new Service();
//Bisher
IModel<List<Dish>> model = new LoadableDetachableModel<List<Dish>>() {
private static final long serialVersionUID = 1380883852804223557L;
@Override
protected List<Dish> load() {
return service.fetchDishes();
}
};
// Wicket 8.Wie schreibe ich von 0. Ich bin sehr froh, dass das LoadableDetachableModel in einer Zeile steht.
IModel<List<Dish>> model = LoadableDetachableModel.of(service::fetchDishes);
Auf diese Weise können Sie ein LoadableDetachableModel usw. in eine Zeile schreiben, was je nach Verwendung praktisch ist, aber Sie mussten es jedes Mal zu einer anonymen Klasse machen **. Das ist sehr nett. Persönlich war ich der Meinung, dass dies der größte Vorteil unter den Modelländerungen war.
Andererseits ist ** AbstractReadOnlyModel veraltet und es wird jetzt empfohlen, stattdessen die anonyme Klasse von IModel zu verwenden **. Bei der Migration auf Wicket 8.0 scheint es einige Zeit zu dauern, alle auf einmal zu suchen und zu ersetzen.
IService service = new Service();
//Bisher
IModel<Integer> model = new AbstractReadOnlyModel<Integer>() {
private static final long serialVersionUID = 2631631544271526736L;
@Override
public Integer getObject() {
return new Random().nextInt();
}
};
// Wicket 8.Ab 0 ist AbstractReadOnlyModel veraltet. Wechseln Sie in IModel zu einer anonymen Klasse.
IModel<Integer> model = new IModel<Integer>() {
private static final long serialVersionUID = -2636918853427797619L;
@Override
public Integer getObject() {
return new Random().nextInt();
}
};
Bei Links, die zwischen Seiten und Schaltflächenkomponenten verschoben werden, die Werte mit Foam veröffentlichen, wurden häufig anonyme Klassen erstellt, um die Methoden onClick () und onSubmit () zu überschreiben, die Klickereignisse steuern.
** In Wicket8 können Sie mithilfe des Lambda-Ausdrucks Links und Schaltflächen erstellen, ohne sie zu einer anonymen Klasse zu machen **.
//Bisher
Link<Void> link = new Link<Void>("toHogePage") {
private static final long serialVersionUID = 3391006051307639762L;
@Override
public void onClick() {
//Verschiedene Verarbeitung
setResponsePage(new HogePage(model));
}
};
// Wicket 8.Verknüpfungskomponente von 0
add(Link.onClick("toHogePage", (l) -> {
//Verschiedene Verarbeitung
setResponsePage(new toHogePage(model));
}));
//Wenn Sie nur Seiten verschieben, ist dies eine Zeile
add(Link.onClick("toHogePage", (l) -> setResponsePage(new toHogePage(model))));
//Bisher
Button button = new Button("toHogePage") {
private static final long serialVersionUID = 7447947126462635005L;
@Override
public void onSubmit() {
//Hier gibt es verschiedene Verarbeitungsmöglichkeiten
setResponsePage(new HogePage(model));
}
};
// Wicket 8.Tastenkomponente von 0
Button button = Button.onSubmit("toHogePage", (b) -> {
//Hier gibt es verschiedene Verarbeitungsmöglichkeiten
setResponsePage(new HogePage(model));
}));
//Dies ist auch eine Zeile, wenn nur Seitenbewegung
Button button = Button.onSubmit("toHogePage", (b) -> setResponsePage(new CompletionPage(orderModel)));
Die Argumente l
und b
im Lambda-Ausdruck beziehen sich auf die Link- und Button-Instanzen selbst. Es kann in Lambda-Ausdrücken wiederverwendet werden, wenn Sie nach dem Klicken Link oder Button (oder Modell oder Formular, das daraus erhältlich ist) bedienen möchten.
** Gleiches gilt für Ajax-basierte Links und Buttons **. Wenn Sie beispielsweise eine Schaltfläche hatten, mit der eine Komponente mit dem Namen "wmc" beim Senden eines Formulars mit Ajax aktualisiert wird,
//Bisher
AjaxButton button = new AjaxButton("button") {
private static final long serialVersionUID = 796871957135885247L;
@Override
protected void onSubmit(AjaxRequestTarget target) {
target.add(getPage().get("wmc"));
}
@Override
protected void onError(AjaxRequestTarget target) {
target.add(getForm().get("feeedback"));
}
};
// Wicket 8.Von 0, Ajax Link,Button kann auch kurz geschrieben werden.
//Der Lambda-Ausdruck des zweiten Arguments lautet onSubmit,Der Lambda-Ausdruck des dritten Arguments lautet onError.
AjaxButton button = AjaxButton.onSubmit("onSubmit",
(b, t) -> t.add(getPage().get("wmc")),
(b, t) -> t.add(b.getForm().get("feedback")));
Es wird so sein. Das Wicket8-Lambda-Ausdrucksargument b
ist die Schaltfläche selbst, und das Argument t
ist AjaxRequestTarget.
Ich benutze diese Komponenten oft, aber sie haben auch die Massenproduktion anonymer Klassen verursacht, daher würde ich mich sehr freuen, wenn ich sie (in kürzester Zeit) in einer Zeile schreiben könnte.
Behavior
Das Verhalten, das Komponenten mit Ajax usw. Verhalten und Funktionalität hinzufügt, enthält auch einen Teil, der mit Factory-Methoden und Lambda leicht geschrieben werden kann.
Unten finden Sie ein Beispiel für eine Label-Komponente mit Verhalten, die die Komponente selbst jede Sekunde aktualisiert (?).
// Wicket 8.AbstractAjaxTimerBehavior von 0. Die Variable t ist AjaxRequestTarget.
add(new Label("timer", LoadableDetachableModel.of(LocalDateTime::now))
.setOutputMarkupId(true)
.add(AbstractAjaxTimerBehavior.onTimer(ONE_SECOND, (t) -> t.add(getPage().get("timer")))));
In der Vergangenheit mussten bei der Vorbereitung solcher Verhaltensweisen anonyme Klassen und Unterklassen erstellt werden. Wicket 8.0 wurde entwickelt, um diese anonymen Klassen zu vermeiden und das Schreiben mit weniger Code zu vereinfachen.
Anhand der bisher vorgestellten Beispiele habe ich ein Beispiel für ein einfaches Einreichungsformular erstellt (Import entfällt). Wenn Sie Wicket bereits verwendet haben, werden Sie feststellen, dass der Java-Code kürzer ist.
<!DOCTYPE html>
<html xmlns:wicket="http://wicket.apache.org">
<head>
<meta charset="utf-8"/>
</head>
<body>
<h1>Bestellformular</h1>
<form wicket:id="form">
<dl>
<div wicket:id="feedback"></div>
<dt>Name</dt>
<dd><input type="text" wicket:id="userName"></dd>
<dt>Mahlzeit</dt>
<dd>unten<span wicket:id="numberOfDish"></span>Bitte wählen Sie einen aus den Artikeln.</dd>
<dd>
<div wicket:id="dish"></div>
</dd>
</dl>
<div>
<button type="submit" wicket:id="onSubmit">bestellen</button>
</div>
</form>
</body>
</html>
public class OrderPage01 extends WebPage {
private static final long serialVersionUID = -8412714440456444538L;
public OrderPage01() {
IService service = new Service();
IModel<Order> orderModel = CompoundPropertyModel.of(Model.of(new Order()));
IModel<List<Dish>> dishes = LoadableDetachableModel.of(service::fetchDishes);
//Ich verwende die Warteschlange, weil die Hierarchie problematisch ist
queue(new Form<>("form", orderModel));
queue(new FeedbackPanel("feedback"));
queue(new TextField<>("userName").setRequired(true));
queue(new Label("numberOfDish", dishes.getObject()::size));
queue(new RadioChoice<>("dish", dishes).setSuffix("<br/>").setRequired(true));
queue(Button.onSubmit("onSubmit", (b) -> setResponsePage(new CompletionPage(orderModel))));
}
}
<!DOCTYPE html>
<html xmlns:wicket="http://wicket.apache.org">
<head>
<meta charset="utf-8"/>
</head>
<body>
<h1>Bestätigungsbildschirm</h1>
<p><span wicket:id="userName"></span>Ist<span wicket:id="dish"></span>ich bestellte</p>
<div><a wicket:id="toIndexPage">Rückkehr</a></div>
</body>
</html>
public class CompletionPage extends WebPage {
private static final long serialVersionUID = 3057979294465321296L;
public CompletionPage(IModel<Order> orderModel) {
setDefaultModel(CompoundPropertyModel.of(orderModel));
add(new Label("userName"));
add(new Label("dish"));
add(Link.onClick("toIndexPage", (link) -> setResponsePage(IndexPage.class)));
}
}
Leider können nicht alle Modelle, Komponenten und Verhaltensweisen anonyme Klassen umgehen.
** ListView usw. sind ebenfalls typische Komponenten, die als anonyme Klassen verwendet werden. Es wurden jedoch keine besonderen Verbesserungen vorgenommen, und es ist erforderlich, sie wie zuvor als anonyme Klassen zu verwenden **.
Auch wenn es sich um eine Link- oder Button-Komponente handelt, sind die Methoden wie ** onInitialize ()
und onConfigure ()
, die die anonyme Klassenkomponente initialisieren, dieselben wie zuvor **. Wenn Sie also eine Komponente generieren möchten, die als Aktualisierungsziel von Ajax festgelegt ist (dh setOutputMarkupId (boolean) festlegen), oder eine Komponente, die Validierung und Sichtbarkeit festlegen muss, ist dies dieselbe wie zuvor. Muss anonyme Klasse sein [^ 3].
[^ 3]: Es ist möglich, Einstellungsmethoden wie "setOutputMarkupId (boolean)" in Form einer Methodenkette zu verbinden, aber der Rückgabewert dieser Methoden muss auf den Komponententyp festgelegt werden. Ja, Casting wird beim Hinzufügen untergeordneter Komponenten unverzichtbar. Sie können die Warteschlange gut nutzen und die Besetzung fortsetzen.
Ich denke jedoch, dass es bequem zu verwenden ist, selbst wenn Sie einfach Links, Schaltflächen und Modelle schreiben können, die sich wahrscheinlich auf einer Seite befinden, für die keine so detaillierte Steuerung erforderlich ist.
Um die bisher eingeführten Inhalte zu erreichen, verfügt Wicket 8.0 über eine eigene Funktionsschnittstelle. Sie sind "WicketBiConsumer", "WicketBiFunction", "WicketConsumer", "WicketFunction", "WicketSupplier". Diese werden jedoch nur von der Java-Standardfunktionsschnittstelle geerbt und serialisierbar gemacht.
Darüber hinaus ist IModel auch eine funktionale Schnittstelle, und Standardmethoden wie die Verarbeitung zum Zeitpunkt des Trennens und Standardmethoden für die Zwischenverarbeitung zum Generieren eines Modells aus einem Modell wie Filter und Karte werden vorbereitet.
Es scheint, dass diese verwendet werden können, wenn Sie Modelle und Komponenten selbst erstellen oder verbessern.
Es gibt viele andere geringfügige Änderungen in Bezug auf Wicket 7.x → 8.0, aber in diesem Artikel wird der interessanteste Teil der täglichen Programmierung, der vereinfachte Teil der Beschreibung von Modellen und Komponenten und Ich habe die Aktualisierung des Teils zusammengefasst, die von anonymen Klassen mit Lambda vermieden werden kann.
Wir hoffen, dass dies für die Migration von Produkten nützlich sein wird, die bereits mit Wicket entwickelt wurden, und für diejenigen, die in Zukunft auf irgendeine Weise mit Wicket 8.0 oder höher entwickelt werden.
Ein Codebeispiel finden Sie unter github.
Recommended Posts