Introduction to the Wicket Framework – Wicket框架简介

最后修改: 2016年 10月 10日

1. Overview

1.概述

Wicket is a Java server-side web component-oriented framework that aims at simplifying building web interfaces by introducing patterns known from desktop UI development.

Wicket 是一个面向Java服务器端Web组件的框架,旨在通过引入桌面UI开发中已知的模式来简化Web界面的构建。

With Wicket it is possible to build a web application using only Java code and XHTML compliant HTML pages. No need for Javascript, nor XML configuration files.

有了Wicket,就可以只用Java代码和XHTML兼容的HTML页面来构建Web应用。不需要Javascript,也不需要XML配置文件。

It provides a layer over the request-response cycle, shielding from working at a low level and allowing developers to focus on the business logic.

它在请求-响应周期上提供了一个层,屏蔽了在低水平上的工作,使开发人员能够专注于业务逻辑。

In this article, we will introduce the basics by building the HelloWorld Wicket application, followed by a complete example using two built-in components that communicate with each other.

在这篇文章中,我们将通过构建HelloWorld Wicket应用程序来介绍基础知识,然后是一个使用两个相互通信的内置组件的完整例子。

2. Setup

2.设置

To run a Wicket project, let’s add the following dependencies:

为了运行Wicket项目,我们来添加以下依赖项。

<dependency>
    <groupId>org.apache.wicket</groupId>
    <artifactId>wicket-core</artifactId>
    <version>7.4.0</version>
</dependency>

You may want to check out the latest version of Wicket in the Maven Central repository, which at the time of your reading may not coincide with the one used here.

你可能想看看Maven Central仓库中的Wicket最新版本,在你阅读时,该仓库可能与这里使用的版本不一致。

Now we are ready to build our first Wicket application.

现在我们已经准备好构建我们的第一个Wicket应用程序了。

3. HelloWorld Wicket

3.HelloWorldWicket

Let’s start by subclassing Wicket’s WebApplication class, which, at a minimum, requires overriding the Class<? extends Page> getHomePage() method.

我们先从Wicket的WebApplication类的子类开始,这至少需要覆盖Class<? extends Page> getHomePage()方法。

Wicket will use this class as application’s main entry point. Inside the method, simply return a class object of a class named HelloWorld:

Wicket会用这个类作为应用程序的主入口。在该方法中,只需返回一个名为HelloWorld:的类的class对象。

public class HelloWorldApplication extends WebApplication {
    @Override
    public Class<? extends Page> getHomePage() {
        return HelloWorld.class;
    }
}

Wicket favors convention over configuration. Adding a new web page to the application requires creating two files: a Java file and an HTML file with the same name (but different extension) under the same directory. Additional configuration is only needed if you want to change the default behaviour.

Wicket更倾向于惯例而不是配置。在应用中添加新的网页需要创建两个文件:一个Java文件和同一目录下的同名HTML文件(但扩展名不同)。只有当你想改变默认行为时,才需要额外的配置。

In the source code’s package directory, first add the HelloWorld.java:

在源代码的包目录中,首先添加HelloWorld.java

public class HelloWorld extends WebPage {
    public HelloWorld() {
        add(new Label("hello", "Hello World!"));
    }
}

then HelloWorld.html:

然后HelloWorld.html

<html>
    <body>
        <span wicket:id="hello"></span>
    </body>
</html>

As a final step, add the filter definition inside the web.xml:

作为最后一步,在web.xml中添加过滤器定义:

<filter>
    <filter-name>wicket.examples</filter-name>
    <filter-class>
      org.apache.wicket.protocol.http.WicketFilter
    </filter-class>
    <init-param>
        <param-name>applicationClassName</param-name>
        <param-value>
          com.baeldung.wicket.examples.HelloWorldApplication
        </param-value>
    </init-param>
</filter>

That’s it. We have just coded our first Wicket web application.

就这样了。我们刚刚编好了第一个Wicket网络应用。

Run the project by building a war file, (mvn package from the command line) and deploy it on a servlet container such as Jetty or Tomcat.

通过建立一个war文件来运行该项目,(mvn package来自命令行)并将其部署在一个Servlet容器上,如Jetty或Tomcat。

Let’s access http://localhost:8080/HelloWorld/ in the browser. An empty page with the message Hello World! shall appear.

让我们在浏览器中访问http://localhost:8080/HelloWorld/。会出现一个空的页面,上面写着Hello World!将出现。

4. Wicket Components

4.球门组件

Components in Wicket are triads consisting of a Java class, the HTML markup, and a model. Models are a facade that components use to access the data.

Wicket的组件是由一个Java类、HTML标记和一个模型组成的三元组。模型是组件用来访问数据的一个门面。

This structure provides a nice separation of concerns and by decoupling the component from data-centric operations, increases code reuse.

这种结构提供了一个很好的关注点分离,通过将组件与以数据为中心的操作解耦,增加了代码的重用。

The example that follows demonstrates how to add Ajax behaviour to a component. It consists of a page with two elements: a dropdown menu and a label. When the dropdown selection changes, the label (and only the label) will be updated.

下面的例子演示了如何向一个组件添加Ajax行为。它包括一个有两个元素的页面:一个下拉菜单和一个标签。当下拉菜单的选择发生变化时,标签(而且只有标签)将被更新。

The body of the HTML file CafeSelector.html will be minimal, with only two elements, a dropdown menu, and a label:

HTML文件CafeSelector.html的主体将是最小的,只有两个元素,一个下拉菜单,和一个标签。

<select wicket:id="cafes"></select>
<p>
    Address: <span wicket:id="address">address</span>
</p>

On the Java side, let’s create the label:

在Java方面,我们来创建标签。

Label addressLabel = new Label("address", 
  new PropertyModel<String>(this.address, "address"));
addressLabel.setOutputMarkupId(true);

The first argument in the Label constructor matching the wicket:id assigned in the HTML file. The second argument is the component’s model, a wrapper for the underlying data that is presented in the component.

Label构造函数的第一个参数与HTML文件中分配的wicket:id相匹配。第二个参数是组件的模型,是组件中呈现的底层数据的封装器。

The setOutputMarkupId method makes the component eligible for modification via Ajax. Let’s now create the dropdown list and add Ajax behavior to it:

setOutputMarkupId方法使该组件有资格通过Ajax修改。现在让我们创建下拉列表,并向它添加Ajax行为。

DropDownChoice<String> cafeDropdown 
  = new DropDownChoice<>(
    "cafes", 
    new PropertyModel<String>(this, "selectedCafe"), 
    cafeNames);
cafeDropdown.add(new AjaxFormComponentUpdatingBehavior("onchange") {
    @Override
    protected void onUpdate(AjaxRequestTarget target) {
        String name = (String) cafeDropdown.getDefaultModel().getObject();
        address.setAddress(cafeNamesAndAddresses.get(name).getAddress());
        target.add(addressLabel);
    }
});

The creation is similar to the label’s, the constructor accepts the wicket id, a model and a list of cafe names.

创建过程与标签类似,构造函数接受wicket ID、模型和咖啡馆名称的列表。

Then AjaxFormComponentUpdatingBehavior is added with the onUpdate callback method that updates the label’s model once ajax request is issued. Finally, the label component is set as a target for refreshing.

然后AjaxFormComponentUpdatingBehavior被添加到onUpdate回调方法中,一旦发出Ajax请求就会更新标签的模型。最后,标签组件被设置为刷新的目标。

Finally, the label component is set as a target for refreshing.

最后,标签组件被设定为刷新的目标。

As you can see everything is Java, not a single line of Javascript was necessary. In order to change what the label displays we simply modified a POJO. The mechanism by which modifying a Java object translates to a change in the web page happens behind the curtains and is not relevant to the developer.

正如你所看到的,所有的东西都是Java,没有必要使用一行Javascript。为了改变标签显示的内容,我们只需修改一个POJO。修改一个Java对象转化为网页变化的机制发生在幕后,与开发者无关。

Wicket offers a big set of AJAX-enabled components out-of-the-box. The catalog of the components with live examples is available here.

Wicket提供了一大套开箱即用的AJAX组件。带有实时示例的组件目录可以在这里找到。

5. Conclusion

5.结论

In this introductory article, we’ve covered the basics of Wicket the component-based web framework in Java.

在这篇介绍性文章中,我们已经介绍了Wicket这个基于组件的Java网络框架的基本知识。

Wicket provides a layer of abstraction that aims to do away entirely with the plumbing code.

Wicket提供了一个抽象层,旨在完全摒弃管道代码。

We’ve included two simple examples, which can be found on GitHub, to give you a taste of what development with this framework looks like.

我们已经包括了两个简单的例子,可以在GitHub上找到,让你体验一下用这个框架进行开发的感觉。