apache wicket_教程– Apache Wicket:有趣的Web框架

apache wicket_教程– Apache Wicket:有趣的Web框架选择Java技术堆栈时,不乏多样性。为了摆脱“滚动自己的(一切)”的想法,以至于很多公司都沦为猎物,而“一切都必须成为标准”的哲学,则对每一层都采取了各种各样的方法过去几年中,Java体系结构如雨后春笋般涌现。UI层对于竞争技术的奋斗并不陌生。有了提供的所有选项,您将如何选择?尽管没有作家可以为您做出选择,但是我们可以做的是向您介绍您可能要考虑的另一种选择,希望它会引起您足够的兴趣并尝…

大家好,欢迎来到IT知识分享网。

apache wicket

选择Java技术堆栈时,不乏多样性。 为了摆脱“滚动自己的[一切]”的想法,以至于许多公司都沦为猎物,而“一切必须成为标准”的哲学,则对每一层都采取了各种各样的方法过去几年中,Java体系结构如雨后春笋般涌现。 UI层对于竞争技术的奋斗并不陌生。 有了提供的所有选项,您将如何选择? 尽管没有作家能为您做出选择,但我们可以做的是向您介绍您可能要考虑的另一种选择,希望它会引起您足够的兴趣并尝试一下。 在本文中,我将向您介绍Apache Wicket。

您可能会对文章的标题感到怀疑,对于我编写的大多数应用程序,Wicket是我偏爱的UI框架。 您是否最终对这个伟大的框架抱有相同的热情–还是它适合您想要编写的应用程序类型–取决于您和您的情况。 但是,继续阅读,您可能会发现另一种很棒的技术可以添加到您的“ go-to”堆栈中。

Wicket是一个面向组件的Java Web框架,致力于简化编写可重用代码的过程。 它不需要XML配置(除了标准的web.xml部署描述符中的几行内容),因此可以刷新使用。 它鼓励逻辑与标记之间的清晰区分,从而满足大多数程序员对顺序感的需求。 使用Wicket,您的代码是“仅Java”,而标记是“仅HTML”。 这使“ HTML专家”更容易地协助该项目,而不必担心弄乱某些东西,而不必学习复杂的模板语言,参数名称和值等。

Wicket吸引了一个热爱面向对象编程的人。 页面上的每个组件都是一个 真实的 Java对象。 它可以像任何Java对象一样保持状态并执行有用的功能。 这样做的好处是,此状态通过Web请求保持不变,以向您抽象无状态超文本传输​​协议的复杂性。 想象一下,您的页面在侧面导航栏中具有手风琴样式的面板,并且在主内容区域中具有复杂的数据表。 用户进入此页面并展开手风琴的一部分。 在您的代码中,您可以调用 setExpandedSection(index) ,也可以 在其上设置 setExpanded(true) ,在其他 示例 上设置false。 无论是对组件进行建模,还是可以将用户选择作为常规Java成员变量存储在手风琴组件或其子组件中。 现在,当用户单击一个链接来还原您的复杂数据表时,该表本身不需要了解手风琴组件或页面上任何其他组件的状态。 但是,手风琴组件以及所有其他组件会在用户提出的各种其他请求中自动保留其状态。

为了达到上述级别的UI复杂性,许多方法要求页面上的每个组件都具有页面上其他组件的一定程度的知识。 在这些其他技术中,当我单击一个组件中的链接时,它需要将其他组件的状态嵌入到其请求中。 也许它在URL中,或者它存储在会话中。 也许每个组件都有一个cookie前缀,并将其状态存储在cookie中。 或者,也许您的程序员会花大量时间在一个复杂的XML文件中配置组件之间的交互,该XML文件将各种组件的输入和输出联系在一起。 无论如何,这都不是简单的编程-有些甚至根本都不是编程-它需要不断地意识到您正在基于无状态协议编写有状态应用程序这一事实。

Wicket通过为我们的Web应用程序的HTTP交互引入一种状态引擎来解决此问题。 当用户首次访问页面时,将实例化Java类的实例。 构造该类时,就像实例化任何其他Java类一样,即 构造新的MyComponent(“ SomeID”)时 ,可以构造其组件

当这些组件的状态更改时,它们会将状态存储为具有实际类型的真实变量。 但是,在初始页面呈现之后,Wicket不会丢弃实例化的页面对象。 整个组件层次结构存储在用户会话中(以及本文中未介绍的有效方式以及磁盘)中。 因此,当他们单击链接以在页面上执行某些操作,提交表单等时,所有状态仍包含在这些类中。 这就是使它变得如此简单(和有趣!)的原因。

现在,大多数人认为的第一件事是“不使用 大量 内存吗?” 答案是 否定的 许多人迷失了这种方法是浪费内存的陷阱,但是随后发现这等于过早的优化。 这并不是说您在使用Wicket时不能踢自己–您当然可以做会使会话大小爆炸的事情。 我们将在下面的“什么是模型”一节中讨论更多有关此的内容。 如果您真的担心能够验证我的主张,即Wicket不会比其他框架使用更多的内存,那么您可能需要查看这篇文章 和另一篇文章,以更详细地比较Wicket与其他几种框架 (均由彼得·托马斯(Peter Thomas)。 如果您现在只能信任我,请继续。


事不宜迟,您如何直接跳进去尝试Wicket? 如果您安装了Maven,这将再简单不过了。 只需跳转到 http://wicket.apache.org/start/quickstart.html ,填写所需的软件包组和工件ID并运行提供的命令。 将会为您生成一个有效的快速入门应用程序。 运行 mvn eclipse:eclipse (或您的IDE的等效文件)将设置项目依赖项。 如果使用的是Eclipse,请转到文件 菜单 ,选择 导入 ,然后 导入现有项目 并选择生成快速入门的目录。 找到 Start.java 文件,将其打开并运行。 导航到 http:// localhost:8080 ,您将看到“ hello world”应用程序正在运行。 通过在IDE的调试模式(Eclipse: Debug as | Java application )而不是正常运行模式下 运行Start类 ,您将能够设置断点并调试应用程序以查看其工作方式。 有关具有Spring,Guice,JPA等功能的更复杂的快速启动应用程序,请参见jWeekend的优秀LegUp资源

原型已经为您完成了“ hello world”部分。 因此,让我们创建一个简单的链接示例,该链接可以增加页面上的计数器。 要开始使用(假设您具有上面运行的简单快速入门),请找到 HomePage.java HomePage.html 文件,然后在编辑器中将其打开。 请注意,除非另有说明,否则本文中的所有示例都将基于最新的稳定版本1.4.18(在撰写本文时)

首先让我们看一下HTML。 您可能注意到的第一件事是它只是常规HTML。 这是设计使然。 标记不应包含逻辑-这是Wicket的理念。 要将标记与控制它的相应Java代码绑定在一起,您只需向其添加 wicket:id 属性。 在这个标记中,我们有两件事是动态的。 最明显的是链接。 第二个是跨度,可在每个页面呈现时呈现计数器的值。 我们之所以使用span标签,仅仅是因为我们需要一个标记占位符来插入值,并且span标签不会破坏其他标记的结构。

HomePage.html

<html xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd" >    <head>          <title>Wicket Quickstart Archetype Homepage</title>    </head>    <body>        <strong>Wicket Quickstart Archetype Homepage</strong>        <br/><br/>        Click <a href="#" wicket:id="increment">this link</a> to increment         the following counter:<br />        Counter: <span wicket:id="counter">123</span>    </body></html>

现在,让我们看一下相关的Java代码。 您应该注意的第一件事是文件的名称和位置。 默认情况下,对于任何Wicket组件(我们在此处使用的页面也是组件,因此适用相同的规则),Wicket会在类路径的相同包目录中查找名称相同,扩展名为的文件。 html(如果要呈现XML,则仍然适用,但 扩展名为 .xml )。 可以重新配置此行为,但是对于本文,我们不再赘述。 有在线资源可以在需要时为您提供帮助。

在检查实际代码时,您将看到几个部分。 您首先看到的是 counterModel 您会注意到它实现了 IModel 模型在Wicket中非常重要。 当程序员第一次采用Wicket时,它们通常也是人们最不了解的概念之一。 我们将在以后再讨论。 就目前而言,足以说它们是用于检索或设置数据的包装器,而 顾名思义, 这个 AbstractReadOnlyModel 仅仅是用于检索数据的包装器。 我们实现 getObject 方法以在每次调用时检索counter的当前值。 然后将此模型传递给 Component 在这种情况下,组件是标签。 标签只是获取标记中与标签相关联的任何标签,并将标签的主体替换为从给定模型中获取的值。 在这种情况下,我们的span标签将用计数器的值替换“ 123”(标记中的静态主体),该值在第一页呈现为零。

接下来看到的是链接。 它让您仅了解Wicket的功能。 我们在这里使用匿名内部类来实现链接。 如果您的应用程序中有多个位置需要增加一个整数,则可以通过将匿名内部类提取到一个真正的顶级类中,而用一个具体的类替换它。

现在,看看在链接上实施各种操作有多么简单。 您只需覆盖 onClick 方法,然后将业务逻辑放入其中。 显然,增加计数器是一个简单的示例,但是您也可以轻松调用服务层方法,该方法删除或编辑您域中的某些内容,发送电子邮件或进行Web服务调用。 Wicket为您完成了艰巨的任务。 您可以实现逻辑,而不必担心如何获取将指示运行少量逻辑的URL。 您不必担心计数器的当前状态存储在哪里。 您所要做的就是编写代码,以执行应用程序设计的工作。 这就是为什么我喜欢Wicket!

HomePage.java

public class HomePage extends WebPage {    private static final long serialVersionUID = 1L;    private int counter = 0;        public HomePage() {        IModel<Integer> counterModel = new AbstractReadOnlyModel<Integer>() {            private static final long serialVersionUID = 1L;            @Override            public Integer getObject() {                return counter;            }        };        Label label = new Label("counter", counterModel);        add(label);                Link<Void> link = new Link<Void>("increment") {            private static final long serialVersionUID = 1L;            @Override            public void onClick() {                counter++;            }        };        add(link);    }}

那AJAX呢?

好的,建立链接很容易。 那又怎样呢? 现在,查看使该链接成为完全支持非AJAX请求的AJAX链接有多么容易。 首先,我们将标签实例定为最终实例,以便我们可以在匿名内部类中对其进行访问,并调用 setOutputMarkupId(true), 以便在span标签中呈现其唯一ID,并可以在客户端的DOM中找到它。 。 我们将 Link 更改 AjaxFallbackLink, 并更改 onClick 方法签名以匹配超类。 可以将传入 AjaxRequestTarget 视为以XML形式发送回客户端进行处理的事物队列。 通过将标签添加到该队列中,它将被重新呈现,以XML格式通过流传输,并在客户端的DOM中被替换。 重新渲染时,它将使用其模型(还记得 counterModel ?)来获取要渲染的最新值。 所有这些都无需我们编写一行代码即可进行任何转换或DOM操作!

我们为什么要检查 AjaxRequestTarget 是否为null? 因为此链接将在没有启用JavaScript的浏览器上自动为您工作。 在这种情况下,页面将像使用常规链接一样简单地重新呈现。 是的,您听到了我的声音-它无需任何其他工作即可正常降级! 太好了,难以置信,对吧? 您会发现,默认情况下,Wicket在大多数情况下都会以这种方式工作。 可以使用常规HTTP或AJAX进行表单提交甚至文件上传,而几乎不需要额外的工作。 在1.5版本中,添加了一个非常方便的事件机制,使向 AjaxRequestTarget 添加组件的工作 变得更加容易。

HomePage.java(注意:仅显示构造函数)

public HomePage() { IModel<Integer> counterModel = new AbstractReadOnlyModel<Integer>() { … } // above code folded for brevity final Label label = new Label("counter", counterModel); add(label.setOutputMarkupId(true)); AjaxFallbackLink<Void> link = new AjaxFallbackLink<Void>("increment") { private static final long serialVersionUID = 1L; @Override public void onClick(AjaxRequestTarget target) { counter++; if (target != null) target.addComponent(label); } }; add(link); }

在许多Web应用程序中,构建应用程序要完成的许多工作都变成接受用户输入的形式。 在Wicket中,表单与其他所有组件一样都是常规对象。 为了查看示例,让我们看一个简单的表单,该表单接受用户的姓名,电子邮件和出生日期

查看HTML,您不会发现有什么特别之处。 您的设计师可以给您一个HTML表单,您可以将wicket:id属性添加到输入字段和表单本身。 带有wicket:id“ feedback”的div是内置Wicket组件的占位符,它向用户显示该表单生成的所有反馈消息。 在上图中,用户刚刚提交了带有错误数据的表单,这导致验证消息出现在我们的反馈面板组件中。 可以轻松地自定义这些字段,以便在每个表单字段附近都有一个反馈面板,该面板仅显示该特定字段的消息-这是许多应用程序中的常见要求。

单一表格的例子

<html xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd" > <head> <title>Quickstart Homepage</title> </head> <body> Add / Edit Person: <div wicket:id="feedback"></div> <form wicket:id="form"> First Name: <input type="text" wicket:id="firstName" /><br /> Email Address: <input type="text" wicket:id="email" /><br /> Date of Birth: <input type="text" wicket:id="dob" /><br /> <input type="submit" value="Save" /> </form> </body> </html>

现在查看Java代码,您会看到我们创建了两个构造函数。 这样,该表格既可以用作“添加人”表格,也可以用作“编辑现有人”表格。 默认情况下,将调用无参数构造函数,该构造函数使其成为“添加个人”形式,因为它使用的是持有新个人的模型。 但是,只需将模型传递给现有人员,即可轻松地编写一个向用户显示“编辑人员”页面的链接。 (请注意,我们在本文中没有介绍该示例,但是如果您这样做,则可能需要使用 LoadableDetachableModel ,在模型部分中将对此进行详细讨论。)

接下来,您看到我们实例化了 Form 对象。 我们实现 onSubmit 方法并使其包含我们的业务逻辑-在这种情况下,是对服务层类的简单调用。 继续前进,您会看到我们在哪里创建每个字段并使用UI规则对其进行配置-哪些字段是必填字段,以及哪些字段是必填字段(例如,有效的电子邮件地址格式)。 您看不到的是令人耳目一新的信息-无需调用 HttpRequest 即可获取字符串,无需将字符串转换为日期,无需手动从表单发布中检索数据,也无需手动设置背景Person对象上的数据。 在长格式中,这节省了数百行复制和粘贴以及高度易出错的代码。 这是因为我们正在处理 真正的Java对象 ,而不是一堆必须手动操作的字符串。 有关更多信息,请参见“前十名”列表中的表单处理图像以及下面指向前十名完整列表的链接。

请注意,我们正在使用服务层对象( IPersonService )进行持久化。 这是一个Spring管理的bean,并且由于Wicket的内置Spring(如果需要,可以选择Guice)集成,使用起来非常简单。

public class HomePage extends WebPage {
    
    @SpringBean
    IPersonService personService;
    
    public HomePage() {
        this(new Model<Person>(new Person()));
    }

    public HomePage(IModel<Person> model) {
        Form<Person> form = new Form<Person>("form", model) {
            protected void onSubmit() {
                Person person = this.getModelObject();
                System.out.println("Saving: " + person);
                personService.savePerson(person);
            }
        };
        
        TextField<String> firstName = new TextField<String>("firstName", new PropertyModel<String>(model, "firstName"));
        firstName.setRequired(true);
        form.add(firstName);
        
        TextField<Date> dob = new TextField<Date>("dob", new PropertyModel<Date>(model, "birthDate"));
        dob.setRequired(true);
        form.add(dob);
        
        TextField<String> email = new TextField<String>("email", new PropertyModel<String>(model, "emailAddress"));
        email.setRequired(true);
        email.add(EmailAddressValidator.getInstance());
        form.add(email);
        
        add(form);
        add(new FeedbackPanel("feedback"));
    }
}

在代码示例中,您已经看到了多次提到模型的信息,前面将它们描述为“用于检索或设置数据的包装器”。 那么,什么是模型,为什么它如此重要? 如前所述,Wicket将整个组件层次结构(页面和添加到其中的所有组件以及添加到这些组件的组件等等)存储在内存中,然后存储到磁盘中,以便您有状态地工作通过无状态HTTP使用Java对象。 但是显示这些数据的这些组件不一定需要在两次请求之间存储数据本身。 他们只需要存储状态-可能是一个标志,指示它们是可见还是不可见,已启用或已禁用,已扩展还是已折叠。 他们所显示的实际数据很可能已经保存在其他位置(可能在数据库中),这意味着我们实际上不需要将其保存到用户的HTTP会话中。 这是模型存在的原因之一–减少了保持组件层次结构所需的内存量。

同样重要的第二个原因是从组件本身提取数据的检索和存储。 考虑上面的表单示例中的简单TextField组件。 它不需要知道它正在编辑的字符串是来自会话,来自Web服务还是来自POJO上的字段。 它仅需要能够从某处获取字符串并在某处设置编辑后的字符串。 IModel 接口有两个方法本- 的getObject 方法setObject -这允许它能够做到这一点。 在开始使用Wicket之前,您还应该查看有关它们的我的资源页面

每个Wicket程序员应该知道的十件事

这是我列出的每个Wicket程序员都应该知道的十大事情的精简版。 有关完整版本,请参见http://wickettraining.com/resources/ten-things-every-wicket-programmer-should-know.html

  1. 模型 –在用Wicket编写任何大型应用程序之前,请务必确保您了解模型。
  2. 拉动,不要推 -通常,您的组件应该能够 拉动 其状态,而不是让其他组件 状态 到其上。 下面的示例演示了这意味着什么以及为什么如此重要。 关键是 构造函数只运行一次 ,但是 构造函数运行后 ,页面上的许多内容可能会更改状态。 如果 状态 入构造函数中的组件,则一旦另一个组件更改了状态,它们就会过时。 唯一的选择是,每个组件都必须知道共享状态的所有其他组件–这不是“ Wicket方法”。 您的组件应独立且可重用。
  3. Wicket是一个UI框架 –不要在Wicket中编写中间层或持久性代码。
  4. 保持标记和代码整洁,紧凑 –熟悉并使用Wicket的可重用性的各个方面–面板,标记继承和片段为例。
  5. 匹配您的层次结构 -完全不需要您花费太多时间来学习该规则,但是标记中组件的层次结构(带有wicket:id属性的标签)必须与Java代码中的层次结构相匹配。
  6. 表单处理生命周期 –处理表单时,了解表单后处理的操作顺序很重要。 如果在这个过程中的任何一步失败 窗体 onError 方法,并提交按钮将调用 ,而不是 方法 onsubmit( 下图
  7. Java细微差别 –有两种Java细微差别使许多Wicket新手措手不及–序列化和匿名内部类的存在。 两者都变得更加熟悉。
  8. 单元测试 –使用 WicketTester 相对容易地测试Wicket代码 试试看。
  9. i18n – Wicket使国际化变得非常容易。 熟悉诸如wicket:消息和Wicket内置i18n支持文件命名标准之类的内容。
  10. 在哪里寻求帮助 – Wicket代码已被详细记录,因此阅读JavaDocs是一个好的开始。 Wicket示例可以在GitHub上在线查看 此外,Wicket拥有任何开源项目中最繁忙,最有用的邮件列表之一。 有关Wicket邮件列表的更多信息,请参见 http://wicket.apache.org/help/email.html

apache wicket_教程– Apache Wicket:有趣的Web框架

结论

我之所以选择Apache Wicket,是因为其他框架从Web编程中吸取了乐趣(好吧,这是主观的,但是我可以说我个人并不喜欢它们)。 我的大部分时间似乎都花在了处理状态或以XML编写配置上。 每个微小的更改都需要对多个文件进行更改,而在XML,Java和专用标记文件中则需要多次更改。 很难制造具有粘性的可重用组件。 与Wicket在一起的几天让我看到了它的巨大变化。 我正在编写真正的Java面向对象代码,并轻松创建可重用的组件。 我希望您能为自己的项目或实验花几天的时间,以便您也能发现Web编程的乐趣。

有关Wicket的更多信息,请参见 http://wickettraining.com/resources

杰里米·汤姆森(Jeremy Thomerson)是一位技术爱好者,热爱探索,学习和创造新技术。 他帮助许多公司主要基于领先的Java开源技术(包括Wicket,Spring,Lucene,Hibernate等)将其架构升级为多层架构。 在过去的几年中,他拥有并经营着提供Wicket培训和咨询服务的美国领先公司。

本文最初发表在Java Tech Journal – Java Web Frameworks中。 您可以在这里找到更多有关该问题的下载

翻译自: https://jaxenter.com/tutorial-apache-wicket-the-fun-web-framework-104503.html

apache wicket

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/23248.html

(0)

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

关注微信