带Lambda表达式的Apache Wicket
這是怎么回事? :)
我一直在從事一些項目,這些項目值得慶幸的是將Apache Wicket用于表示層。 我自然想到Java的8個lambda表達式如何與Wicket完美匹配。 而不僅僅是我, Wicket團隊似乎已經在努力更改API,以為開箱即用的lambda提供支持。
如果您已經知道Java中的lambda如何工作,那么本文將更加有趣。 如果您不這樣做,那么這是一個很好的起點 。 還建議您了解一些有關Apache Wicket的知識,但是,如果您曾經使用過任何面向GUI的API(例如Swing或GWT),那么足以理解它。
在開始之前,我只想發表一個聲明,說明為什么我比JSF更喜歡Wichet。 如果您不在乎,請跳過此部分:)
我對JSF的狂熱
綜上所述,如果您正在考慮為項目使用基于服務器端基于組件的框架,那么我認為沒有理由選擇Wicket上的JSF。 這是我的一些論點:
1. Wicket代碼更易于閱讀和維護
JSF強迫您將表示邏輯分散在xHTML文件和Java類(托管Bean)之間,這要歸因于render , render等所有方面。 另一方面,Wicket使我們能夠編寫Java代碼。 所有邏輯都包含在controller類中,以我的拙見,它更易于閱讀和維護。
有人可能會爭辯說,與所有其他面向GUI的API一樣,由于最終編寫了所有匿名內部類 ,Wicket的代碼更加冗長。 對我來說,這僅是部分正確。 該代碼確實比JSF的Managed Bean更為冗長,但是更易于閱讀。 它只是一個地方的Java代碼。 在Facelets頁內,沒有Java與EL混合在一起。
對于所有匿名內部類 ,通過使用lambda表達式 ,它們可以并且比以往任何時候都可以被阻止。 這就是我在本文中向您展示的內容。
2.使用Wicket可以更清楚地劃分角色
Wicket的構建前提是我們可以使用純HTML來構建頁面。 有一些標記需要使用,但最終結果仍然是95%純HTML 。 這樣就可以使對Java或Wicket一無所知的Web設計人員與開發人員并肩工作。 設計人員會做自己最擅長的事情,而開發人員幾乎完全使用他們創建的內容,而只擔心常規的Java代碼。
JSF是完全不同的野獸。 您幾乎有兩種選擇:1)迫使您的設計師學習他們討厭的JSF。 2)如果他們制作純HTML原型,則有人將不得不在JSF中“重新編碼”它們。
我知道有很多替代方法可以解決此問題,他們甚至在JSF 2.2中引入了“友好標記”功能 。 不過,我所知道的方法都沒有Wicket這么簡單。
3.在Wicket中,擴展/創建組件要容易得多
在JSF中從頭開始創建組件是一場噩夢。 即使在談論小面組成時,它也沒有Wicket一樣簡單。
總而言之,這只是我的看法。 當然,JSF受到關注是因為它是Java EE規范的一部分,并且該鎮的每個新開發人員都希望學習JSF,而不是Wicket。 雖然當然可以使用JSF構建出色的Web應用程序,但Wicket卻可以承受一半的麻煩。
還需要注意的是,我對JSF團隊沒有任何反對。 相反,情況恰恰相反:JSF專家組中充滿了才華橫溢的人。 不可否認。 我只想知道如果設置為使用完全不同的解決方案,他們可以實現什么。
最后,Wicket和Lambdas
一旦被匿名內部類填充,Lambdas將填補這一空白。 通常,與任何GUI API一樣,處理GUI事件將誘使您編寫匿名類。 這是Swing的一個簡單示例:
JButton button = new JButton("Save"); button.addActionListener(new ActionListener() { //anonymous class@Overridepublic void actionPerformed(ActionEvent e) {System.out.println("Button clicked");//Our button was clicked. Here we perform//everything needed to make the action//of clicking a button work.} });就是這樣 我們最終傳遞了一個狀態,一個對象,應該傳遞一種行為,一種方法的位置。 該代碼比應該的更加冗長。
使用Wicket時,問題幾乎相同:
AjaxFallbackLink<Void> link = new AjaxFallbackLink<Void>("linkId") {@Overridepublic void onClick(AjaxRequestTarget target) {System.out.println("Link clicked!");} };為了減輕處理GUI事件的痛苦,使用lambda表達式和幾個幫助器類,我們可以在同一行代碼中像上面這樣編寫相同的代碼:
AjaxFallbackLink<Void> link = ComponentFactory.newAjaxLink("linkId", (target) -> System.out.println("Link clicked!"));當然,大多數事件處理將需要的不僅僅是一個簡單的“ System.out”。 因此,出于這個原因,最好將這些詳細信息隱藏在同一類的私有方法中。 這是一個看起來更完整的代碼示例:
public class MyPage extends WebPage {public MyPage(final PageParameters parameters) {super(parameters);AjaxFallbackLink<Void> link = ComponentFactory.newAjaxLink("linkId", (target) -> linkClick(target));}//this method is called in line 6private void linkClick(AjaxRequestTarget target) {//do a bunch of stuff here} }釘下來
和往常一樣,我在GitHub上用完整的代碼建立了一個小項目。 你可以在這里得到它。 代碼雖然不多,但是我認為足夠了,因此您可以創建一個自己的啟用了lambda的API。
該項目由一個小的用例組成,該用例用于將用戶插入到make make believe數據庫中(該數據庫實際上是一個ArrayList,如您在代碼中看到的那樣)。 看起來像這樣。 丑陋,但功能強大:
那里沒有神秘。 新插入的用戶顯示在下面的紅色表格中,每個用戶都有一個“編輯”鏈接。 現在讓我們看一下代碼。
首先,我們需要一些“功能接口” 。 首先,您可能會想使用JDK已經提供的功能接口 。 它們很多,而且確實確實可以滿足您的需求。 問題是,作為序列化的怪胎,Wicket會抱怨它們都不是可序列化的 。 因此,我決定提出自己的建議:
提示: 如果您不知道Java的lambda是如何工作的,那么這一切都沒有道理。 首先閱讀本文 。
@FunctionalInterface public interface AjaxAction extends Serializable { public abstract void onClick(AjaxRequestTarget target); }@FunctionalInterface public interface FormAction extends Serializable { public abstract void onSubmit(); }@FunctionalInterface public interface StringSupplier extends Serializable {public String get(); }很快我們將采取行動。 就像我之前說過的那樣,請注意,它們都擴展了Serializable 。
動態標簽
該頁面的一個相當煩人的方面是某些標簽必須根據我們正在執行的實際操作進行更改。 也就是說,如果我們正在編輯現有用戶,則在頂部顯示“ 插入用戶”是沒有意義的。 “ 編輯用戶”標簽更合適。 下面的“ 保存 ”按鈕也可以更改為“ 更新 ”。 請記住這一點,因為這就是我創建StringSupplier功能接口的原因。
我使用的方法是使用單個HTML元素并根據需要更改其值,而不必在必要時隱藏和顯示兩個不同的元素。 為了提供一些觀點,這是通常的做法:
<div style="text-align: center;"><h2 wicket:id="titleLabel">Insert User/Update User</h2> </div>titleLabel = new Label("titleLabel", new Model<String>() {@Overridepublic String getObject() {if (form.getModelObject().getId() == null) {return "Insert User";} else {return "Edit User";}} });我們將提供一個帶有“匿名類”的標簽作為模型。 然后, getObject()方法將根據“用戶”(我們的實體)模型對象的當前狀態來確定它是插入還是更新。 真麻煩
使用lambda,我的建議是這樣的(HTML頁面保持不變):
titleLabel = ComponentFactory.newLabel("titleLabel", () -> form.getModelObject().getId() == null ? "Insert User" : "Edit User"); add(titleLabel);如您在第一行中看到的,我們有一個lambda,其表達式為三元運算符。 通常可以使用if / else語句來完成if,但是看起來很丑。 我已經向您展示了StringSupplier功能界面,現在該看一下我們的幫助器ComponentFactory類了。
顧名思義,它只是一個帶有一些靜態工廠方法的常規類來創建組件。 這是我們的newLabel()工廠方法的樣子:
//Remember, StringSupplier is a functional interface that returns a String.public static Label newLabel(String wicketId, StringSupplier supplier) {Label label = new Label(wicketId, new Model<String>() {@Overridepublic String getObject() {return supplier.get();}});label.setOutputMarkupId(true);return label; }紐扣
現在到“保存/更新”按鈕。 除了其標簽也應根據表單的模型狀態而改變的事實之外,我們還將使用lambda表達式來分配一個處理“單擊事件”的方法。 通常,沒有lambda,這就是我們要做的:
//this would go inside the class constructor Button saveUpdateButton = new Button("saveUpdateButton") {@Overridepublic void onSubmit() {//saveUpdate(User) is a private method//in this very same classsaveUpdate(form.getModelObject());} }; saveUpdateButton.add(new AttributeModifier("value", new Model<String>() {@Overridepublic String getObject() { return form.getModelObject().getId() == null ? "Save" : "Update";} })); form.add(saveUpdateButton);//this is a private method inside the same class private void saveUpdate(User user) {//Logic to insert or update an User. }我們創建了一個覆蓋其onSubmit()方法的Button,然后附加了AttributeModifier行為來處理標簽切換。 看起來我們有15行代碼。 現在是lambda對應項:
Button saveUpdateButton = ComponentFactory.newButton("saveUpdateButton",() -> form.getModelObject().getId() == null ? "Save" : "Update",() -> saveUpdate(form.getModelObject())); form.add(saveUpdateButton);而已。 請注意,它很容易只有2行,但是由于第一條語句太長,因此我決定將其分成 3行。newButton()方法采用3個參數:wicket id和兩個lambda表達式,分別為StringSupplier和FormAction 。 這是代碼:
public static Button newButton(String wicketId, StringSupplier labelSupplier, FormAction action) {Button button = new Button(wicketId) {@Overridepublic void onSubmit() {action.onSubmit();}};AttributeModifier attrModifier = new AttributeModifier("value", new Model<String>() {@Overridepublic String getObject() { return labelSupplier.get();}});button.add(attrModifier);return button; }好吧,就是這樣。 希望你喜歡它。 如果需要,請在下面留下問題。
- 您可以在此處獲取源代碼。
同樣,您可以在此處找到有關lambda表達式的很好的介紹。
翻譯自: https://www.javacodegeeks.com/2015/03/apache-wicket-with-lambda-expressions.html
總結
以上是生活随笔為你收集整理的带Lambda表达式的Apache Wicket的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java旧版不断发展
- 下一篇: 云监控电脑版(云监控电脑版下载安装)