这是怎么回事? :)

我一直在从事一些项目,这些项目值得庆幸的是将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

带Lambda表达式的Apache Wicket相关推荐

  1. lambda表达式_带Lambda表达式的Apache Wicket

    lambda表达式 这是怎么回事? :) 我一直在从事一些项目,这些项目值得庆幸的是将Apache Wicket用于表示层. 我自然而然地想到了Java的8个lambda表达式如何与Wicket完美契 ...

  2. 设计模式的Java 8 Lambda表达式–命令设计模式

    在本博客中,我将说明如何使用Java 8 Lambda表达式以函数式编程方式实现命令模式 . 命令模式的目的是将请求封装为对象,从而为具有不同请求,队列或日志请求的客户端参数化,并支持相应的操作. 命 ...

  3. python中lambda 表达式(无参数、一个参数、默认参数、可变参数(*args、**kwargs)、带判断的lambda、列表使用lambda)

    如果⼀个函数有⼀个返回值,并且只有⼀句代码,可以使⽤ lambda简化. lambda语法: lambda 参数列表 : 表达式 注意: lambda表达式的参数可有可⽆,函数的参数在lambda表达 ...

  4. java lambda表达式_凯哥带你从零学大数据系列之Java篇---第二十二章:Lambda表达式...

    温馨提示:如果想学扎实,一定要从头开始看凯哥的一系列文章(凯哥带你从零学大数据系列),千万不要从中间的某个部分开始看,知识前后是有很大关联,否则学习效果会打折扣. 系列文章第一篇是拥抱大数据:凯哥带你 ...

  5. lambda表达式java项目常用_一文带你彻底搞懂Lambda表达式

    1. 为什么使用Lambda表达式 Lambda是一个匿名函数,我们可以把Lambda表达式理解为是一段可以传递的代码(将代码像数据一样进行传递).可以写出更简洁.更灵活的代码.作为一种更紧凑的代码风 ...

  6. java枚举变量带括号_Java~如何使用Enum(枚举)和Lambda表达式

    文章目录 Enum的使用 switch中使用 常见方法 values() 以数组形式返回枚举类型的所有成员 ordinal() 获取枚举成员的索引位置 valueOf() 将普通字符串转换为枚举实例 ...

  7. 小司机带你用Java新特性之Lambda表达式

    最为一名吊丝程序员,那么方法引用以及Lambda表达式这个技能是必须的. 翻了一下网上关于Lambda表达式的示例写的真的是乱七八糟,可阅读性不强 最后小编自己撸了一个最典型的示例,来看一下: pac ...

  8. 【Java10】lambda表达式(函数式编程),Stream流,File类,字节/字符流,乱码,缓冲/转换/序列化/打印流,Properties

    文章目录 1.lambda表达式标准语法:()->{} 2.lambda表达式简略语法:可推导即可省略 3.lambda表达式原理:lambda效率比匿名内部类高 4.两个函数式接口:Consu ...

  9. 四万字 Lambda 表达式完整教程(强烈建议收藏)

    点击关注公众号,利用碎片时间学习 Java Lambda表达式的一个重要用法是简化某些匿名内部类(Anonymous Classes)的写法.实际上Lambda表达式并不仅仅是匿名内部类的语法糖,JV ...

最新文章

  1. 树莓派安装octave,报错missing `server' JVM at问题解决
  2. 禁用任何未使用的端口com_分享连接思科路由器控制台端口的正确设置
  3. 逆向知识十三讲,汇编中数组的表现形式,以及还原数组
  4. swiper动态加载数据左右切换失效
  5. Python字典values()方法与示例
  6. [论文阅读] End-to-End Incremental Learning
  7. linux php添加mysql扩展模块_linux下为php添加扩展库的方法
  8. 社会达尔文主义 盛行时间_新达尔文主义的心理理论
  9. IDEA配置LeetCode刷题环境
  10. 白话大数据之HDFS
  11. Kitkat中对class core, class main, class late_start的简单分析
  12. 资深工程师,专家,研究员等进阶
  13. 2022年汽车驾驶员(中级)理论题库模拟考试平台操作
  14. Bsnet:Bi-Similarity Network for Few-shot Fine-grained Image Classification论文复现
  15. Serv-U 安装配置以及外网访问使用
  16. SpringMVC(三)——响应
  17. 絮絮叨叨,码农中的唐僧
  18. 如果说数据是数字经济的新石油,那么人工智能(AI)就是蒸汽机
  19. 【云原生】阿里云Kubernetes(ACK)简介
  20. 段码液晶屏问题六大分类

热门文章

  1. 考研408大纲22年考研
  2. 集成Swagger(API)---SpringBoot
  3. Hibernate框架(1)
  4. jquery sleep函数
  5. 项目的包结构 mybatis三剑客
  6. java jpa saveall方法优化_JPA批量插入(saveAll)
  7. mysql 删除过期日志_【转】对mysql日志进行操作的总结包括 启用,过期自动删除 等...
  8. ogm neo4j_Neo4J OGM与Quarkus
  9. oracle密码不能重复用_重复码
  10. java创建和销毁一个对象_有效的Java –创建和销毁对象