了解 Apache Click

使用轻量模型快速编写 Web 应用程序,避免使用复杂的框架

本文将介绍 Apache Click,这是一个 Java™ Platform, Enterprise Edition (Java EE) Web 应用程序框架,可以用它创建 Web 应用程序,而不需要使用 Model-View-Controller (MVC) 模式或 JavaServer Pages (JSP)。本文通过示例演示如何显示简单的网页并创建 Web 表单,表单提交的数据在另一个网页上显示。

Nathan A. Good, 高级顾问,自由开发人员, Enterprise Frameworks

Nathan Good Nathan A. Good 居住在明尼苏达州的双子城。他的专长是软件开发、软件架构和系统管理。平时不编写软件时,他喜欢组装 PC 和服务器、阅读和撰写技术文章,并鼓励他的所有朋友转用开源软件。他是许多书籍和文章的作者或合著者,包括 Professional Red Hat Enterprise Linux 3, Regular Expression Recipes: A Problem-Solution ApproachFoundations of PEAR: Rapid PHP Development



2010 年 5 月 06 日

本文中的示例要求安装 Eclipse 和 Web 应用服务器。这些示例使用 Tomcat 6.0,但是使用 WebSphere® Application Server Community Edition、Jetty 或 Tomcat 的老版本等其他 Web 应用服务器应该也可以。如果还没有安装 Web 应用服务器,可以通过 参考资料 下载并安装 Apache Tomcat 6.0 或 WebSphere Application Server Community Edition。

Apache Click 概述

Apache Click 是一个 Web 应用程序框架,可以用它快速地构建 Java Web 应用程序。Apache Click 的目标是提供一种无须使用 JSP 或 MVC 框架的构建 Web 应用程序的方法,这可以简化 Web 应用程序的开发。Apache Click 采用 Apache License 许可协议(见 参考资料)。

Apache Click 并不使用复杂的框架,而是使用 HTML 模板和普通旧式 Java 对象 (POJO)。HTML 模板由 Apache Velocity 模板引擎处理(关于 Apache Velocity 的更多信息见 参考资料),这使模板尽可能接近标准的 HTML,不需要特殊的标记。使用 Velocity 模板不需要学习复杂的语法,让 Web 开发人员可以发挥现有的 HTML 技能。

POJO 继承由 Apache Click 发行版提供的基类。Apache Click 提供一个 Page 类和组件类,通过编写它们的子类实现每个页面的处理代码。这些组件提供开箱即用的功能,可以用它们构建 HTML 控件并响应事件。

Apache Click 还包含一个用于 mock 测试的 API,可以用它改进单元测试、连续集成构建和测试驱动开发 (TDD)。关于 Mock API 的更多信息见 参考资料


Apache Click 组件和事件处理

org.apache.click.Page 类是所有页面组件的基类。可以使用 Page 基类中的方法处理多种事件,比如页面初始化 (onInit())、页面显示 (onRender()) 和页面安全检查 (onSecurityCheck())。在扩展 Page 的类中,可以通过覆盖这些方法提供定制的功能。扩展 Page 的每个类还可以包含处理页面事件的方法。

通过实现 java.io.Serializable 接口并在构造方法中调用 Page 基类的 setStateful() 方法,可以创建有状态的页面(见清单 1)。

清单 1. 在构造方法中设置 stateful 属性
    public WelcomePage() {
        setStateful(true);
    }

Apache Click 提供几个与 HTML 元素对应的控件组件。通过动态地添加这些控件组件,可以以编程方式构建表单。通过使用这些控件,可以在 Java 代码中以编程方式获取和设置 HTML 控件数据。

通过使用字段控件(即 TextFieldSelect)的 setEventListener() 方法,可以在扩展 Page 的类上定义一个方法,如果字段中的输入是有效的,在处理表单期间就会执行这个方法。

按钮和链接也提供事件处理。可以在表单上创建新的提交按钮并把它链接到 Page 类中的一个方法,使用的声明见清单 2。

清单 2. 用 onClick 事件处理方法创建提交按钮
Submit submitButton = new Submit("Submit Me", this, "onClick");

在单击按钮时,事件被分派给定制的 Page 类的 onClick() 方法。执行 onClick() 方法中的所有代码,包括把数据保存到数据库中或转发给另一个页面的代码。

关于这个 API 的更多信息见 参考资料


Apache Click 模板

在默认情况下,Apache Click 使用 Apache Velocity 模板引擎。根据一些默认的映射规则,模板自动地与应用程序中扩展 Page 的类匹配。例如,名为 HelloPage 的页面类自动地与 Web 项目中的 HTML 文件 hello.html 匹配。名为 HelloWorldPage 的页面类自动地映射到 helloWorld.html 或 hello-world.html 文件。

如果不喜欢默认的页面映射,可以修改 click.xml 文件,添加自己的定制映射。

除了修改 Velocity 使用的页面映射外,还可以决定不使用 Velocity 作为模板引擎。Apache Click 允许使用 JSP 显示页面,这有助于使用现有的 JSP。


下载 Apache Click

从网站下载 Apache Click(见 参考资料)。下载之后,把压缩 (.zip) 文件解压到容易记住的位置。

如果想看看 Apache Click 附带的示例,可以把 dist 文件夹中的 click-examples.war 文件部署到 Web 应用服务器中。示例包括许多不同的场景,比如构建表格、使用不同的控件和使用不同的模板。

下载和解压文件之后,就可以开始创建包含 Apache Click 库的 Web 应用程序了。


导入 Apache Click

把所需的 Java Archive (JAR) 文件放在 Web 项目中就可以安装 Apache Click。在 Web 项目中包含 Apache Click 之后,把项目部署到 Web 应用服务器中。

在 Eclipse 中,按以下步骤创建使用 Apache Click 的 Web 应用程序:

  1. 从菜单中选择 New > Other
  2. Select a Wizard 中,选择 Web / Dynamic Web Project 并单击 Next
  3. 输入一个名称作为 Project Name(例如,MyFirstClick)。
  4. 选择一个 Target Runtime,比如 Apache Tomcat 6.0。关于为 Eclipse 配置运行时的更多信息见 参考资料
  5. 单击 Finish — 其他设置可以保持默认值。

完成这些步骤之后,在 Eclipse 中应该有一个新的空 Web 项目(见图 1)。

图 1. 空的 Web 项目
显示空 Web 项目中的目录的屏幕截图

现在,可以导入 Apache Click 库。按以下步骤导入库:

  1. 单击 File > Import
  2. 从列表中选择 General / File System 并单击 Next
  3. 浏览到解压 Apache Click 文件的目录并选择 dist 目录。
  4. 在文件列表中,选择 click-{version}.jar 和 click-{version}-extras.jar 文件(见图 2)。
    图 2. 导入 JAR 文件
    选择 click-2.0.1-incubating.jar 和 click-extras-2.0.1-incubating.jar
  5. 确认在 Into folder 字段中选择了 WebContent/WEB-INF/lib 文件夹,然后单击 Finish

在 WEB-INF 目录中导入 JAR 文件之后,修改 Web 应用程序的 web.xml 文件以包含 ClickServlet,Apache Click 使用这个 servlet 分派事件。配置这个 servlet 之后,就不再需要修改 web.xml 文件了。web.xml 的内容见清单 3。

清单 3. web.xml 文件
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/javaee" 
		xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
		http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    id="WebApp_ID" version="2.5">
    <display-name>MyFirstClick</display-name>

    <servlet>
        <servlet-name>ClickServlet</servlet-name>
        <servlet-class>org.apache.click.ClickServlet</servlet-class>
        <load-on-startup>0</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>ClickServlet</servlet-name>
        <url-pattern>*.html</url-pattern>
    </servlet-mapping>

    <welcome-file-list>
        <welcome-file>welcome.html</welcome-file>
    </welcome-file-list>

</web-app>

现在创建一个包(比如 com.example.myfirstclick.pages),您的页面类将放在这里。创建包之后,在 Web 项目的 WEB-INF 文件夹中创建新文件 click.xml。在 click.xml 文件中指定刚才创建的包的名称,见清单 4。

清单 4. click.xml 文件
<?xml version="1.0" encoding="UTF-8"?>
<click-app>
    <pages package="com.example.myfirstclick.pages" />
</click-app>

构建示例应用程序

既然项目已经设置好了,就可以开始编写扩展 Apache Click 类的类了。第一个类扩展 Page(所有页面组件的基类)。通过选择 File > New > Other 并选择 Java / Class 在包中创建新的类。一定要输入 org.apache.click.Page 作为 Superclass

在新类中添加清单 5 所示的内容。

清单 5. WelcomePage
package com.example.myfirstclick.pages;

import org.apache.click.Page;

public class WelcomePage extends Page {

    // Initialize the value to something
    protected String theMessage = "Welcome!";

    public WelcomePage() {
        // Add the value to the map ("message" = "$message")
        addModel("message", theMessage);
    }
}

创建了 WelcomePage 类之后,需要创建一个 HTML 页面,它是为浏览器提供输出的模板。因为 Apache Click 的默认模板引擎是 Apache Velocity,HTML 文件与一般的静态 HTML 页面相似。

在 Web 项目的 WebContent 文件夹中创建新的 HTML 页面(名为 welcome.html),添加清单 6 所示的内容。

清单 6. welcome.html 文件
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>MyFirstClick Welcome</title>
</head>
<body>
<p>$message</p>
</body>
</html>

注意 HTML 文件中的 $message 变量。在生成页面时,Velocity 模板引擎会替换这个变量。ClickServletWelcomePage 类与 welcome.html 文件匹配起来。WelcomePage 类把它的 message 字段初始化为一个值 (Welcome),然后在构造方法中通过传递变量名(message 映射到 $message)和值(theMessage 字段),使用 addModel() 方法把这个值添加到模块中。分配给这个字段的值显示在浏览器中。


运行示例应用程序

创建文件之后,可以以 Web Archive (WAR) 的形式把文件导出到 Tomcat webapps 文件夹,从而试用这个应用程序。最简便的方法是在 Eclipse 中执行以下步骤:

  1. 单击这个项目并选择 File > Export
  2. 选择 Web / WAR 文件并单击 Next
  3. Destination 字段中,浏览到 Tomcat webapps 文件夹。
  4. 确保选择 Overwrite existing files 并单击 Finish(见图 3)。
    图 3. 以 WAR 的形式导出项目
    显示导出 MyFirstClick 项目的窗口

把 WAR 文件导出到 Tomcat webapps 目录之后,可以通过在浏览器中访问 http://localhost:8080/MyFirstClick/welcome.html 来浏览这个新页面(如果 Web 应用服务器使用不同的端口,或者 Web 应用程序使用不同的名称,URL 可能有变化)。

修改 WelcomePage 中 message 字段的值,然后把它重新部署到 Web 应用服务器中。如果看到修改后的值,就说明应用程序运行正常,可以研究更动态的示例了。


构建表单

既然已经完成了简单的欢迎页面,就可以试试更复杂的功能了。动态的网站不仅仅包含只读的数据,其中大多数都需要用户输入并使用用户输入执行某些操作。典型的示例是通过表单接收输入,然后在另一个网页上显示输入。

对于这个示例,创建另一个扩展 Page 的类。把这个新类命名为 InputPage(见清单 7)。

清单 7. InputPage
package com.example.myfirstclick.pages;

import org.apache.click.Page;
import org.apache.click.control.Form;
import org.apache.click.control.Submit;
import org.apache.click.control.TextField;

public class InputPage extends Page {

    public Form form = new Form();

    private TextField nameField;

    public InputPage() {

        form.setLabelsPosition(Form.POSITION_TOP);

        nameField = new TextField("Enter your name");

        form.add(nameField);
        form.add(new Submit("Submit", this, "onSubmitClick"));

    }
    
    public boolean onSubmitClick()
    {
        SayHelloPage nextPage = (SayHelloPage)getContext().createPage("/sayHello.html");
        nextPage.setName(nameField.getValue());
        
        setForward(nextPage);
        
        return false;
    }

}

这个新类在构造方法中创建一个 Form 对象,在其中添加一个用于输入的字段。然后,添加一个 HTML 提交按钮和处理方法(onSubmitClick() 方法)。当单击提交按钮时执行这个处理方法,所以应该在其中创建下一个页面。在添加下一个页面(即 SayHelloPage)之前,代码无法编译。

现在,在 Web 项目的 WebContent 文件夹中创建一个新的 HTML 文件并命名为 input.html。在这个页面上添加一个 $form 变量,它将被替换为 InputPage 类中表单字段的 HTML 输出。完成之后,input.html 文件应该像清单 8 这样。

清单 8. input.html 文件
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>MyFirstClick Input Sample</title>
</head>
<body>
$form
</body>
</html>

现在,添加显示输入的页面,这个类名为 SayHelloPage,它也扩展 org.apache.click.Page。这个新类应该像清单 9 这样。

清单 9. SayHelloPage
package com.example.myfirstclick.pages;

import org.apache.click.Page;

public class SayHelloPage extends Page {

    private String name;
    
    @Override
    public void onInit()
    {
        super.onInit();
        
        if (name != null)
        {
            addModel("name", name);
        }

    }
    
    public void setName(String name) {
        this.name = name;
    }    
    
}

这个类通过覆盖 Page 基类的 onInit() 方法设置页面上显示的值。应该检查通过 addModel() 方法添加到模块中的任意值是否为 null — 如果试图添加 null 值,它会抛出 IllegalArgumentException。这要求您编写出在值为 null 时以适当方式显示页面的代码。

通过一个公共的 getter 方法 setName() 公开 SayHelloPage 类中的 name 字段。InputPage 中的 onSubmitClick() 事件处理方法在获得页面的新实例之后调用这个 accessor 方法。

“No path configured...” 错误

在我初次运行代码时,从 ClickServlet 产生了一个错误,错误消息是 “No path configured for Page class: com.example.myfirstclick.pages.SayHelloPage”。原因在于我把 SayHelloPage.class 传递给 createPage(),但是没有在 click.xml 中配置这个页面。把它改为 /sayHello.html 就恢复正常了。这是因为在默认情况下 Apache Click 映射扩展名为 .jsp 和 .htm 的文件,而我选用 .html 作为扩展名。

onSubmitClick() 方法使用来自 nameField 控件的值 (nameField.getValue()) 设置名称。然后使用 setForward() 方法转移到下一个页面。结果是 SayHelloPage 上的 name 字段被填入输入框中的值并把它放在 $name 中。

现在添加 HTML 文件 sayHello.html,它包含 $name 变量。sayHello.html 的内容见清单 10。

清单 10. sayHello.html 页面
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Results</title>
</head>
<body>
<p>Hello, $name!</p>
</body>
</html>

在 Web 浏览器中访问 http://localhost:8080/MyFirstClick/input.html 以运行这个示例。在文本框中输入一个值并单击 Submit。现在浏览器中会显示这个值。


结束语

通过使用 Apache Click,可以用轻量模型快速编写 Web 应用程序,不需要使用复杂的框架。Apache Click 的简单性让我们能够使用自己的面向对象编程实践和模式。默认的模板引擎 Velocity 不需要定制的标记,让 HTML 代码更接近 HTML 规范的要求。

Apache Click 中的组件和事件模型提供了一种构建 HTML 控件和处理事件的方法,非常容易掌握。

参考资料

学习

获得产品和技术

讨论

条评论

developerWorks: 登录

标有星(*)号的字段是必填字段。


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件

 


在您首次登录 developerWorks 时,会为您创建一份个人概要。您的个人概要中的信息(您的姓名、国家/地区,以及公司名称)是公开显示的,而且会随着您发布的任何内容一起显示,除非您选择隐藏您的公司名称。您可以随时更新您的 IBM 帐户。

所有提交的信息确保安全。

选择您的昵称



当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

标有星(*)号的字段是必填字段。

(昵称长度在 3 至 31 个字符之间)

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

 


所有提交的信息确保安全。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Web development, Open source
ArticleID=487687
ArticleTitle=了解 Apache Click
publish-date=05062010