了解Apache Click应用框架
本文中的示例要求安装 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 的更多信息见 参考资料。
org.apache.click.Page
类是所有页面组件的基类。可以使用 Page
基类中的方法处理多种事件,比如页面初始化 (onInit()
)、页面显示 (onRender()
) 和页面安全检查 (onSecurityCheck()
)。在扩展 Page
的类中,可以通过覆盖这些方法提供定制的功能。扩展 Page
的每个类还可以包含处理页面事件的方法。
通过实现 java.io.Serializable
接口并在构造方法中调用 Page
基类的 setStateful()
方法,可以创建有状态的页面(见清单 1)。
public WelcomePage() { setStateful(true); } |
Apache Click 提供几个与 HTML 元素对应的控件组件。通过动态地添加这些控件组件,可以以编程方式构建表单。通过使用这些控件,可以在 Java 代码中以编程方式获取和设置 HTML 控件数据。
通过使用字段控件(即 TextField
、Select
)的 setEventListener()
方法,可以在扩展 Page
的类上定义一个方法,如果字段中的输入是有效的,在处理表单期间就会执行这个方法。
按钮和链接也提供事件处理。可以在表单上创建新的提交按钮并把它链接到 Page
类中的一个方法,使用的声明见清单 2。
Submit submitButton = new Submit("Submit Me", this, "onClick"); |
在单击按钮时,事件被分派给定制的 Page
类的 onClick()
方法。执行 onClick()
方法中的所有代码,包括把数据保存到数据库中或转发给另一个页面的代码。
关于这个 API 的更多信息见 参考资料。
在默认情况下,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(见 参考资料)。下载之后,把压缩 (.zip) 文件解压到容易记住的位置。
如果想看看 Apache Click 附带的示例,可以把 dist 文件夹中的 click-examples.war 文件部署到 Web 应用服务器中。示例包括许多不同的场景,比如构建表格、使用不同的控件和使用不同的模板。
下载和解压文件之后,就可以开始创建包含 Apache Click 库的 Web 应用程序了。
把所需的 Java Archive (JAR) 文件放在 Web 项目中就可以安装 Apache Click。在 Web 项目中包含 Apache Click 之后,把项目部署到 Web 应用服务器中。
在 Eclipse 中,按以下步骤创建使用 Apache Click 的 Web 应用程序:
- 从菜单中选择 New > Other。
- 在 Select a Wizard 中,选择 Web / Dynamic Web Project 并单击 Next。
- 输入一个名称作为 Project Name(例如,
MyFirstClick
)。 - 选择一个 Target Runtime,比如 Apache Tomcat 6.0。关于为 Eclipse 配置运行时的更多信息见 参考资料。
- 单击 Finish — 其他设置可以保持默认值。
完成这些步骤之后,在 Eclipse 中应该有一个新的空 Web 项目(见图 1)。
现在,可以导入 Apache Click 库。按以下步骤导入库:
- 单击 File > Import。
- 从列表中选择 General / File System 并单击 Next。
- 浏览到解压 Apache Click 文件的目录并选择 dist 目录。
- 在文件列表中,选择 click-{version}.jar 和 click-{version}-extras.jar 文件(见图 2)。
图 2. 导入 JAR 文件 - 确认在 Into folder 字段中选择了 WebContent/WEB-INF/lib 文件夹,然后单击 Finish。
在 WEB-INF 目录中导入 JAR 文件之后,修改 Web 应用程序的 web.xml 文件以包含 ClickServlet
,Apache Click 使用这个 servlet 分派事件。配置这个 servlet 之后,就不再需要修改 web.xml 文件了。web.xml 的内容见清单 3。
<?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。
<?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 所示的内容。
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 所示的内容。
<!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 模板引擎会替换这个变量。ClickServlet
把 WelcomePage
类与 welcome.html 文件匹配起来。WelcomePage
类把它的 message 字段初始化为一个值 (Welcome
),然后在构造方法中通过传递变量名(message
映射到 $message
)和值(theMessage
字段),使用 addModel()
方法把这个值添加到模块中。分配给这个字段的值显示在浏览器中。
创建文件之后,可以以 Web Archive (WAR) 的形式把文件导出到 Tomcat webapps 文件夹,从而试用这个应用程序。最简便的方法是在 Eclipse 中执行以下步骤:
- 单击这个项目并选择 File > Export。
- 选择 Web / WAR 文件并单击 Next。
- 在 Destination 字段中,浏览到 Tomcat webapps 文件夹。
- 确保选择 Overwrite existing files 并单击 Finish(见图 3)。
图 3. 以 WAR 的形式导出项目
把 WAR 文件导出到 Tomcat webapps 目录之后,可以通过在浏览器中访问 http://localhost:8080/MyFirstClick/welcome.html 来浏览这个新页面(如果 Web 应用服务器使用不同的端口,或者 Web 应用程序使用不同的名称,URL 可能有变化)。
修改 WelcomePage
中 message 字段的值,然后把它重新部署到 Web 应用服务器中。如果看到修改后的值,就说明应用程序运行正常,可以研究更动态的示例了。
既然已经完成了简单的欢迎页面,就可以试试更复杂的功能了。动态的网站不仅仅包含只读的数据,其中大多数都需要用户输入并使用用户输入执行某些操作。典型的示例是通过表单接收输入,然后在另一个网页上显示输入。
对于这个示例,创建另一个扩展 Page
的类。把这个新类命名为 InputPage
(见清单 7)。
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 这样。
<!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 这样。
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 方法。
onSubmitClick()
方法使用来自 nameField
控件的值 (nameField.getValue()
) 设置名称。然后使用 setForward()
方法转移到下一个页面。结果是 SayHelloPage
上的 name 字段被填入输入框中的值并把它放在 $name
中。
现在添加 HTML 文件 sayHello.html,它包含 $name
变量。sayHello.html 的内容见清单 10。
<!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 控件和处理事件的方法,非常容易掌握。