带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)之间,这要归因于renderrender等所有方面。 另一方面,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表达式,分别为StringSupplierFormAction 。 这是代码:

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/360867.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

装饰者模式如何拯救了我的一天

在工作中&#xff0c;我正在处理庞大的Java代码库&#xff0c;该代码库是由许多不同的开发人员在15年的时间里开发的。 并不是所有的事情都由书来完成&#xff0c;但是同时我通常没有机会重构遇到的每一个奇怪之处。 尽管如此&#xff0c;仍可以每天采取提高代码质量的措施。 …

快速的骆驼和云消息传递

Apache Camel是一个流行的&#xff0c;成熟的开源集成库。 它实现了企业集成模式 &#xff0c;这是在集成分布式系统时经常出现的一组模式。 过去&#xff0c;我写过很多关于Camel的文章&#xff0c; 包括为什么我比Spring Integration更喜欢它 &#xff0c; 路由引擎 如何 工作…

三角形类1

/* 程序的版权和版本声明部分 Copyright (c)2012, 烟台大学计算机学院学生 All rightsreserved. 文件名称&#xff1a; object.cpp 作者&#xff1a;刘清远 完成日期&#xff1a; 2013年3月29日 版本号&#xff1a; v1.0 输入描述&#xff1a;无 问题描述&#xff1a;设计求三…

android 自定义xml属性

Android 自定义组件 Android 提供了非常精致的和非常强大的组件化模型&#xff0c;能够更加方便的构建UI,这些UI组件都是基于基本的layout类:View 和 ViewGroup。 部分能够用的widgets包括&#xff1a;Button&#xff0c;TextView,EditText,ListView,CheckBox&#xff0c;Radio…

LeetCode: Longest Common Prefix

string.erase没掌握好&#xff0c;悲了个剧&#xff0c;2次过 1 class Solution {2 public:3 string longestCommonPrefix(vector<string> &strs) {4 // Start typing your C/C solution below5 // DO NOT write int main() function6 s…

流式传输大数据:Storm,Spark和Samza

有许多分布式计算系统可以实时或近实时处理大数据。 本文将从对三个Apache框架的简短描述开始&#xff0c;并试图对它们之间的某些相似之处和不同之处提供一个快速的高级概述。 阿帕奇风暴 在风暴 &#xff0c;你设计要求的T opology实时计算的图&#xff0c;然后喂到集群&…

uniapp使用阿里云多色图标

下载&#xff0c;然后解压 输入cmd&#xff0c;然后enter 输入 npm install -g iconfont-tools 再输入 iconfont-tools&#xff0c;然后一直enter&#xff0c;直到结束 目录会多了个iconfont-weapp文件&#xff0c;点击去找到 iconfont-weapp-icon.css 导入和使用 t-icon开头 接…

针对Java中的XSD验证XML

有许多工具可用于根据XSD 验证XML文档 。 其中包括操作系统脚本和工具&#xff0c;例如xmllint &#xff0c;XML编辑器和IDE&#xff0c;甚至是在线验证器。 由于前面提到的方法的局限性或问题&#xff0c;我发现拥有自己的易于使用的XML验证工具很有用。 Java使编写这样的工具…

uniapp uni.request GET方式请求,不能直接传数组解决方法

这里写目录标题目录遇到的问题 GET请求方法传数组解决方案目录 遇到的问题 GET请求方法传数组 想传一个数组&#xff0c;但是后台接受到的数据与浏览器中显示的数据和前台代码传的不一样&#xff1b; 前台代码打印 浏览器显示数据 其中HerbalNameList &#xff0c;变成了字…

休眠CascadeType.LOCK陷阱

介绍 引入了Hibernate 显式锁定支持以及Cascade Types之后 &#xff0c;就该分析CascadeType.LOCK行为了。 休眠锁定请求触发内部LockEvent 。 关联的DefaultLockEventListener可以将锁定请求级联到锁定实体子级。 由于CascadeType.ALL也包括CascadeType.LOCK &#xff0c;因…

c++中在堆和栈中申请空间的差别

堆中和栈中申请的空间的比较, 我找到了下面的比较: 栈的情况&#xff1a;栈上分配空间的好处是快&#xff0c;而且对象生存期是自动的&#xff0c;离开当前域之后就自动析构回收。坏处就是栈空间有限&#xff0c;而且不能人为控制对象的生存期&#xff0c;比如你无法将一个函数…

推销自己的海盗猫王运营商

因此&#xff0c;Java没有Elvis运算符&#xff08;或者更正式的名称是null合并运算符或null安全成员选择&#xff09;……虽然我个人不太在意它&#xff0c;但有些人似乎很喜欢它。 当一位同事需要几天后&#xff0c;我坐下来探讨了我们的选择。 而且你知道什么&#xff01; 您…

使用CDI简化JAX-RS缓存

这篇文章&#xff08;通过一个简单的示例&#xff09;说明了如何使用CDI Producers使其在RESTful服务中利用缓存控制语义更加容易 与HTTP 1.0中可用的Expires标头相比&#xff0c; HTTP 1.1中添加了Cache-Control标头&#xff0c;这是急需的改进。 RESTful Web服务可以利用此标…

transform限制position:fixed的跟随效果

我们应该都知道&#xff0c;position:fixed可以让元素不跟随浏览器的滚动条滚动&#xff0c;而且这种跟随效果连它的兄弟们position:relative/absolute都限制不了。但是&#xff0c;真是一物降一物&#xff0c;position:fixed固定效果却被小小的transform给干掉了&#xff0c;直…

Java 8 Lambda表达式教程

问候&#xff01; :) 离开几个月后&#xff0c;我决定恢复风格:)。 我注意到我以前有关新的Date / Time API的一篇文章非常受欢迎&#xff0c;因此这次我将把本篇文章专门介绍Java 8的另一个新功能&#xff1a; Lambda Expressions 。 功能编程 Lambda表达式是Java编程语言最…

[HDU] 2553 N皇后问题-简单深搜

题目链接&#xff1a; http://acm.hdu.edu.cn/showproblem.php?pid2553 方法&#xff1a; 1.可以用对称的思想&#xff0c;即&#xff1a;如果N是偶数&#xff0c;则只计算第一个皇后分别放在第一行的位置1到N/2这N/2个情况的结果和&#xff0c;最后再乘以2。如果是奇数&#…

您真的了解@WebService吗?

SOAP Web服务无论如何都不是最先进的技术-尽管它仍然存在&#xff0c;但是基于REST的Web服务却提供了激烈的竞争。 无论如何–这绝对不是REST vs SOAP帖子&#xff01; 我观察到了一些实例&#xff0c;至少可以说&#xff0c;使用基于Java的SOAP Web服务的方式不太理想。 我认…

Error: Module “xxx“ does not exist in container. / antd pro v5启用qiankun报错 / 同时使用mfsu和qiankun报错

一、问题描述 我们用antd pro v5搭建前端项目&#xff0c;启用qiankun微前端模式&#xff0c;终端报错如下&#xff1a; Uncaught (in promise) Error: Module “xxx” does not exist in container. while loading “xxx” from webpack/container/reference/mf 经过排查&…

双链表

问题&#xff1a;在分配空间时&#xff0c;遇到问题 定义一个结构体&#xff1a; typedef struct dLinkListNode{ int data; struct dLinkListNode *prior; struct dLinkListNode *next;}*dLinkList,dListNode; dList(dLinkList)malloc(sizeof(dListNode));与dList(dLinkList)m…

JVMTI标记如何影响GC暂停

这篇文章分析了为什么Plumbr Agents在某些情况下以及如何延长GC暂停的时间。 对基本问题进行故障诊断揭示了有关在GC暂停期间如何处理JVMTI标记的有趣见解。 发现问题 我们的一位客户抱怨说&#xff0c;附加了Plumbr代理后&#xff0c;应用程序的响应速度明显降低。 通过分析G…