GWT - 快速指南
GWT - 概述
什么是 GWT?
Google Web Toolkit (GWT) 是一个用于创建 RICH Internet 应用程序 (RIA) 的开发工具包。以下是其一些值得注意的功能 −
GWT 为开发人员提供了使用 JAVA 编写客户端应用程序的选项。
GWT 将使用 JAVA 编写的代码编译为 JavaScript 代码。
使用 GWT 编写的应用程序兼容跨浏览器。GWT 会自动生成适用于每种浏览器的 javascript 代码。
GWT 是开源的、完全免费的,全球有成千上万的开发人员在使用。它根据 Apache 许可证 2.0 版获得许可。
总体而言,GWT 是一个框架,用于构建大规模、高性能的 Web 应用程序,同时保持其易于维护。
为什么要使用 GWT?
基于 Java,您可以使用 Eclipse 等 JAVA IDE 来开发 GWT 应用程序。
开发人员可以使用代码自动完成/重构/导航/项目管理以及 IDE 的所有功能。GWT 提供完整的调试功能。开发人员可以像调试 Java 应用程序一样调试客户端应用程序。
GWT 可轻松与 Junit 和 Maven 集成。
同样基于 Java,GWT 对于 Java 开发人员来说学习难度较低。
GWT 生成优化的 javascript 代码,自行生成浏览器特定的 javascript 代码。
GWT 提供的 Widgets 库可满足应用程序中所需的大部分任务。
GWT 可扩展,可以创建自定义小部件以满足应用程序需求。
最重要的是,GWT 应用程序可以在所有主流浏览器和智能手机上运行,包括基于 Android 和 iOS 的手机/平板电脑。
GWT 的缺点
尽管 GWT 提供了许多优势,但它也存在以下缺点−
不可索引 − GWT 生成的网页不会被搜索引擎索引,因为这些应用程序是动态生成的。
不可降级 − 如果您的应用程序用户禁用了 Javascript,那么用户只会看到基本页面,而不会看到其他内容。
对设计师不友好 − GWT 不适合喜欢使用纯 HTML 和占位符在以后插入动态内容的网页设计师。
GWT 组件
GWT 框架可分为以下三个主要部分 −
GWT Java 到 JavaScript 编译器 − 这是 GWT 最重要的部分,使其成为构建 RIA 的强大工具。 GWT 编译器用于将用 Java 编写的所有应用程序代码转换为 JavaScript。
JRE 模拟库 − Google Web Toolkit 包含一个模拟 Java 运行时库子集的库。该列表包括 java.lang、java.lang.annotation、java.math、java.io、java.sql、java.util 和 java.util.logging
GWT UI 构建库 − GWT 的这一部分由许多子部分组成,其中包括实际的 UI 组件、RPC 支持、历史记录管理等等。
GWT 还提供了 GWT 托管 Web 浏览器,可让您在托管模式下运行和执行 GWT 应用程序,其中您的代码在 Java 虚拟机中以 Java 形式运行,而无需编译为 JavaScript。
GWT - 安装和环境设置
本教程将指导您如何准备开发环境以开始使用 GWT 框架。本教程还将教您如何在设置 GWT 框架之前在您的机器上设置 JDK、Tomcat 和 Eclipse −
系统要求
GWT 需要 JDK 1.6 或更高版本,因此第一个要求是在您的机器上安装 JDK。
JDK | 1.6 或更高版本。 |
---|---|
内存 | 无最低要求。 |
磁盘空间 | 无最低要求。 |
操作系统 | 无最低要求要求。 |
按照给定的步骤设置您的环境以开始 GWT 应用程序开发。
步骤 1 - 验证机器上的 Java 安装
现在打开控制台并执行以下 java 命令。
OS | 任务 | 命令 |
---|---|---|
Windows | 打开命令控制台 | c:\> java -version |
Linux | 打开命令终端 | $ java -version |
Mac | 打开终端 | machine:~ joseph$ java -version |
让我们验证所有操作系统的输出
Sr.No. | 操作系统和生成的输出 |
---|---|
1 |
Windows java version "1.6.0_21" Java(TM) SE Runtime Environment (build 1.6.0_21-b07) Java HotSpot(TM) Client VM (build 17.0-b17, mixed mode, sharing) |
2 |
Linux java version "1.6.0_21" Java(TM) SE Runtime Environment (build 1.6.0_21-b07) ava HotSpot(TM) Client VM (build 17.0-b17, mixed mode, sharing) |
3 |
Mac java version "1.6.0_21" Java(TM) SE Runtime Environment (build 1.6.0_21-b07) Java HotSpot(TM)64-Bit Server VM (build 17.0-b17, mixed mode, sharing) |
第 2 步 - 设置 Java 开发工具包 (JDK)
如果您尚未安装 Java,则可以从 Oracle 的 Java 站点安装 Java 软件开发工具包 (SDK):Java SE 下载。您将在下载的文件中找到安装 JDK 的说明,按照给出的说明安装和配置设置。最后设置 PATH 和 JAVA_HOME 环境变量以引用包含 java 和 javac 的目录,通常分别为 java_install_dir/bin 和 java_install_dir。
设置 JAVA_HOME 环境变量以指向 Java 在您的计算机上安装的基本目录位置。例如
Sr.No. | OS &输出 |
---|---|
1 |
Windows 将环境变量 JAVA_HOME 设置为 C:\Program Files\Java\jdk1.6.0_21 |
2 |
Linux export JAVA_HOME = /usr/local/java-current |
3 |
Mac export JAVA_HOME = /Library/Java/Home |
将 Java 编译器位置附加到系统路径。
Sr.No. | 操作系统和输出 |
---|---|
1 |
Windows 将字符串 ;%JAVA_HOME%\bin 附加到系统变量 Path 的末尾。 |
2 |
Linux export PATH=$PATH:$JAVA_HOME/bin/ |
3 |
Mac 不需要 |
或者,如果您使用像 Borland 这样的集成开发环境 (IDE) JBuilder、Eclipse、IntelliJ IDEA 或 Sun ONE Studio,编译并运行一个简单的程序,以确认 IDE 知道您在哪里安装了 Java,否则请按照 IDE 的给定文档进行正确设置。
步骤 3 - 设置 Eclipse IDE
本教程中的所有示例都是使用 Eclipse IDE 编写的。因此,我建议您根据您的操作系统在您的机器上安装最新版本的 Eclipse。
要安装 Eclipse IDE,请从 https://www.eclipse.org 下载最新的 Eclipse 二进制文件。下载安装程序后,将二进制分发包解压到方便的位置。例如在 Windows 上是 C:\eclipse,在 Linux/Unix 上是 /usr/local/eclipse,最后适当地设置 PATH 变量。
在 Windows 机器上执行以下命令即可启动 Eclipse,或者直接双击 eclipse.exe 即可
%C:\eclipse\eclipse.exe
在 Unix(Solaris、Linux 等)机器上执行以下命令即可启动 Eclipse −
$/usr/local/eclipse/eclipse
启动成功后,如果一切正常,则应显示以下结果 −
第 4 步 - 安装 GWT SDK 和 Eclipse 插件
按照链接 Eclipse 插件(包括 SDK) 中给出的说明安装 GWT SDK 和安装在您机器上的 Eclipse 版本的插件。
成功设置 GWT 插件后,如果一切正常,则应显示以下屏幕,其中 Google 图标 标有红色矩形,如下所示 −
步骤 5:设置 Apache Tomcat
您可以从 https://tomcat.apache.org/ 下载最新版本的 Tomcat。下载安装程序后,将二进制分发包解压到方便的位置。例如在 Windows 上位于 C:\apache-tomcat-6.0.33,或在 Linux/Unix 上位于 /usr/local/apache-tomcat-6.0.33,并设置指向安装位置的 CATALINA_HOME 环境变量。
可以在 Windows 机器上执行以下命令来启动 Tomcat,或者只需双击 startup.bat 即可
%CATALINA_HOME%\bin\startup.bat 或 /usr/local/apache-tomcat-6.0.33/bin/startup.sh
启动成功后,访问 http://localhost:8080/ 即可使用 Tomcat 附带的默认 Web 应用程序。如果一切正常,则应显示以下结果 −
有关配置和运行 Tomcat 的更多信息,请参阅此处包含的文档以及 Tomcat 网站 − https://tomcat.apache.org/
可以通过在 Windows 计算机上执行以下命令来停止 Tomcat −
%CATALINA_HOME%\bin\shutdown 或 C:\apache-tomcat-5.5.29\bin\shutdown
可以通过在 Unix(Solaris、Linux 等)计算机上执行以下命令来停止 Tomcat −
$CATALINA_HOME/bin/shutdown.sh or /usr/local/apache-tomcat-5.5.29/bin/shutdown.sh
GWT - 应用程序
在我们开始使用 GWT 创建实际的"HelloWorld"应用程序之前,让我们先看看 GWT 应用程序的实际部分是什么 −
GWT 应用程序由以下四个重要部分组成,其中最后一部分是可选的,但前三个部分是必需的。
- 模块描述符
- 公共资源
- 客户端代码
- 服务器端代码
典型 gwt 应用程序 HelloWord 不同部分的示例位置如下所示 −
名称 | 位置 |
---|---|
项目根目录 | HelloWorld/ |
模块描述符 | src/com/tutorialspoint/HelloWorld.gwt.xml |
公共资源 | src/com/tutorialspoint/war/ |
客户端代码 | src/com/tutorialspoint/client/ |
服务器端代码 | src/com/tutorialspoint/server/ |
模块描述符
模块描述符是 XML 形式的配置文件,用于配置 GWT 应用程序。
模块描述符文件扩展名为 *.gwt.xml,其中 * 是应用程序的名称,此文件应位于项目的根目录中。
以下是 HelloWorld 应用程序的默认模块描述符 HelloWorld.gwt.xml −
<?xml version = "1.0" encoding = "utf-8"?> <module rename-to = 'helloworld'> <!-- inherit the core web toolkit stuff. --> <inherits name = 'com.google.gwt.user.user'/> <!-- inherit the default gwt style sheet. --> <inherits name = 'com.google.gwt.user.theme.clean.Clean'/> <!-- specify the app entry point class. --> <entry-point class = 'com.tutorialspoint.client.HelloWorld'/> <!-- specify the paths for translatable code --> <source path = '...'/> <source path = '...'/> <!-- specify the paths for static files like html, css etc. --> <public path = '...'/> <public path = '...'/> <!-- specify the paths for external javascript files --> <script src = "js-url" /> <script src = "js-url" /> <!-- specify the paths for external style sheet files --> <stylesheet src = "css-url" /> <stylesheet src = "css-url" /> </module>
以下是模块描述符中使用的不同部分的简要说明。
Sr.No. | 节点和描述 |
---|---|
1 |
<module rename-to = "helloworld"> 这提供了应用程序的名称。 |
2 |
<inherits name = "logical-module-name" /> 这会在应用程序中添加其他 gwt 模块,就像在 java 应用程序中导入一样。可以以这种方式继承任意数量的模块。 |
3 |
<entry-point class = "classname" /> 这指定了将开始加载 GWT 应用程序的类的名称。可以添加任意数量的入口点类,并按照它们在模块文件中出现的顺序依次调用它们。因此,当第一个入口点的 onModuleLoad() 完成时,将立即调用下一个入口点。 |
4 |
<source path = "path" /> 这指定了 GWT 编译器将搜索源编译的源文件夹的名称。 |
5 |
<public path = "path" /> 公共路径是项目中存储 GWT 模块引用的静态资源(如 CSS 或图像)的位置。默认公共路径是存储模块 XML 文件下的公共子目录。 |
6 |
<script src="js-url" /> 自动注入位于 src 指定位置的外部 JavaScript 文件。 |
7 |
<stylesheet src="css-url" /> 自动注入位于 src 指定位置的外部 CSS 文件。 |
公共资源
这些都是您的 GWT 模块引用的文件,例如主机 HTML 页面、CSS 或图像。
可以使用模块配置文件中的 <public path = "path" /> 元素配置这些资源的位置。默认情况下,它是存储模块 XML 文件的公共子目录。
将应用程序编译为 JavaScript 时,可以在公共路径上找到的所有文件都将复制到模块的输出目录中。
最重要的公共资源是主机页,用于调用实际的 GWT 应用程序。应用程序的典型 HTML 主机页可能根本不包含任何可见的 HTML 正文内容,但始终希望通过 <script.../> 标记包含 GWT 应用程序,如下所示
<html> <head> <title>Hello World</title> <link rel = "stylesheet" href = "HelloWorld.css"/> <script language = "javascript" src = "helloworld/helloworld.nocache.js"> </script> </head> <body> <h1>Hello World</h1> <p>Welcome to first GWT application</p> </body> </html>
以下是我们在主页中包含的示例样式表 −
body { text-align: center; font-family: verdana, sans-serif; } h1 { font-size: 2em; font-weight: bold; color: #777777; margin: 40px 0px 70px; text-align: center; }
客户端代码
这是实际编写的 Java 代码,用于实现应用程序的业务逻辑,GWT 编译器会将其转换为 JavaScript,最终在浏览器中运行。可以使用模块配置文件中的 <source path = "path" /> 元素配置这些资源的位置。
例如,Entry Point 代码将用作客户端代码,其位置将使用 <source path = "path" /> 指定。
模块 entry-point 是可分配给 EntryPoint 的任何类,并且可以无参数构造。加载模块时,每个入口点类都会被实例化,并且其 EntryPoint.onModuleLoad() 方法会被调用。HelloWorld 入口点类示例如下。 −
public class HelloWorld implements EntryPoint { public void onModuleLoad() { Window.alert("Hello, World!"); } }
服务器端代码
这是应用程序的服务器端部分,并且是可选的。如果您没有在应用程序中进行任何后端处理,则不需要此部分,但如果后端需要某些处理并且您的客户端应用程序与服务器交互,则您必须开发这些组件。
下一章将利用上述所有概念使用 Eclipse IDE 创建 HelloWorld 应用程序。
GWT - 创建应用程序
由于 GWT 的强大之处在于用 Java 编写,用 JavaScript 运行,我们将使用 Java IDE Eclipse 来演示我们的示例。
让我们从一个简单的 HelloWorld 应用程序开始 −
步骤 1 - 创建项目
第一步是使用 Eclipse IDE 创建一个简单的 Web 应用程序项目。使用选项 Google 图标 > 新建 Web 应用程序项目... 启动项目向导。现在使用向导窗口将您的项目命名为 HelloWorld,如下所示 −
取消选择 使用 Google App Engine,因为我们不会在此项目中使用它,并保留其他默认值(保持 生成示例项目代码 选项选中),然后单击完成按钮。
成功创建项目后,您将在项目资源管理器中看到以下内容 −
以下是所有重要文件夹的简要说明
Sr.No. | 文件夹 &位置 |
---|---|
1 |
src 源代码(java 类)文件。 客户端文件夹,包含负责客户端 UI 显示的客户端特定 java 类。 服务器文件夹,包含负责服务器端处理的服务器端 java 类。 共享文件夹,包含用于将数据从服务器传输到客户端和反之亦然的 java 模型类。 HelloWorld.gwt.xml,GWT 编译器编译 HelloWorld 项目所需的模块描述符文件。 |
2 |
test 测试代码(java 类)源文件。 客户端文件夹包含负责测试 gwt 客户端代码的 java 类。 |
3 |
war 这是最重要的部分,它代表实际可部署的 Web 应用程序。 WEB-INF 包含已编译的类、gwt 库、servlet 库。 HelloWorld.css,项目样式表。 HelloWorld.html,将调用 GWT UI 应用程序的热门 HTML。 |
第 2 步 - 修改模块描述符:HelloWorld.gwt.xml
GWT 插件将创建一个默认模块描述符文件src/com.tutorialspoint/HelloWorld.gwt.xml 如下所示。对于此示例,我们不对其进行修改,但您可以根据需要对其进行修改。
<?xml version = "1.0" encoding = "UTF-8"?> <module rename-to = 'helloworld'> <!-- Inherit the core Web Toolkit stuff. --> <inherits name = 'com.google.gwt.user.User'/> <!-- Inherit the default GWT style sheet. You can change --> <!-- the theme of your GWT application by uncommenting --> <!-- any one of the following lines. --> <inherits name = 'com.google.gwt.user.theme.clean.Clean'/> <!-- <inherits name = 'com.google.gwt.user.theme.chrome.Chrome'/> --> <!-- <inherits name = 'com.google.gwt.user.theme.dark.Dark'/> --> <!-- Other module inherits --> <!-- Specify the app entry point class. --> <entry-point class = 'com.tutorialspoint.client.HelloWorld'/> <!-- Specify the paths for translatable code --> <source path = 'client'/> <source path = 'shared'/> </module>
步骤 3 - 修改样式表:HelloWorld.css
GWT 插件将创建一个默认样式表文件 war/HelloWorld.css。让我们修改此文件,以使我们的示例保持最简单的理解水平 −
body { text-align: center; font-family: verdana, sans-serif; } h1 { font-size: 2em; font-weight: bold; color: #777777; margin: 40px 0px 70px; text-align: center; }
第 4 步 - 修改主机文件:HelloWorld.html
GWT 插件将创建一个默认 HTML 主机文件 war/HelloWorld.html。让我们修改此文件,以使我们的示例保持最简单的理解水平 −
<html> <head> <title>Hello World</title> <link rel = "stylesheet" href = "HelloWorld.css"/> <script language = "javascript" src = "helloworld/helloworld.nocache.js"> </script> </head> <body> <h1>Hello World</h1> <p>Welcome to first GWT application</p> </body> </html>
您可以在同一个源目录中创建更多静态文件,如 HTML、CSS 或图像,也可以创建更多子目录并移动这些子目录中的文件,然后在应用程序的模块描述符中配置这些子目录。
步骤 5 - 修改入口点:HelloWorld.java
GWT 插件将创建一个默认 Java 文件 src/com.tutorialspoint/HelloWorld.java,该文件为应用程序保留一个入口点。
Let us modify this file to display "Hello,World!"
package com.tutorialspoint.client; import com.google.gwt.core.client.EntryPoint; import com.google.gwt.user.client.Window; public class HelloWorld implements EntryPoint { public void onModuleLoad() { Window.alert("Hello, World!"); } }
您可以在同一个源目录中创建更多 Java 文件来定义入口点或定义辅助例程。
第 6 步 - 编译应用程序
完成所有更改后,就可以编译项目了。使用选项 Google 图标 > GWT 编译项目... 启动 GWT 编译对话框,如下所示 −
保留默认值并单击编译按钮。如果一切顺利,您将在 Eclipse 控制台中看到以下输出
Compiling module com.tutorialspoint.HelloWorld Compiling 6 permutations Compiling permutation 0... Compiling permutation 1... Compiling permutation 2... Compiling permutation 3... Compiling permutation 4... Compiling permutation 5... Compile of permutations succeeded Linking into C:\workspace\HelloWorld\war\helloworld Link succeeded Compilation succeeded -- 33.029s
第 7 步 - 运行应用程序
现在单击 运行应用程序菜单并选择 HelloWorld 应用程序来运行该应用程序。
如果一切正常,您必须看到 Eclipse 中激活的 GWT 开发模式,其中包含如下所示的 URL。双击该 URL 以打开 GWT 应用程序。
由于您正在开发模式下运行应用程序,因此您需要为浏览器安装 GWT 插件。只需按照屏幕上的说明安装插件即可。
如果您已为浏览器设置了 GWT 插件,那么您应该能够看到以下输出
恭喜!您已使用 Google Web Toolkit (GWT) 实现了第一个应用程序。
GWT - 部署应用程序
本教程将向您解释如何创建应用程序 "war" 文件以及如何在 Apache Tomcat Websever 根目录中部署该文件。
如果您理解了这个简单示例,那么您也将能够按照相同的步骤部署复杂的 GWT 应用程序。
让我们使用 Eclipse IDE 和 GWT 插件,并按照以下步骤创建 GWT 应用程序 −
步骤 | 描述 | 1 | 在 com.tutorialspoint 包下创建一个名为 HelloWorld 的项目,如 GWT - 创建应用程序 中所述章节。 |
---|---|
2 | 按照以下说明修改 HelloWorld.gwt.xml、HelloWorld.css、HelloWorld.html 和 HelloWorld.java。保持其余文件不变。 |
3 | 编译并运行应用程序以确保业务逻辑按要求运行。 |
4 | 最后,以 war 文件的形式压缩应用程序 war 文件夹的内容,并将其部署在 Apache Tomcat Web 服务器中。 |
5 | 按照最后一步中的说明,使用适当的 URL 启动您的 Web 应用程序。 |
以下是修改后的模块描述符 src/com.tutorialspoint/HelloWorld.gwt.xml 的内容。
<?xml version = "1.0" encoding = "UTF-8"?> <module rename-to = 'helloworld'> <!-- Inherit the core Web Toolkit stuff. --> <inherits name = 'com.google.gwt.user.User'/> <!-- Inherit the default GWT style sheet. --> <inherits name = 'com.google.gwt.user.theme.clean.Clean'/> <!-- Specify the app entry point class. --> <entry-point class = 'com.tutorialspoint.client.HelloWorld'/> <!-- Specify the paths for translatable code --> <source path = 'client'/> <source path = 'shared'/> </module>
以下是修改后的样式表文件war/HelloWorld.css的内容。
body { text-align: center; font-family: verdana, sans-serif; } h1 { font-size: 2em; font-weight: bold; color: #777777; margin: 40px 0px 70px; text-align: center; }
以下是修改后的 HTML 主机文件 war/HelloWorld.html 的内容。
<html> <head> <title>Hello World</title> <link rel = "stylesheet" href = "HelloWorld.css"/> <script language = "javascript" src = "helloworld/helloworld.nocache.js"> </script> </head> <body> <h1>Hello World</h1> <div id = "gwtContainer"></div> </body> </html>
我对上一个示例的 HTML 做了一些修改。在这里我创建了一个占位符 <div>...</div>,我们将使用入口点 java 类在其中插入一些内容。因此,让我们拥有 Java 文件 src/com.tutorialspoint/HelloWorld.java 的以下内容。
package com.tutorialspoint.client; import com.google.gwt.core.client.EntryPoint; import com.google.gwt.user.client.ui.HTML; import com.google.gwt.user.client.ui.RootPanel; public class HelloWorld implements EntryPoint { public void onModuleLoad() { HTML html = new HTML("<p>Welcome to GWT application</p>"); RootPanel.get("gwtContainer").add(html); } }
我们在这里创建了基本的小部件 HTML,并将其添加到 id="gwtContainer" 的 div 标签内。我们将在接下来的章节中研究不同的 GWT 小部件。
完成所有更改后,让我们像在 GWT - 创建应用程序 一章中所做的那样,在开发模式下编译并运行应用程序。如果您的应用程序一切正常,则将产生以下结果 −
创建 WAR 文件
现在我们的应用程序运行良好,我们准备将其导出为 war 文件。
按照以下步骤 −
进入项目的 war 目录 C:\workspace\HelloWorld\war
选择 war 目录中可用的所有文件和文件夹。
压缩所有选定的文件和文件夹文件夹中的一个名为 HelloWorld.zip 的文件。
将 HelloWorld.zip 重命名为 HelloWorld.war。
部署 WAR 文件
停止 tomcat 服务器。
将 HelloWorld.war 文件复制到 tomcat 安装目录 > webapps 文件夹。
启动 tomcat 服务器。
查看 webapps 目录,应该有一个文件夹 helloworld 被创建。
现在 HelloWorld.war 已成功部署在 Tomcat Webserver 根目录中。
运行应用程序
在 Web 浏览器中输入 URL:http://localhost:8080/HelloWorld 以启动应用程序
服务器名称 (localhost) 和端口 (8080) 可能因您的 tomcat 配置而异。
GWT - 使用 CSS 进行样式设置
GWT 小部件依靠层叠样式表 (CSS) 进行视觉样式设置。默认情况下,每个组件的类名为 gwt-<classname>。
例如,Button 小部件的默认样式为 gwt-Button,类似地,TextBox 小部件的默认样式为 gwt-TextBox。
为了使所有按钮和文本框的字体更大,您可以在应用程序的 CSS 文件中放置以下规则
.gwt-Button { font-size: 150%; } .gwt-TextBox { font-size: 150%; }
默认情况下,浏览器和 GWT 都不会为小部件创建默认的 id 属性。您必须为可以在 CSS 中使用的元素明确创建一个唯一的 id。为了给 id 为 my-button-id 的特定按钮提供更大的字体,您可以在应用程序的 CSS 文件中放入以下规则 −
#my-button-id { font-size: 150%; }
要设置 GWT 小部件的 id,请检索其 DOM 元素,然后按如下方式设置 id 属性 −
Button b = new Button(); DOM.setElementAttribute(b.getElement(), "id", "my-button-id")
CSS 样式 API
有许多 API 可用于处理任何 GWT 小部件的 CSS 设置。以下是一些重要的 API,它们将帮助您使用 GWT 进行日常 Web 编程 −
Sr.No. | API &描述 |
---|---|
1 |
public void setStyleName(java.lang.String style) 此方法将清除所有现有样式,并使用 style 将小部件样式设置为提供的新 CSS 类。 |
2 |
public void addStyleName(java.lang.String style) 此方法将向小部件添加次要或依赖的样式名称。次要样式名称是附加样式名称,因此如果之前已应用任何样式名称,则将保留这些样式名称。 |
3 |
public void removeStyleName(java.lang.String style) 此方法将从小部件中删除给定样式,并保留与小部件关联的任何其他样式。 |
4 |
public java.lang.String getStyleName() 此方法获取对象的所有样式名称,以空格分隔的列表形式显示。 |
5 |
public void setStylePrimaryName(java.lang.String style) 此方法设置对象的主要样式名称并更新所有依赖样式名称。 |
例如,让我们定义两个将应用于文本的新样式 −
.gwt-Big-Text { font-size:150%; } .gwt-Small-Text { font-size:75%; } .gwt-Red-Text { color:red; }
现在您可以使用 setStyleName(Style) 将默认设置更改为新设置。应用以下规则后,文本的字体将变大
txtWidget.setStyleName("gwt-Big-Text");
我们可以在同一个小部件上应用辅助 CSS 规则来更改其颜色,如下所示 −
txtWidget.addStyleName("gwt-Red-Text");
使用上述方法,您可以根据需要添加任意数量的样式以应用于小部件。如果您从按钮小部件中删除第一种样式,则第二种样式仍将保留文本。
txtWidget.removeStyleName("gwt-Big-Text");
主要和次要样式
默认情况下,小部件的主要样式名称将是其小部件类的默认样式名称,例如按钮小部件的gwt-Button。当我们使用 AddStyleName() 方法添加和删除样式名称时,这些样式称为次要样式。
小部件的最终外观由添加到它的所有次要样式的总和加上其主要样式决定。您可以使用setStylePrimaryName(String)方法设置小部件的主要样式。为了说明,假设我们有一个标签小部件。在我们的 CSS 文件中,我们定义了以下规则 −
.MyText { color: blue; } .BigText { font-size: large; } .LoudText { font-weight: bold; }
假设我们希望某个标签小部件始终显示蓝色文本,并且在某些情况下,使用更大的粗体字体来增加强调效果。
我们可以这样做 −
// 设置主要样式 Label someText = new Label(); someText.setStylePrimaryName("MyText"); ... // 稍后,真正吸引用户的注意力 someText.addStyleName("BigText"); someText.addStyleName("LoudText"); ... // 危机结束后 someText.removeStyleName("BigText"); someText.removeStyleName("LoudText");
关联 CSS 文件
有多种方法可以将 CSS 文件与模块关联。现代 GWT 应用程序通常结合使用 CssResource 和 UiBinder。我们在示例中仅使用第一种方法。
在主机 HTML 页面中使用 <link> 标记。
在模块 XML 文件中使用 <stylesheet> 元素。
使用 ClientBundle 中包含的 CssResource。
在 UiBinder 模板中使用内联 <ui:style> 元素。
GWT CSS 示例
此示例将引导您完成在 GWT 小部件上应用不同 CSS 规则的简单步骤。让我们使用 Eclipse IDE 和 GWT 插件,并按照以下步骤创建 GWT 应用程序 −
步骤 | 描述 |
---|---|
1 | 在 com.tutorialspoint 包下创建一个名为 HelloWorld 的项目,如 GWT - 创建应用程序 一章中所述。 |
2 | 修改 HelloWorld.gwt.xml、HelloWorld.css、HelloWorld.html 和 HelloWorld.java,如下所述。其余文件保持不变。 |
3 | 编译并运行应用程序以验证实现逻辑的结果。 |
以下是修改后的模块描述符src/com.tutorialspoint/HelloWorld.gwt.xml的内容。
<?xml version = "1.0" encoding = "UTF-8"?> <module rename-to = 'helloworld'> <!-- Inherit the core Web Toolkit stuff. --> <inherits name = 'com.google.gwt.user.User'/> <!-- Inherit the default GWT style sheet. --> <inherits name = 'com.google.gwt.user.theme.clean.Clean'/> <!-- Specify the app entry point class. --> <entry-point class = 'com.tutorialspoint.client.HelloWorld'/> <!-- Specify the paths for translatable code --> <source path = 'client'/> <source path = 'shared'/> </module>
以下是修改后的样式表文件war/HelloWorld.css的内容。
body { text-align: center; font-family: verdana, sans-serif; } h1 { font-size: 2em; font-weight: bold; color: #777777; margin: 40px 0px 70px; text-align: center; } .gwt-Button { font-size: 150%; font-weight: bold; width:100px; height:100px; } .gwt-Big-Text { font-size:150%; } .gwt-Small-Text { font-size:75%; }
以下是修改后的 HTML 主机文件 war/HelloWorld.html 的内容,用于容纳两个按钮。
<html> <head> <title>Hello World</title> <link rel = "stylesheet" href = "HelloWorld.css"/> <script language = "javascript" src = "helloworld/helloworld.nocache.js"> </script> </head> <body> <div id = "mytext"><h1>Hello, World!</h1></div> <div id = "gwtGreenButton"></div> <div id = "gwtRedButton"></div> </body> </html>
让我们拥有以下 Java 文件 src/com.tutorialspoint/HelloWorld.java 的内容,它将负责在 HTML 中添加两个按钮并应用自定义 CSS 样式。
package com.tutorialspoint.client; import com.google.gwt.core.client.EntryPoint; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.HTML; import com.google.gwt.user.client.ui.RootPanel; public class HelloWorld implements EntryPoint { public void onModuleLoad() { // 添加按钮,单击时字体变大。 Button Btn1 = new Button("Big Text"); Btn1.addClickHandler(new ClickHandler() { public void onClick(ClickEvent event) { RootPanel.get("mytext").setStyleName("gwt-Big-Text"); } }); // 添加按钮,单击时字体变小。 Button Btn2 = new Button("Small Text"); Btn2.addClickHandler(new ClickHandler() { public void onClick(ClickEvent event) { RootPanel.get("mytext").setStyleName("gwt-Small-Text"); } }); RootPanel.get("gwtGreenButton").add(Btn1); RootPanel.get("gwtRedButton").add(Btn2); } }
完成所有更改后,让我们像在 GWT - 创建应用程序 一章中一样,在开发模式下编译并运行应用程序。如果您的应用程序一切正常,这将产生以下结果 −
现在尝试单击显示的两个按钮,并观察"Hello, World!"文本,单击这两个按钮时,文本的字体不断变化。
GWT - 基本小部件
每个用户界面都会考虑以下三个主要方面 −
UI 元素 − 这些是用户最终看到并与之交互的核心视觉元素。GWT 提供了大量广泛使用和常见的元素列表,从基本到复杂,我们将在本教程中介绍。
布局 − 它们定义应如何在屏幕上组织 UI 元素,并为 GUI(图形用户界面)提供最终的外观和感觉。这部分将在布局章节中介绍。
行为 − 这些是用户与 UI 元素交互时发生的事件。这部分将在事件处理章节中介绍。
GWT UI 元素
GWT 库在明确定义的类层次结构中提供类,以创建复杂的基于 Web 的用户界面。此组件层次结构中的所有类均派生自 UIObject 基类,如下所示 −
每个基本 UI 小部件都从 Widget 类继承属性,而 Widget 类又从 UIObject 继承属性。树和菜单将在复杂小部件教程中介绍。
Sr.No. | 小部件 &描述 |
---|---|
1 |
GWT UIObject 类
此小部件包含文本,未使用 <div> 元素将其解释为 HTML,导致其以块布局显示。 |
2 |
GWT 小部件类
此小部件可以包含 HTML 文本并使用 <div> 显示 html 内容元素,使其以块布局显示。 |
基本小部件
以下是一些重要的基本小部件 −
Sr.No. | 小部件 &描述 |
---|---|
1 |
标签
此小部件包含文本,未使用 <div> 元素将其解释为 HTML,导致其以块布局显示。 |
2 |
HTML
此小部件可以包含 HTML 文本并使用 <div> 显示 html 内容元素,使其以块布局显示。 |
3 |
图像
此小部件在给定的 URL 处显示图像。 |
4 |
锚点
此小部件代表一个简单的 <a> 元素。 |
GWT - Form 小部件
Form 表单小部件允许用户输入数据并为他们提供与应用程序交互的功能。每个表单小部件都从 Widget 类继承属性,而 Widget 类又从 UIObject 和 Wigdet 类继承属性。
Sr.No. | 小部件 &描述 |
---|---|
1 |
GWT UIObject 类
此小部件包含文本,未使用 <div> 元素将其解释为 HTML,导致其以块布局显示。 |
2 |
GWT 小部件类
此小部件可以包含 HTML 文本并使用 <div> 显示 html 内容元素,使其以块布局显示。 |
表单小部件
以下是一些重要的表单小部件 −
Sr.No. | 小部件 &描述 |
---|---|
1 |
Button
此小部件表示标准按钮。 |
2 |
PushButton
此小部件表示具有自定义样式的普通按钮。 |
3 |
ToggleButton
此小部件表示一个时尚的状态按钮,允许用户在向上和向下状态之间切换。 |
4 |
CheckBox
此小部件表示一个标准复选框小部件。此类还可用作 RadioButton 的基类。 |
5 |
RadioButton
此小部件表示互斥选择单选按钮小部件。 |
6 |
ListBox
此小部件向用户表示选项列表,可以是列表框或下拉列表。 |
7 |
SuggestBox
此小部件表示一个文本框或文本区域,显示一组与用户输入相匹配的预配置选择。每个 SuggestBox 都与一个 SuggestOracle 相关联。 SuggestOracle 用于根据特定查询字符串提供一组选择。 |
8 |
TextBox
此小部件表示单行文本框。 |
9 |
PasswordTextBox
此小部件表示一个文本框,它在视觉上掩盖其输入以防止窃听。 |
10 |
TextArea
此小部件表示允许输入多行文本的文本框。 |
11 |
RichTextArea
此小部件表示允许复杂样式和格式的富文本编辑器。 |
12 |
FileUpload
此小部件包装 HTML <input type='file'> 元素。 |
13 |
Hidden
此小部件表示 HTML 表单中的隐藏字段。 |
GWT - 复杂小部件
"复杂小部件"允许用户与应用程序进行高级交互。每个复杂小部件都从 Widget 类继承属性,而 Widget 类又从 UIObject 继承属性。
Sr.No. | 小部件 &描述 |
---|---|
1 |
GWT UIObject 类
此小部件包含文本,未使用 <div> 元素将其解释为 HTML,导致其以块布局显示。 |
2 |
GWT 小部件类
此小部件可以包含 HTML 文本并使用 <div> 显示 html 内容元素,使其以块布局显示。 |
复杂小部件
以下是一些重要的复杂小部件 −
Sr.No. | 小部件和说明 |
---|---|
1 |
tree
此小部件表示标准的分层树小部件。该树包含用户可以打开、关闭和选择的 TreeItem 层次结构。 |
2 |
MenuBar
此小部件表示标准菜单栏小部件。菜单栏可以包含任意数量的菜单项,每个菜单项都可以触发命令或打开级联菜单栏。 |
3 |
DatePicker
此小部件表示标准 GWT 日期选择器。 |
4 |
CellTree
此小部件表示树的视图。此小部件仅在标准模式下工作,这要求运行它的 HTML 页面具有显式 <!DOCTYPE>声明。 |
5 |
CellList
此小部件表示单元格的单列列表。 |
6 |
CellTable
此小部件表示支持分页和列的表格视图。 |
7 |
CellBrowser
此小部件表示树的可浏览视图,其中每个级别一次只能打开一个节点。此小部件仅在标准模式下工作,这要求运行它的 HTML 页面具有显式 <!DOCTYPE> 声明。 |
GWT - 布局面板
布局面板可以包含其他小部件。这些面板控制小部件在用户界面上的显示方式。每个面板小部件都从 Panel 类继承属性,而 Panel 类又从 Widget 类继承属性,而 Widget 类又从 UIObject 类继承属性。
Sr.No. | 小部件 &描述 |
---|---|
1 |
GWT UIObject 类
此小部件包含文本,未使用 <div> 元素将其解释为 HTML,导致其以块布局显示。 |
2 |
GWT 小部件类
此小部件可以包含 HTML 文本并使用 <div> 显示 html 内容元素,使其以块布局显示。 |
3 |
GWT 面板类
这是所有面板的抽象基类,面板是可以包含其他小部件的小部件。 |
布局面板
以下是一些重要的布局面板 −
Sr.No. | 小部件 &描述 |
---|---|
1 |
FlowPanel
此小部件表示使用默认 HTML 布局行为格式化其子小部件的面板。 |
2 |
HorizontalPanel
此小部件表示将其所有小部件布置在单个水平列中的面板。 |
3 |
VerticalPanel
此小部件表示一个面板,该面板将所有小部件布置在一个垂直列中。 |
4 |
HorizontalSplitPanel
此小部件表示一个面板,该面板将两个小部件排列在一个水平行中,并允许用户以交互方式更改两个小部件各自专用的宽度比例。必要时,HorizontalSplitPanel 中包含的小部件将自动用滚动条装饰。 |
5 |
VerticalSplitPanel
此小部件表示一个面板,该面板将两个小部件排列在一个垂直列中,并允许用户以交互方式更改两个小部件各自专用的高度比例。必要时,VertialSplitPanel 中包含的小部件将自动用滚动条装饰。 |
6 |
FlexTable
此小部件表示可根据需要创建单元格的灵活表格。它可以是锯齿状的(即每行可以包含不同数量的单元格),并且可以将单个单元格设置为跨越多行或多列。 |
7 |
Grid
此小部件表示一个矩形网格,其单元格内可以包含文本、html 或子小部件。必须将其大小明确调整为所需的行数和列数。 |
8 |
DeckPanel
面板,在"面板"中显示其所有子窗口小部件,一次只能看到一个。它由 TabPanel 使用。 |
9 |
DockPanel
此小部件表示一个面板,其子小部件"停靠"在其外边缘,并允许其最后一个小部件占据其中心的剩余空间。 |
10 |
HTMLPanel
此小部件表示一个包含 HTML 的面板,并且可以将子小部件附加到该 HTML 中已识别的元素。 |
11 |
TabPanel
此小部件表示一个面板,该面板表示一组选项卡式页面,每个页面包含另一个小部件。当用户选择与其关联的各种选项卡时,将显示其子窗口小部件。这些选项卡可以包含任意 HTML。 |
12 |
Composite
此窗口小部件表示一种可以包装另一个窗口小部件的窗口小部件,从而隐藏被包装窗口小部件的方法。当添加到面板时,复合组件的行为与它所包裹的小部件被添加时的行为完全相同。 |
13 |
SimplePanel
此小部件表示仅包含一个小部件的面板的基类。 |
14 |
ScrollPanel
此小部件表示一个简单面板,将其内容包裹在可滚动区域中 |
15 |
FocusPanel
此小部件表示一个简单的面板,使其内容可聚焦,并增加了捕获鼠标和键盘事件的能力。 |
16 |
FormPanel
此小部件表示一个将其内容包装在 HTML <FORM> 中的面板元素。 |
17 |
PopupPanel
此小部件表示一个可以弹出在其他小部件上的面板。它覆盖浏览器的客户区(以及任何先前创建的弹出窗口)。 |
18 |
DialogBox
此小部件表示一种弹出窗口形式,其顶部有一个标题区域,用户可以拖动。与 PopupPanel 不同,调用 PopupPanel.setWidth(String) 和 PopupPanel.setHeight(String) 将设置对话框本身的宽度和高度,即使尚未添加小部件。 |
GWT - 事件处理
GWT 提供类似于 Java AWT 或 SWING 用户界面框架的事件处理程序模型。
侦听器接口定义小部件调用以宣布事件的一个或多个方法。 GWT 提供了与各种可能事件相对应的接口列表。
希望接收特定类型事件的类会实现关联的处理程序接口,然后将对自身的引用传递给小部件以订阅一组事件。
例如,Button 类发布 click 事件,因此您必须编写一个类来实现 ClickHandler 来处理 click 事件。
事件处理程序接口
所有 GWT 事件处理程序都已从 EventHandler 接口扩展,并且每个处理程序只有一个带有单个参数的方法。此参数始终是关联事件类型的对象。每个 event 对象都有许多方法来操作传递的事件对象。例如,对于 click 事件,您必须按如下方式编写处理程序 −
/** * create a custom click handler which will call * onClick method when button is clicked. */ public class MyClickHandler implements ClickHandler { @Override public void onClick(ClickEvent event) { Window.alert("Hello World!"); } }
现在,任何希望接收点击事件的类都将调用 addClickHandler() 来注册事件处理程序,如下所示 −
/** * 创建按钮并附加点击处理程序 */ Button button = new Button("Click Me!"); button.addClickHandler(new MyClickHandler());
每个支持事件类型的小部件都将具有 HandlerRegistration addFooHandler(FooEvent) 形式的方法,其中 Foo 是实际事件,如 Click、Error、KeyPress 等。
以下是重要的 GWT 事件处理程序和相关事件以及处理程序注册方法的列表 −
Sr.No. | 事件接口 | 事件方法 &描述 |
---|---|---|
1 | Before Selection Handler<I> |
void on Before Selection (Before Selection Event<I> event); 在 BeforeSelectionEvent 触发时调用。 |
2 | BlurHandler |
void on Blur(Blur Event event); 在 Blur Event 触发时调用。 |
3 | ChangeHandler |
void on Change(ChangeEvent event); 触发 change 事件时调用。 |
4 | ClickHandler |
void on Click(ClickEvent event); 触发本机 click 事件时调用。 |
5 | CloseHandler<T> |
void on Close(CloseEvent<T> event); 触发 CloseEvent 时调用。 |
6 | Context Menu Handler |
void on Context Menu(Context Menu Event event); 在触发本机上下文菜单事件时调用。 |
7 | Double Click Handler |
void on Double Click(Double Click Event event); 在触发双击事件时调用。 |
8 | Error Handler |
void on Error(Error Event event); 在触发错误事件时调用触发。 |
9 | Focus Handler |
void on Focus(Focus Event event); 触发焦点事件时调用。 |
10 | Form Panel.Submit Complete Handler |
void on Submit Complete(Form Panel.Submit Complete Event event); 表单成功提交时触发。 |
11 | FormPanel.SubmitHandler |
void on Submit(Form Panel.Submit Event event); 表单提交时触发。 |
12 | Key Down Handler |
void on Key Down(Key Down Event event); KeyDownEvent 触发时调用。 |
13 | KeyPressHandler |
void on KeyPress(KeyPressEvent event); KeyPressEvent 触发时调用触发。 |
14 | KeyUpHandler |
void on KeyUp(KeyUpEvent event); 触发 KeyUpEvent 时调用。 |
15 | LoadHandler |
void on Load(LoadEvent event); 触发 LoadEvent 时调用。 |
16 | MouseDownHandler |
void on MouseDown(MouseDownEvent event); 在触发 MouseDown 时调用。 |
17 | MouseMoveHandler |
void on MouseMove(MouseMoveEvent event); 在触发 MouseMoveEvent 时调用。 |
18 | MouseOutHandler |
void on MouseOut(MouseOutEvent event); 在触发 MouseOutEvent 时调用。 |
19 | MouseOverHandler |
void on MouseOver(MouseOverEvent event); 在触发 MouseOverEvent 时调用。 |
20 | MouseUpHandler |
void on MouseUp(MouseUpEvent event); 在触发 MouseUpEvent 时调用。 |
21 | MouseWheelHandler |
void on MouseWheel(MouseWheelEvent event); 在触发 MouseWheelEvent 时调用。 |
22 | ResizeHandler |
void on Resize(ResizeEvent event); 在调整小部件大小时触发。 |
23 | ScrollHandler |
void on Scroll(ScrollEvent event); 在 ScrollEvent 时调用触发。 |
24 | SelectionHandler<I> |
void on Selection(SelectionEvent<I>事件); 在 SelectionEvent 触发时调用。 |
25 | ValueChangeHandler<I> |
void on ValueChange(ValueChangeEvent<I> event); 在 ValueChangeEvent 触发时调用。 |
26 | Window.ClosingHandler |
void on WindowClosing(Window.ClosingEvent event); 在浏览器窗口关闭或导航到其他窗口之前触发站点。 |
27 | Window.ScrollHandler |
void on WindowScroll(Window.ScrollEvent event); 浏览器窗口滚动时触发。 |
事件方法
如前所述,每个处理程序都有一个带有单个参数的方法,该方法保存事件对象,例如 void onClick(ClickEvent event) 或 void onKeyDown(KeyDownEvent event)。ClickEvent 和 KeyDownEvent 等事件对象有几个常用方法,如下所示 −
Sr.No. | 方法和说明 |
---|---|
1 |
protected void dispatch(ClickHandler handler) 此方法仅应由 HandlerManager 调用 |
2 |
DomEvent.Type <FooHandler> getAssociatedType() 此方法返回用于注册 Foo 事件的类型。 |
3 |
static DomEvent.Type<FooHandler> getType() 此方法获取与 Foo 事件关联的事件类型。 |
4 |
public java.lang.Object getSource() 此方法返回最后触发此事件的源。 |
5 |
protected final boolean isLive() 此方法返回事件是否处于活动状态。 |
6 |
protected void kill() 此方法终止事件 |
示例
此示例将通过简单的步骤向您展示 GWT 中 Click 事件和 KeyDown 事件处理的用法。按照以下步骤更新我们在 GWT - 创建应用程序 一章中创建的 GWT 应用程序 −
步骤 | 描述 |
---|---|
1 | 在 com.tutorialspoint 包下创建一个名为 HelloWorld 的项目,如 GWT - 创建应用程序 一章中所述。 |
2 | 修改 HelloWorld.gwt.xml、HelloWorld.css、HelloWorld.html 和 HelloWorld.java,如下所述。其余文件保持不变。 |
3 | 编译并运行应用程序以验证实现逻辑的结果。 |
以下是修改后的模块描述符src/com.tutorialspoint/HelloWorld.gwt.xml的内容。
<?xml version = "1.0" encoding = "UTF-8"?> <module rename-to = 'helloworld'> <!-- Inherit the core Web Toolkit stuff. --> <inherits name = 'com.google.gwt.user.User'/> <!-- Inherit the default GWT style sheet. --> <inherits name = 'com.google.gwt.user.theme.clean.Clean'/> <!-- Specify the app entry point class. --> <entry-point class = 'com.tutorialspoint.client.HelloWorld'/> <!-- Specify the paths for translatable code --> <source path = 'client'/> <source path = 'shared'/> </module>
以下是修改后的样式表文件war/HelloWorld.css的内容。
body { text-align: center; font-family: verdana, sans-serif; } h1 { font-size: 2em; font-weight: bold; color: #777777; margin: 40px 0px 70px; text-align: center; }
以下是修改后的 HTML 主机文件 war/HelloWorld.html 的内容。
<html> <head> <title>Hello World</title> <link rel = "stylesheet" href = "HelloWorld.css"/> <script language = "javascript" src = "helloworld/helloworld.nocache.js"> </script> </head> <body> <h1>Event Handling Demonstration</h1> <div id = "gwtContainer"></div> </body> </html>
让我们来看看 Java 文件 src/com.tutorialspoint/HelloWorld.java 的以下内容,它将演示 GWT 中事件处理的使用。
package com.tutorialspoint.client; import com.google.gwt.core.client.EntryPoint; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.event.dom.client.KeyCodes; import com.google.gwt.event.dom.client.KeyDownEvent; import com.google.gwt.event.dom.client.KeyDownHandler; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.DecoratorPanel; import com.google.gwt.user.client.ui.HasHorizontalAlignment; import com.google.gwt.user.client.ui.RootPanel; import com.google.gwt.user.client.ui.TextBox; import com.google.gwt.user.client.ui.VerticalPanel; public class HelloWorld implements EntryPoint { public void onModuleLoad() { /** * create textbox and attach key down handler */ TextBox textBox = new TextBox(); textBox.addKeyDownHandler(new MyKeyDownHandler()); /* * create button and attach click handler */ Button button = new Button("Click Me!"); button.addClickHandler(new MyClickHandler()); VerticalPanel panel = new VerticalPanel(); panel.setSpacing(10); panel.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER); panel.setSize("300", "100"); panel.add(textBox); panel.add(button); DecoratorPanel decoratorPanel = new DecoratorPanel(); decoratorPanel.add(panel); RootPanel.get("gwtContainer").add(decoratorPanel); } /** * create a custom click handler which will call * onClick method when button is clicked. */ private class MyClickHandler implements ClickHandler { @Override public void onClick(ClickEvent event) { Window.alert("Hello World!"); } } /** * create a custom key down handler which will call * onKeyDown method when a key is down in textbox. */ private class MyKeyDownHandler implements KeyDownHandler { @Override public void onKeyDown(KeyDownEvent event) { if(event.getNativeKeyCode() == KeyCodes.KEY_ENTER){ Window.alert(((TextBox)event.getSource()).getValue()); } } } }
完成所有更改后,让我们像在 GWT - 创建应用程序 一章中一样,在开发模式下编译并运行应用程序。如果您的应用程序一切正常,这将产生以下结果 −
GWT - 自定义小部件
GWT 提供了三种创建自定义用户界面元素的方法。有三种常规策略可供遵循 −
通过扩展 Composite 类创建小部件 − 这是创建自定义小部件最常见、最简单的方法。在这里,您可以使用现有小部件创建具有自定义属性的复合视图。
使用 JAVA 中的 GWT DOM API 创建小部件 − GWT 基本小部件就是以这种方式创建的。但这仍然是一种非常复杂的创建自定义小部件的方法,应谨慎使用。
使用 JavaScript 并使用 JSNI 将其包装在小部件中 − 这通常只应作为最后的手段。考虑到本机方法的跨浏览器影响,它变得非常复杂,并且调试起来也更加困难。
使用复合类创建自定义小部件
此示例将带您完成简单的步骤,展示如何在 GWT 中创建自定义小部件。按照以下步骤更新我们在 GWT - Basic Widgets 一章中创建的 GWT 应用程序 −
在这里,我们将通过扩展 Composite 类来创建自定义小部件,这是构建自定义小部件的最简单方法。
步骤 | 描述 |
---|---|
1 | 在 com.tutorialspoint 包下创建一个名为 HelloWorld 的项目,如 GWT - Create Application 一章中所述。 |
2 | 修改 HelloWorld.gwt.xml, HelloWorld.css、HelloWorld.html 和 HelloWorld.java 如下所述。其余文件保持不变。 |
3 | 编译并运行应用程序以验证实施逻辑的结果。 |
以下是修改后的模块描述符 src/com.tutorialspoint/HelloWorld.gwt.xml 的内容。
<?xml version = "1.0" encoding = "UTF-8"?> <module rename-to = 'helloworld'> <!-- Inherit the core Web Toolkit stuff. --> <inherits name = 'com.google.gwt.user.User'/> <!-- Inherit the default GWT style sheet. --> <inherits name = 'com.google.gwt.user.theme.clean.Clean'/> <!-- Specify the app entry point class. --> <entry-point class = 'com.tutorialspoint.client.HelloWorld'/> <!-- Specify the paths for translatable code --> <source path = 'client'/> <source path = 'shared'/> </module>
以下是修改后的样式表文件war/HelloWorld.css的内容。
body { text-align: center; font-family: verdana, sans-serif; } h1 { font-size: 2em; font-weight: bold; color: #777777; margin: 40px 0px 70px; text-align: center; }
以下是修改后的 HTML 主机文件 war/HelloWorld.html 的内容。
<html> <head> <title>Hello World</title> <link rel = "stylesheet" href = "HelloWorld.css"/> <script language = "javascript" src = "helloworld/helloworld.nocache.js"> </script> </head> <body> <h1>Custom Widget Demonstration</h1> <div id = "gwtContainer"></div> </body> </html>
让我们来看看 Java 文件 src/com.tutorialspoint/HelloWorld.java 的以下内容,它将演示如何创建自定义小部件。
package com.tutorialspoint.client; import com.google.gwt.core.client.EntryPoint; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.user.client.ui.CheckBox; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.HorizontalPanel; import com.google.gwt.user.client.ui.RootPanel; import com.google.gwt.user.client.ui.TextBox; public class HelloWorld implements EntryPoint { /** * A composite of a TextBox and a CheckBox that optionally enables it. */ private static class OptionalTextBox extends Composite implements ClickHandler { private TextBox textBox = new TextBox(); private CheckBox checkBox = new CheckBox(); private boolean enabled = true; public boolean isEnabled() { return enabled; } public void setEnabled(boolean enabled) { this.enabled = enabled; } /** * Style this widget using .optionalTextWidget CSS class.<br/> * Style textbox using .optionalTextBox CSS class.<br/> * Style checkbox using .optionalCheckBox CSS class.<br/> * Constructs an OptionalTextBox with the given caption * on the check. * @param caption the caption to be displayed with the check box */ public OptionalTextBox(String caption) { // 使用垂直面板将复选框放置在文本框上方。 HorizontalPanel panel = new HorizontalPanel(); // panel.setBorderWidth(1); panel.setSpacing(10); panel.add(checkBox); panel.add(textBox); // 所有复合体都必须在其构造函数中调用 initWidget()。 initWidget(panel); //设置整个小部件的样式名称 setStyleName("optionalTextWidget"); //设置文本框的样式名称 textBox.setStyleName("optionalTextBox"); //设置复选框的样式名称 checkBox.setStyleName("optionalCheckBox"); textBox.setWidth("200"); // 设置复选框的标题,并默认选中。 checkBox.setText(caption); checkBox.setValue(enabled); checkBox.addClickHandler(this); enableTextBox(enabled,checkBox.getValue()); } public void onClick(ClickEvent event) { if (event.getSource() == checkBox) { // When the check box is clicked, //update the text box's enabled state. enableTextBox(enabled,checkBox.getValue()); } } private void enableTextBox(boolean enable,boolean isChecked){ enable = (enable && isChecked) || (!enable && !isChecked); textBox.setStyleDependentName("disabled", !enable); textBox.setEnabled(enable); } } public void onModuleLoad() { // 创建一个可选文本框并将其添加到根面板。 OptionalTextBox otb = new OptionalTextBox( "Want to explain the solution?"); otb.setEnabled(true); RootPanel.get().add(otb); } }
完成所有更改后,让我们像在 GWT - 创建应用程序 一章中一样,在开发模式下编译并运行应用程序。如果您的应用程序一切正常,则将产生以下结果 −
您可以注意到以下几点
通过扩展 Composite 小部件创建自定义小部件非常简单。
我们使用 GWT 内置小部件、TextBox 和 CheckBox 创建了一个小部件,从而使用了可重用性的概念。
根据复选框的状态,TextBox 被禁用/启用。我们提供了一个 API 来启用/禁用该控件。
我们通过记录的 CSS 样式公开了内部小部件样式。
GWT - UiBinder
简介
UiBinder 是一个旨在分离用户界面功能和视图的框架。
UiBinder 框架允许开发人员将 gwt 应用程序构建为 HTML 页面,并在其中配置 GWT 小部件。
UiBinder 框架使与更熟悉 XML、HTML 和 CSS 而非 Java 源代码的 UI 设计人员的协作更加容易
UIBinder 提供了一种定义用户界面的声明方式。
UIBinder 将编程逻辑与 UI 分离。
UIBinder 类似于 JSP 与 Servlet。
UiBinder 工作流程
步骤 1 - 创建 UI 声明 XML文件
创建一个基于 XML/HTML 的用户界面声明文件。我们在示例中创建了一个 Login.ui.xml 文件。
<ui:UiBinder xmlns:ui = 'urn:ui:com.google.gwt.uibinder' xmlns:gwt = 'urn:import:com.google.gwt.user.client.ui' xmlns:res = 'urn:with:com.tutorialspoint.client.LoginResources'> <ui:with type = "com.tutorialspoint.client.LoginResources" field = "res"> </ui:with> <gwt:HTMLPanel> ... </gwt:HTMLPanel> </ui:UiBinder>
步骤 2 - 使用 ui:field 进行后续绑定
使用 XML/HTML 元素中的 ui:field 属性将 XML 中的 UI 字段与 JAVA 文件中的 UI 字段关联起来,以便后续绑定。
<gwt:Label ui:field = "completionLabel1" /> <gwt:Label ui:field = "completionLabel2" />
步骤 3 - 创建 UI XML 的 Java 对应项
通过扩展 Composite 小部件创建基于 XML 布局的 Java 对应项。我们在示例中创建了一个 Login.java 文件。
package com.tutorialspoint.client; ... public class Login extends Composite { ... }
第 4 步 - 使用 UiField 注释绑定 Java UI 字段
在 Login.java 中使用 @UiField 注释指定对应的类成员以绑定到 Login.ui.xml 中的基于 XML 的字段
public class Login extends Composite { ... @UiField Label completionLabel1; @UiField Label completionLabel2; ... }
步骤 5 - 使用 UiTemplate 注释将 Java UI 与 UI XML 绑定
指示 GWT 使用 @UiTemplate 注释绑定基于 Java 的组件 Login.java 和基于 XML 的布局 Login.ui.xml
public class Login extends Composite { private static LoginUiBinder uiBinder = GWT.create(LoginUiBinder.class); /* * @UiTemplate is not mandatory but allows multiple XML templates * to be used for the same widget. * Default file loaded will be <class-name>.ui.xml */ @UiTemplate("Login.ui.xml") interface LoginUiBinder extends UiBinder<Widget, Login> { } ... }
第 6 步 - 创建 CSS 文件
创建外部 CSS 文件Login.css 和相当于 css 样式的基于 Java 的资源 LoginResources.java 文件
.blackText { font-family: Arial, Sans-serif; color: #000000; font-size: 11px; text-align: left; } ...
第 7 步 - 为 CSS 文件创建基于 Java 的资源文件
package com.tutorialspoint.client; ... public interface LoginResources extends ClientBundle { public interface MyCss extends CssResource { String blackText(); ... } @Source("Login.css") MyCss style(); }
第 8 步 - 在 Java UI 代码文件中附加 CSS 资源。
使用基于 Java 的小部件类 Login.java 的构造函数附加外部 CSS 文件 Login.css>
public Login() { this.res = GWT.create(LoginResources.class); res.style().ensureInjected(); initWidget(uiBinder.createAndBindUi(this)); }
UIBinder 完整示例
此示例将带您完成一些简单步骤,展示 GWT 中 UIBinder 的使用方法。按照以下步骤更新我们在 GWT - 创建应用程序 一章中创建的 GWT 应用程序 −
步骤 | 描述 |
---|---|
1 | 按照GWT - 创建应用程序一章中的说明,在com.tutorialspoint包下创建一个名为HelloWorld的项目。 |
2 | 按照下面的说明修改HelloWorld.gwt.xml、HelloWorld.css、HelloWorld.html和HelloWorld.java。其余文件保持不变。 |
3 | 编译并运行应用程序以验证实现逻辑的结果。 |
以下是修改后的模块描述符src/com.tutorialspoint/HelloWorld.gwt.xml的内容。
<?xml version = "1.0" encoding = "UTF-8"?> <module rename-to = 'helloworld'> <!-- Inherit the core Web Toolkit stuff. --> <inherits name = 'com.google.gwt.user.User'/> <!-- Inherit the default GWT style sheet. --> <inherits name = 'com.google.gwt.user.theme.clean.Clean'/> <!-- Inherit the UiBinder module. --> <inherits name = "com.google.gwt.uibinder.UiBinder"/> <!-- Specify the app entry point class. --> <entry-point class = 'com.tutorialspoint.client.HelloWorld'/> <!-- Specify the paths for translatable code --> <source path ='client'/> <source path = 'shared'/> </module>
以下是修改后的样式表文件war/HelloWorld.css的内容。
body { text-align: center; font-family: verdana, sans-serif; } h1 { font-size: 2em; font-weight: bold; color: #777777; margin: 40px 0px 70px; text-align: center; }
以下是修改后的 HTML 主机文件 war/HelloWorld.html 的内容。
<html> <head> <title>Hello World</title> <link rel = "stylesheet" href = "HelloWorld.css"/> <script language = "javascript" src = "helloworld/helloworld.nocache.js"> </script> </head> <body> <h1>UiBinder Demonstration</h1> <div id = "gwtContainer"></div> </body> </html>
现在创建一个新的 UiBinder 模板和所有者类(文件 → 新建 → UiBinder)。
选择项目的客户端包,然后将其命名为 Login。保留所有其他默认设置。单击"完成"按钮,插件将创建一个新的 UiBinder 模板和所有者类。
现在在 src/com.tutorialspoint/client 包中创建 Login.css 文件,并将以下内容放入其中
.blackText { font-family: Arial, Sans-serif; color: #000000; font-size: 11px; text-align: left; } .redText { font-family: Arial, Sans-serif; color: #ff0000; font-size: 11px; text-align: left; } .loginButton { border: 1px solid #3399DD; color: #FFFFFF; background: #555555; font-size: 11px; font-weight: bold; margin: 0 5px 0 0; padding: 4px 10px 5px; text-shadow: 0 -1px 0 #3399DD; } .box { border: 1px solid #AACCEE; display: block; font-size: 12px; margin: 0 0 5px; padding: 3px; width: 203px; } .background { background-color: #999999; border: 1px none transparent; color: #000000; font-size: 11px; margin-left: -8px; margin-top: 5px; padding: 6px; }
现在在 src/com.tutorialspoint/client 包中创建 LoginResources.java 文件,并将以下内容放入其中
package com.tutorialspoint.client; import com.google.gwt.resources.client.ClientBundle; import com.google.gwt.resources.client.CssResource; public interface LoginResources extends ClientBundle { /** * Sample CssResource. */ public interface MyCss extends CssResource { String blackText(); String redText(); String loginButton(); String box(); String background(); } @Source("Login.css") MyCss style(); }
将 src/com.tutorialspoint/client 包中的 Login.ui.xml 内容替换为以下内容
<ui:UiBinder xmlns:ui = 'urn:ui:com.google.gwt.uibinder' xmlns:gwt = 'urn:import:com.google.gwt.user.client.ui' xmlns:res = 'urn:with:com.tutorialspoint.client.LoginResources'> <ui:with type = "com.tutorialspoint.client.LoginResources" field = "res"> </ui:with> <gwt:HTMLPanel> <div align = "center"> <gwt:VerticalPanel res:styleName = "style.background"> <gwt:Label text = "Login" res:styleName = "style.blackText" /> <gwt:TextBox ui:field="loginBox" res:styleName = "style.box" /> <gwt:Label text = "Password" res:styleName = "style.blackText" /> <gwt:PasswordTextBox ui:field = "passwordBox" res:styleName = "style.box" /> <gwt:HorizontalPanel verticalAlignment = "middle"> <gwt:Button ui:field = "buttonSubmit" text="Submit" res:styleName = "style.loginButton" /> <gwt:CheckBox ui:field = "myCheckBox" /> <gwt:Label ui:field = "myLabel" text = "Remember me" res:styleName = "style.blackText" /> </gwt:HorizontalPanel> <gwt:Label ui:field = "completionLabel1" res:styleName = "style.blackText" /> <gwt:Label ui:field = "completionLabel2" res:styleName = "style.blackText" /> </gwt:VerticalPanel> </div> </gwt:HTMLPanel> </ui:UiBinder>
将 src/com.tutorialspoint/client 包中的 Login.java 内容替换为以下内容
package com.tutorialspoint.client; import com.google.gwt.core.client.GWT; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.logical.shared.ValueChangeEvent; import com.google.gwt.uibinder.client.UiBinder; import com.google.gwt.uibinder.client.UiField; import com.google.gwt.uibinder.client.UiHandler; import com.google.gwt.uibinder.client.UiTemplate; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.TextBox; import com.google.gwt.user.client.ui.Widget; public class Login extends Composite { private static LoginUiBinder uiBinder = GWT.create(LoginUiBinder.class); /* * @UiTemplate is not mandatory but allows multiple XML templates * to be used for the same widget. * Default file loaded will be <class-name>.ui.xml */ @UiTemplate("Login.ui.xml") interface LoginUiBinder extends UiBinder<Widget, Login> { } @UiField(provided = true) final LoginResources res; public Login() { this.res = GWT.create(LoginResources.class); res.style().ensureInjected(); initWidget(uiBinder.createAndBindUi(this)); } @UiField TextBox loginBox; @UiField TextBox passwordBox; @UiField Label completionLabel1; @UiField Label completionLabel2; private Boolean tooShort = false; /* * Method name is not relevant, the binding is done according to the class * of the parameter. */ @UiHandler("buttonSubmit") void doClickSubmit(ClickEvent event) { if (!tooShort) { Window.alert("Login Successful!"); } else { Window.alert("Login or Password is too short!"); } } @UiHandler("loginBox") void handleLoginChange(ValueChangeEvent<String> event) { if (event.getValue().length() < 6) { completionLabel1.setText("Login too short (Size must be > 6)"); tooShort = true; } else { tooShort = false; completionLabel1.setText(""); } } @UiHandler("passwordBox") void handlePasswordChange(ValueChangeEvent<String> event) { if (event.getValue().length() < 6) { tooShort = true; completionLabel2.setText("Password too short (Size must be > 6)"); } else { tooShort = false; completionLabel2.setText(""); } } }
让我们来看看 Java 文件 src/com.tutorialspoint/HelloWorld.java 的以下内容,它将演示 UiBinder 的使用。
package com.tutorialspoint.client; import com.google.gwt.core.client.EntryPoint; import com.google.gwt.user.client.ui.RootPanel; public class HelloWorld implements EntryPoint { public void onModuleLoad() { RootPanel.get().add(new Login()); } }
完成所有更改后,让我们像在 GWT - 创建应用程序 一章中一样,在开发模式下编译并运行应用程序。如果您的应用程序一切正常,这将产生以下结果 −
GWT - RPC 通信
基于 GWT 的应用程序通常由客户端模块和服务器端模块组成。客户端代码在浏览器中运行,服务器端代码在 Web 服务器中运行。客户端代码必须通过网络发出 HTTP 请求才能访问服务器端数据。
RPC(远程过程调用)是 GWT 使用的机制,客户端代码可以直接执行服务器端方法。
GWT RPC 基于 servlet。
GWT RPC 是异步的,客户端在通信过程中不会被阻止。
使用 GWT RPC,Java 对象可以直接在客户端和服务器之间发送(由 GWT 框架自动序列化)。
服务器端 servlet 称为服务。
从客户端代码调用服务器端 servlet 的方法的远程过程调用称为调用服务。
GWT RPC组件
以下是 GWT RPC 通信机制中使用的三个组件
- 在服务器上运行的远程服务(服务器端 servlet)。
- 用于调用该服务的客户端代码。
- 将在客户端和服务器之间传递的 Java 数据对象。
GWT 客户端和服务器都会自动序列化和反序列化数据,因此开发人员无需序列化/反序列化对象,并且数据对象可以通过 HTTP 传输。
下图显示了 RPC 架构。
要开始使用 RPC,我们需要遵循 GWT 约定。
RPC 通信工作流
步骤 1 - 创建可序列化的模型类
在客户端定义一个可序列化的 Java 模型对象。
public class Message implements Serializable { ... private String message; public Message(){}; public void setMessage(String message) { this.message = message; } ... }
步骤 2 - 创建服务接口
在客户端定义服务接口,扩展 RemoteService 并列出所有服务方法。
使用注释 @RemoteServiceRelativePath 将服务与远程 servlet 相对于模块基本 URL 的默认路径进行映射。
@RemoteServiceRelativePath("message") public interface MessageService extends RemoteService { Message getMessage(String input); }
步骤 3 - 创建异步服务接口
在客户端定义服务异步接口(与上述服务位于同一位置),该接口将在 GWT 客户端代码中使用。
public interface MessageServiceAsync { void getMessage(String input, AsyncCallback<Message> callback); }
步骤 4 - 创建服务实现 Servlet 类
在服务器端实现接口,该类应扩展 RemoteServiceServlet 类。
public class MessageServiceImpl extends RemoteServiceServlet implements MessageService{ ... public Message getMessage(String input) { String messageString = "Hello " + input + "!"; Message message = new Message(); message.setMessage(messageString); return message; } }
步骤 5 - 更新 Web.xml 以包含 Servlet 声明
编辑 Web 应用程序部署描述符 (web.xml) 以包含 MessageServiceImpl Servlet 声明。
<web-app> ... <servlet> <servlet-name>messageServiceImpl</servlet-name> <servlet-class>com.tutorialspoint.server.MessageServiceImpl </servlet-class> </servlet> <servlet-mapping> <servlet-name>messageServiceImpl</servlet-name> <url-pattern>/helloworld/message</url-pattern> </servlet-mapping> </web-app>
第 6 步 - 在应用程序代码中进行远程过程调用
创建服务代理类。
MessageServiceAsync messageService = GWT.create(MessageService.class);
创建 AsyncCallback Handler 来处理 RPC 回调,服务器通过该回调将消息返回给客户端
class MessageCallBack implements AsyncCallback<Message> { @Override public void onFailure(Throwable caught) { Window.alert("Unable to obtain server response: " + caught.getMessage()); } @Override public void onSuccess(Message result) { Window.alert(result.getMessage()); } }
当用户与 UI 交互时调用远程服务
public class HelloWorld implements EntryPoint { ... public void onModuleLoad() { ... buttonMessage.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { messageService.getMessage(txtName.getValue(), new MessageCallBack()); } }); ... } }
RPC 通信完整示例
此示例将带您完成一些简单的步骤,展示 GWT 中的 RPC 通信示例。按照以下步骤更新我们在 GWT - 创建应用程序 一章中创建的 GWT 应用程序 −
步骤 | 描述 |
---|---|
1 | 在 com.tutorialspoint 包下创建一个名为 HelloWorld 的项目,如 GWT - 创建应用程序 一章中所述。 |
2 | 修改 HelloWorld.gwt.xml、HelloWorld.css、HelloWorld.html 和 HelloWorld.java,如下所述。其余文件保持不变。 |
3 | 编译并运行应用程序以验证实现逻辑的结果。 |
以下是修改后的模块描述符src/com.tutorialspoint/HelloWorld.gwt.xml的内容。
<?xml version = "1.0" encoding = "UTF-8"?> <module rename-to = 'helloworld'> <!-- Inherit the core Web Toolkit stuff. --> <inherits name = 'com.google.gwt.user.User'/> <!-- Inherit the default GWT style sheet. --> <inherits name = 'com.google.gwt.user.theme.clean.Clean'/> <!-- Inherit the UiBinder module. --> <inherits name = "com.google.gwt.uibinder.UiBinder"/> <!-- Specify the app entry point class. --> <entry-point class = 'com.tutorialspoint.client.HelloWorld'/> <!-- Specify the paths for translatable code --> <source path = 'client'/> <source path = 'shared'/> </module>
以下是修改后的样式表文件war/HelloWorld.css的内容。
body { text-align: center; font-family: verdana, sans-serif; } h1 { font-size: 2em; font-weight: bold; color: #777777; margin: 40px 0px 70px; text-align: center; }
以下是修改后的 HTML 主机文件 war/HelloWorld.html 的内容。
<html> <head> <title>Hello World</title> <link rel = "stylesheet" href = "HelloWorld.css"/> <script language = "javascript" src = "helloworld/helloworld.nocache.js"> </script> </head> <body> <h1>RPC Communication Demonstration</h1> <div id = "gwtContainer"></div> </body> </html>
现在在 src/com.tutorialspoint/client 包中创建 Message.java 文件并将以下内容放入其中
package com.tutorialspoint.client; import java.io.Serializable; public class Message implements Serializable { private static final long serialVersionUID = 1L; private String message; public Message(){}; public void setMessage(String message) { this.message = message; } public String getMessage() { return message; } }
现在在 src/com.tutorialspoint/client 包中创建 MessageService.java 文件,并将以下内容放入其中
package com.tutorialspoint.client; import com.google.gwt.user.client.rpc.RemoteService; import com.google.gwt.user.client.rpc.RemoteServiceRelativePath; @RemoteServiceRelativePath("message") public interface MessageService extends RemoteService { Message getMessage(String input); }
现在在 src/com.tutorialspoint/client 包中创建 MessageServiceAsync.java 文件,并将以下内容放入其中
package com.tutorialspoint.client; import com.google.gwt.user.client.rpc.AsyncCallback; public interface MessageServiceAsync { void getMessage(String input, AsyncCallback<Message> callback); }
现在在 src/com.tutorialspoint/server 包中创建 MessageServiceImpl.java 文件,并将以下内容放入其中
package com.tutorialspoint.server; import com.google.gwt.user.server.rpc.RemoteServiceServlet; import com.tutorialspoint.client.Message; import com.tutorialspoint.client.MessageService; public class MessageServiceImpl extends RemoteServiceServlet implements MessageService{ private static final long serialVersionUID = 1L; public Message getMessage(String input) { String messageString = "Hello " + input + "!"; Message message = new Message(); message.setMessage(messageString); return message; } }
更新已修改的 Web 应用程序部署描述符 war/WEB-INF/web.xml 的内容以包含 MessageServiceImpl Servlet 声明。
<?xml version = "1.0" encoding = "UTF-8"?> <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd"> <web-app> <!-- Default page to serve --> <welcome-file-list> <welcome-file>HelloWorld.html</welcome-file> </welcome-file-list> <servlet> <servlet-name>messageServiceImpl</servlet-name> <servlet-class>com.tutorialspoint.server.MessageServiceImpl </servlet-class> </servlet> <servlet-mapping> <servlet-name>messageServiceImpl</servlet-name> <url-pattern>/helloworld/message</url-pattern> </servlet-mapping> </web-app>
将 src/com.tutorialspoint/client 包中的 HelloWorld.java 内容替换为以下内容
package com.tutorialspoint.client; import com.google.gwt.core.client.EntryPoint; import com.google.gwt.core.client.GWT; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.event.dom.client.KeyCodes; import com.google.gwt.event.dom.client.KeyUpEvent; import com.google.gwt.event.dom.client.KeyUpHandler; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.DecoratorPanel; import com.google.gwt.user.client.ui.HasHorizontalAlignment; import com.google.gwt.user.client.ui.HorizontalPanel; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.RootPanel; import com.google.gwt.user.client.ui.TextBox; import com.google.gwt.user.client.ui.VerticalPanel; public class HelloWorld implements EntryPoint { private MessageServiceAsync messageService = GWT.create(MessageService.class); private class MessageCallBack implements AsyncCallback<Message> { @Override public void onFailure(Throwable caught) { /* 发生服务器端错误 */ Window.alert("Unable to obtain server response: " + caught.getMessage()); } @Override public void onSuccess(Message result) { /* 服务器返回结果,向用户显示消息 */ Window.alert(result.getMessage()); } } public void onModuleLoad() { /*create UI */ final TextBox txtName = new TextBox(); txtName.setWidth("200"); txtName.addKeyUpHandler(new KeyUpHandler() { @Override public void onKeyUp(KeyUpEvent event) { if(event.getNativeKeyCode() == KeyCodes.KEY_ENTER){ /* 远程调用服务器来获取消息 */ messageService.getMessage(txtName.getValue(), new MessageCallBack()); } } }); Label lblName = new Label("Enter your name: "); Button buttonMessage = new Button("Click Me!"); buttonMessage.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { /* 远程调用服务器来获取消息 */ messageService.getMessage(txtName.getValue(), new MessageCallBack()); } }); HorizontalPanel hPanel = new HorizontalPanel(); hPanel.add(lblName); hPanel.add(txtName); hPanel.setCellWidth(lblName, "130"); VerticalPanel vPanel = new VerticalPanel(); vPanel.setSpacing(10); vPanel.add(hPanel); vPanel.add(buttonMessage); vPanel.setCellHorizontalAlignment(buttonMessage, HasHorizontalAlignment.ALIGN_RIGHT); DecoratorPanel panel = new DecoratorPanel(); panel.add(vPanel); // 将小部件添加到根面板。 RootPanel.get("gwtContainer").add(panel); } }
完成所有更改后,让我们像在 GWT - 创建应用程序 一章中一样,在开发模式下编译并运行应用程序。如果您的应用程序一切正常,这将产生以下结果 −
GWT - JUnit 集成
GWT 使用 JUnit 测试框架为客户端代码的自动测试提供了出色的支持。在本文中,我们将演示 GWT 和 JUNIT 集成。
下载 Junit 存档
JUnit 官方网站 − https://www.junit.org
下载 Junit-4.10.jar
操作系统 | 存档名称 |
---|---|
Windows | junit4.10.jar |
Linux | junit4.10.jar |
Mac | junit4.10.jar |
将下载的 jar 文件存储到计算机上的某个位置。我们将其存储在 C:/ > JUNIT
找到 GWT 安装文件夹
OS | GWT 安装文件夹 |
---|---|
Windows | C:\GWT\gwt-2.1.0 |
Linux | /usr/local/GWT/gwt-2.1.0 |
Mac | /Library/GWT/gwt-2.1.0 |
GWTTestCase 类
GWT 提供了 GWTTestCase 基类,该基类提供 JUnit 集成。运行在 JUnit 下扩展 GWTTestCase 的编译类将启动 HtmlUnit 浏览器,该浏览器用于在测试执行期间模拟应用程序行为。
GWTTestCase 是从 JUnit 的 TestCase 派生的类,可以使用 JUnit TestRunner 运行。
使用 webAppCreator
GWT 提供了一个特殊的命令行工具 webAppCreator,它可以为我们生成一个启动测试用例,以及用于在开发模式和生产模式下进行测试的 ant 目标和 eclipse 启动配置。
打开命令提示符并转到 C:\ > GWT_WORKSPACE > 您想要在其中创建具有测试支持的新项目。运行以下命令
C:\GWT_WORKSPACE>C:\GWT\gwt-2.1.0\webAppCreator -out HelloWorld -junit C:\JUNIT\junit-4.10.jar com.tutorialspoint.HelloWorld
值得注意的点
- 我们正在执行 webAppCreator 命令行实用程序。
- HelloWorld 是要创建的项目的名称
- -junit 选项指示 webAppCreator 向项目添加 junit 支持
- com.tutorialspoint.HelloWorld 是模块的名称
验证输出。
Created directory HelloWorld\src Created directory HelloWorld\war Created directory HelloWorld\war\WEB-INF Created directory HelloWorld\war\WEB-INF\lib Created directory HelloWorld\src\com utorialspoint Created directory HelloWorld\src\com utorialspoint\client Created directory HelloWorld\src\com utorialspoint\server Created directory HelloWorld\src\com utorialspoint\shared Created directory HelloWorld est\com utorialspoint Created directory HelloWorld est\com utorialspoint\client Created file HelloWorld\src\com utorialspoint\HelloWorld.gwt.xml Created file HelloWorld\war\HelloWorld.html Created file HelloWorld\war\HelloWorld.css Created file HelloWorld\war\WEB-INF\web.xml Created file HelloWorld\src\com utorialspoint\client\HelloWorld.java Created file HelloWorld\src\com utorialspoint\client\GreetingService.java Created file HelloWorld\src\com utorialspoint\client\GreetingServiceAsync.java Created file HelloWorld\src\com utorialspoint\server\GreetingServiceImpl.java Created file HelloWorld\src\com utorialspoint\shared\FieldVerifier.java Created file HelloWorld\build.xml Created file HelloWorld\README.txt Created file HelloWorld est\com utorialspoint\HelloWorldJUnit.gwt.xml Created file HelloWorld est\com utorialspoint\client\HelloWorldTest.java Created file HelloWorld\.project Created file HelloWorld\.classpath Created file HelloWorld\HelloWorld.launch Created file HelloWorld\HelloWorldTest-dev.launch Created file HelloWorld\HelloWorldTest-prod.launch
了解测试类:HelloWorldTest.java
package com.tutorialspoint.client; import com.tutorialspoint.shared.FieldVerifier; import com.google.gwt.core.client.GWT; import com.google.gwt.junit.client.GWTTestCase; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.rpc.ServiceDefTarget; /** * GWT JUnit 测试必须扩展 GWTTestCase。 */ public class HelloWorldTest extends GWTTestCase { /** * 必须引用提供此类的有效模块。 */ public String getModuleName() { return "com.tutorialspoint.HelloWorldJUnit"; } /** * 测试 FieldVerifier。 */ public void testFieldVerifier() { assertFalse(FieldVerifier.isValidName(null)); assertFalse(FieldVerifier.isValidName("")); assertFalse(FieldVerifier.isValidName("a")); assertFalse(FieldVerifier.isValidName("ab")); assertFalse(FieldVerifier.isValidName("abc")); assertTrue(FieldVerifier.isValidName("abcd")); } /** * 此测试将使用greetServer向服务器发送请求 * GreetingService 中的方法并验证响应。 */ public void testGreetingService() { /* 创建我们将要测试的服务。 */ GreetingServiceAsync greetingService = GWT.create(GreetingService.class); ServiceDefTarget target = (ServiceDefTarget) greetingService; target.setServiceEntryPoint(GWT.getModuleBaseURL() + "helloworld/greet"); /* since RPC calls are asynchronous, we will need to wait for a response after this test method returns. This line tells the test runner to wait up to 10 seconds before timing out. */ delayTestFinish(10000); /* 向服务器发送请求。 */ greetingService.greetServer("GWT User", new AsyncCallback<String>() { public void onFailure(Throwable caught) { /* 请求导致意外错误。 */ fail("Request failure: " + caught.getMessage()); } public void onSuccess(String result) { /* 验证响应是否正确。 */ assertTrue(result.startsWith("Hello, GWT User!")); /* now that we have received a response, we need to tell the test runner that the test is complete. You must call finishTest() after an asynchronous test finishes successfully, or the test will time out.*/ finishTest(); } }); } }
值得注意的要点
Sr.No. | 说明 |
---|---|
1 | HelloWorldTest 类是在 HelloWorld/test 目录下的 com.tutorialspoint.client 包中生成的。 |
2 | HelloWorldTest 类将包含 HelloWorld 的单元测试用例。 |
3 | HelloWorldTest 类扩展了 com.google.gwt.junit.client 包中的 GWTTestCase 类。 |
4 | HelloWorldTest 类有一个抽象方法 (getModuleName),该方法必须返回 GWT 模块的名称。对于 HelloWorld,此名称为 com.tutorialspoint.HelloWorldJUnit。 |
5 | HelloWorldTest 类由两个示例测试用例 testFieldVerifier、testSimple 生成。我们添加了 testGreetingService。 |
6 | 这些方法使用它从 JUnit Assert 类继承的众多 assert* 函数之一,该类是 GWTTestCase 的祖先。 |
7 | assertTrue(boolean) 函数断言传入的布尔参数的计算结果为 true。如果不是,则在 JUnit 中运行时测试将失败。 |
GWT - JUnit 集成完整示例
此示例将带您完成简单的步骤,展示 GWT 中 JUnit 集成的示例。
按照以下步骤更新我们上面创建的 GWT 应用程序 −
步骤 | 描述 |
---|---|
1 | 使用导入现有项目向导 (文件 → 导入 → 常规 → 将现有项目放入工作区) 在 eclipse 中导入名为 HelloWorld 的项目。 |
2 | 按照以下说明修改 HelloWorld.gwt.xml、HelloWorld.css、HelloWorld.html 和 HelloWorld.java。保持其余文件不变。 |
3 | 编译并运行应用程序以验证实施逻辑的结果。 |
以下是 eclipse 中的项目结构。
以下是修改后的模块描述符 src/com.tutorialspoint/HelloWorld.gwt.xml 的内容。
<?xml version = "1.0" encoding = "UTF-8"?> <module rename-to = 'helloworld'> <!-- Inherit the core Web Toolkit stuff. --> <inherits name = 'com.google.gwt.user.User'/> <!-- Inherit the default GWT style sheet. --> <inherits name = 'com.google.gwt.user.theme.clean.Clean'/> <!-- Inherit the UiBinder module. --> <inherits name = "com.google.gwt.uibinder.UiBinder"/> <!-- Specify the app entry point class. --> <entry-point class = 'com.tutorialspoint.client.HelloWorld'/> <!-- Specify the paths for translatable code --> <source path = 'client'/> <source path = 'shared'/> </module>
以下是修改后的样式表文件war/HelloWorld.css的内容。
body { text-align: center; font-family: verdana, sans-serif; } h1 { font-size: 2em; font-weight: bold; color: #777777; margin: 40px 0px 70px; text-align: center; }
以下是修改后的 HTML 主机文件 war/HelloWorld.html 的内容。
<html> <head> <title>Hello World</title> <link rel = "stylesheet" href = "HelloWorld.css"/> <script language = "javascript" src = "helloworld/helloworld.nocache.js"> </script> </head> <body> <h1>JUnit Integration Demonstration</h1> <div id = "gwtContainer"></div> </body> </html>
将 src/com.tutorialspoint/client 包中的 HelloWorld.java 内容替换为以下内容
package com.tutorialspoint.client; import com.google.gwt.core.client.EntryPoint; import com.google.gwt.core.client.GWT; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.event.dom.client.KeyCodes; import com.google.gwt.event.dom.client.KeyUpEvent; import com.google.gwt.event.dom.client.KeyUpHandler; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.DecoratorPanel; import com.google.gwt.user.client.ui.HasHorizontalAlignment; import com.google.gwt.user.client.ui.HorizontalPanel; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.RootPanel; import com.google.gwt.user.client.ui.TextBox; import com.google.gwt.user.client.ui.VerticalPanel; public class HelloWorld implements EntryPoint { public void onModuleLoad() { /*create UI */ final TextBox txtName = new TextBox(); txtName.setWidth("200"); txtName.addKeyUpHandler(new KeyUpHandler() { @Override public void onKeyUp(KeyUpEvent event) { if(event.getNativeKeyCode() == KeyCodes.KEY_ENTER){ Window.alert(getGreeting(txtName.getValue())); } } }); Label lblName = new Label("Enter your name: "); Button buttonMessage = new Button("Click Me!"); buttonMessage.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { Window.alert(getGreeting(txtName.getValue())); } }); HorizontalPanel hPanel = new HorizontalPanel(); hPanel.add(lblName); hPanel.add(txtName); hPanel.setCellWidth(lblName, "130"); VerticalPanel vPanel = new VerticalPanel(); vPanel.setSpacing(10); vPanel.add(hPanel); vPanel.add(buttonMessage); vPanel.setCellHorizontalAlignment(buttonMessage, HasHorizontalAlignment.ALIGN_RIGHT); DecoratorPanel panel = new DecoratorPanel(); panel.add(vPanel); // 将小部件添加到根面板。 RootPanel.get("gwtContainer").add(panel); } public String getGreeting(String name){ return "Hello "+name+"!"; } }
将 test/com.tutorialspoint/client 包中的 HelloWorldTest.java 内容替换为以下内容
package com.tutorialspoint.client; import com.tutorialspoint.shared.FieldVerifier; import com.google.gwt.core.client.GWT; import com.google.gwt.junit.client.GWTTestCase; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.rpc.ServiceDefTarget; /** * GWT JUnit 测试必须扩展 GWTTestCase。 */ public class HelloWorldTest extends GWTTestCase { /** * 必须引用提供此类的有效模块。 */ public String getModuleName() { return "com.tutorialspoint.HelloWorldJUnit"; } /** * 测试 FieldVerifier。 */ public void testFieldVerifier() { assertFalse(FieldVerifier.isValidName(null)); assertFalse(FieldVerifier.isValidName("")); assertFalse(FieldVerifier.isValidName("a")); assertFalse(FieldVerifier.isValidName("ab")); assertFalse(FieldVerifier.isValidName("abc")); assertTrue(FieldVerifier.isValidName("abcd")); } /** * 此测试将使用greetServer向服务器发送请求 * GreetingService 中的方法并验证响应。 */ public void testGreetingService() { /* 创建我们将要测试的服务。 */ GreetingServiceAsync greetingService = GWT.create(GreetingService.class); ServiceDefTarget target = (ServiceDefTarget) greetingService; target.setServiceEntryPoint(GWT.getModuleBaseURL() + "helloworld/greet"); /* since RPC calls are asynchronous, we will need to wait for a response after this test method returns. This line tells the test runner to wait up to 10 seconds before timing out. */ delayTestFinish(10000); /* 向服务器发送请求。 */ greetingService.greetServer("GWT User", new AsyncCallback<String>() { public void onFailure(Throwable caught) { /* 请求导致意外错误。 */ fail("Request failure: " + caught.getMessage()); } public void onSuccess(String result) { /* 验证响应是否正确。 */ assertTrue(result.startsWith("Hello, GWT User!")); /* now that we have received a response, we need to tell the test runner that the test is complete. You must call finishTest() after an asynchronous test finishes successfully, or the test will time out.*/ finishTest(); } }); /** * 测试 getGreeting 方法。 */ public void testGetGreeting() { HelloWorld helloWorld = new HelloWorld(); String name = "Robert"; String expectedGreeting = "Hello "+name+"!"; assertEquals(expectedGreeting,helloWorld.getGreeting(name)); } } }
使用生成的启动配置在 Eclipse 中运行测试用例
我们将使用 webAppCreator 为开发模式和生产模式生成的启动配置在 Eclipse 中运行单元测试。
在开发模式下运行 JUnit 测试
- 从 Eclipse 菜单栏中选择"运行"→运行配置...
- 在 JUnit 部分下,选择 HelloWorldTest-dev
- 要保存对参数的更改,请按应用
- 要运行测试,请按运行
如果您的应用程序一切正常,这将产生以下结果 −
在生产模式下运行 JUnit 测试
- 从 Eclipse 菜单栏中,选择运行 →运行配置...
- 在 JUnit 部分下,选择 HelloWorldTest-prod
- 要保存对参数的更改,请按应用
- 要运行测试,请按运行
如果您的应用程序一切正常,这将产生以下结果 −
GWT - 调试应用程序
GWT 提供了出色的客户端和服务器端代码调试功能。
在开发模式下,GWT 应用程序基于 Java 代码,不会转换为 JavaScript。
当应用程序在开发模式下运行时,Java 虚拟机 (JVM) 实际上是将应用程序代码作为已编译的 Java 字节码执行,并使用 GWT 功能连接到浏览器窗口。
GWT 使用基于浏览器的插件连接到 JVM。
因此,开发人员可以自由使用任何基于 Java 的 IDE 来调试客户端 GWT 代码以及服务器端代码。
在本文中,我们将演示使用 Eclipse 调试 GWT 客户端代码的用法。我们将执行以下任务 −
- 在代码中设置断点并在 BreakPoint Explorer 中查看它们。
- 在调试期间逐行执行代码。
- 查看变量的值。
- 检查所有变量的值。
- 检查表达式的值。
- 显示挂起线程的堆栈框架。
调试示例
此示例将带您完成简单的步骤来演示如何调试 GWT 应用程序。按照以下步骤更新我们在 GWT - 创建应用程序 一章中创建的 GWT 应用程序 −
步骤 | 描述 |
---|---|
1 | 在 com.tutorialspoint 包下创建一个名为 HelloWorld 的项目,如 GWT - 创建应用程序 一章中所述。 |
2 | 修改 HelloWorld.gwt.xml、HelloWorld.css、HelloWorld.html 和 HelloWorld.java,如下所述。其余文件保持不变。 |
3 | 编译并运行应用程序以验证实现逻辑的结果。 |
以下是修改后的模块描述符src/com.tutorialspoint/HelloWorld.gwt.xml的内容。
<?xml version = "1.0" encoding = "UTF-8"?> <module rename-to = 'helloworld'> <!-- Inherit the core Web Toolkit stuff. --> <inherits name = 'com.google.gwt.user.User'/> <!-- Inherit the default GWT style sheet. --> <inherits name = 'com.google.gwt.user.theme.clean.Clean'/> <!-- Specify the app entry point class. --> <entry-point class = 'com.tutorialspoint.client.HelloWorld'/> <!-- Specify the paths for translatable code --> <source path = 'client'/> <source path = 'shared'/> </module>
以下是修改后的样式表文件war/HelloWorld.css的内容。
body { text-align: center; font-family: verdana, sans-serif; } h1 { font-size: 2em; font-weight: bold; color: #777777; margin: 40px 0px 70px; text-align: center; } .gwt-Label{ font-size: 150%; font-weight: bold; color:red; padding:5px; margin:5px; }
以下是修改后的 HTML 主机文件 war/HelloWorld.html 的内容,用于容纳两个按钮。
<html> <head> <title>Hello World</title> <link rel = "stylesheet" href = "HelloWorld.css"/> <script language = "javascript" src = "helloworld/helloworld.nocache.js"> </script> </head> <body> <h1>Debugging Application Demonstration</h1> <div id = "gwtContainer"></div> </body> </html>
让我们获得 Java 文件 src/com.tutorialspoint/HelloWorld.java 的以下内容,我们将使用它来演示 GWT 代码的调试功能。
package com.tutorialspoint.client; import com.google.gwt.core.client.EntryPoint; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.event.dom.client.KeyCodes; import com.google.gwt.event.dom.client.KeyUpEvent; import com.google.gwt.event.dom.client.KeyUpHandler; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.DecoratorPanel; import com.google.gwt.user.client.ui.HasHorizontalAlignment; import com.google.gwt.user.client.ui.HorizontalPanel; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.RootPanel; import com.google.gwt.user.client.ui.TextBox; import com.google.gwt.user.client.ui.VerticalPanel; public class HelloWorld implements EntryPoint { public void onModuleLoad() { /*create UI */ final TextBox txtName = new TextBox(); txtName.setWidth("200"); txtName.addKeyUpHandler(new KeyUpHandler() { @Override public void onKeyUp(KeyUpEvent event) { if(event.getNativeKeyCode() == KeyCodes.KEY_ENTER){ Window.alert(getGreeting(txtName.getValue())); } } }); Label lblName = new Label("Enter your name: "); Button buttonMessage = new Button("Click Me!"); buttonMessage.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { Window.alert(getGreeting(txtName.getValue())); }}); HorizontalPanel hPanel = new HorizontalPanel(); hPanel.add(lblName); hPanel.add(txtName); hPanel.setCellWidth(lblName, "130"); VerticalPanel vPanel = new VerticalPanel(); vPanel.setSpacing(10); vPanel.add(hPanel); vPanel.add(buttonMessage); vPanel.setCellHorizontalAlignment(buttonMessage, HasHorizontalAlignment.ALIGN_RIGHT); DecoratorPanel panel = new DecoratorPanel(); panel.add(vPanel); // 将小部件添加到根面板。 RootPanel.get("gwtContainer").add(panel); } public String getGreeting(String name){ return "Hello "+name+"!"; } }
步骤 1 - 放置断点
在 HelloWorld.java 的 onModuleLoad() 的第一行放置一个断点
步骤 2 - 调试应用程序
现在单击 调试应用程序菜单并选择 HelloWorld 应用程序来调试应用程序。
如果一切正常,您一定会看到 Eclipse 中激活了 GWT 开发模式,其中包含如下所示的 URL。双击 URL 以打开 GWT 应用程序。
应用程序启动后,您将看到焦点位于 Eclipse 断点上,因为我们已将断点放在入口点方法的第一行。
您可以查看挂起线程的堆栈跟踪。
您可以查看表达式的值。
您可以查看所放置断点的列表。
现在继续按 F6,直到到达 onModuleLoad() 方法的最后一行。作为功能键的参考,F6 逐行检查代码,F5 进一步进入内部,F8 将恢复应用程序。现在您可以看到 onModuleLoad() 方法的所有变量的值列表。
可以像调试 Java 应用程序一样调试 GWT 客户端代码。将断点放置在任何行并使用 GWT 的调试功能。
GWT - 国际化
GWT 提供了三种方式来国际化 GWT 应用程序,我们将演示项目中最常用的静态字符串国际化。
Sr.No. | 技术和说明 |
---|---|
1 |
静态字符串国际化 这种技术最为普遍,运行时所需的开销非常小;是一种非常有效的翻译常量和参数化字符串的技术;最容易实现。 静态字符串国际化使用标准 Java 属性文件来存储翻译的字符串和参数化消息,并创建强类型 Java 接口来检索它们的值。 |
2 |
动态字符串国际化 这种技术非常灵活,但比静态字符串国际化慢。主机页面包含本地化字符串,因此,当我们添加新的语言环境时,不需要重新编译应用程序。如果要将 GWT 应用程序与现有的服务器端本地化系统集成,则应使用此技术。 |
3 |
可本地化接口 此技术是三种技术中最强大的。实现 Localizable 允许我们创建自定义类型的本地化版本。这是一种高级国际化技术。 |
国际化 GWT 应用程序的工作流程
步骤 1 - 创建属性文件
创建包含要在应用程序中使用的消息的属性文件。我们在示例中创建了一个 HelloWorldMessages.properties 文件。
enterName = 输入您的姓名 clickMe = 点击我 applicationTitle = 应用程序国际化演示 greeting = 你好 {0}
创建包含特定于语言环境的翻译值的属性文件。我们在示例中创建了一个 HelloWorldMessages_de.properties 文件。此文件包含德语翻译。_de 指定德语语言环境,我们将在我们的应用程序中支持德语。
如果您使用 Eclipse 创建属性文件,则将文件的编码更改为 UTF-8。选择该文件,然后右键单击以打开其属性窗口。选择文本文件编码为 其他 UTF-8。应用并保存更改。
输入名称 = Geben Sie Ihren Namen clickMe = 点击米奇 applicationTitle = Anwendung Internationalisierung Demonstration 问候语 = 你好{0} 前>第 2 步 - 将 i18n 模块添加到模块描述符 XML 文件
更新模块文件HelloWorld.gwt.xml以包含对德语区域设置的支持
<?xml version = "1.0" encoding = "UTF-8"?> <module rename-to = 'helloworld'> ... <extend-property name = "locale" values="de" /> ... </module>步骤 3 - 创建与属性文件等效的接口
通过扩展 GWT 的 Messages 接口来创建 HelloWorldMessages.java 接口,以包含对内部化的支持。它应包含与属性文件中的键相同的方法名称。占位符将被字符串参数替换。
public interface HelloWorldMessages extends Messages { @DefaultMessage("Enter your name") String enterName(); @DefaultMessage("Click Me") String clickMe(); @DefaultMessage("Application Internalization Demonstration") String applicationTitle(); @DefaultMessage("Hello {0}") String greeting(String name); }步骤 4 - 在 UI 组件中使用消息接口。
使用 HelloWorld 中的 HelloWorldMessages 对象获取消息。
public class HelloWorld implements EntryPoint { /* create an object of HelloWorldMessages interface using GWT.create() method */ private HelloWorldMessages messages = GWT.create(HelloWorldMessages.class); public void onModuleLoad() { ... Label titleLabel = new Label(messages.applicationTitle()); //Add title to the application RootPanel.get("gwtAppTitle").add(titleLabel); ... } }国际化 - 完整示例
此示例将带您完成一些简单的步骤,以演示 GWT 应用程序的国际化功能。
按照以下步骤更新我们在 GWT - 创建应用程序 一章中创建的 GWT 应用程序 −
步骤 描述 1 在 com.tutorialspoint 包下创建一个名为 HelloWorld 的项目,如 GWT - 创建应用程序 一章中所述。 2 修改HelloWorld.gwt.xml、HelloWorld.css、HelloWorld.html 和 HelloWorld.java 如下所述。其余文件保持不变。 3 编译并运行应用程序以验证实施逻辑的结果。 以下是修改后的模块描述符 src/com.tutorialspoint/HelloWorld.gwt.xml 的内容。
<?xml version = "1.0" encoding = "UTF-8"?> <module rename-to = 'helloworld'> <!-- Inherit the core Web Toolkit stuff. --> <inherits name = 'com.google.gwt.user.User'/> <!-- Inherit the default GWT style sheet. --> <inherits name = 'com.google.gwt.user.theme.clean.Clean'/> <!-- Specify the app entry point class. --> <entry-point class = 'com.tutorialspoint.client.HelloWorld'/> <extend-property name = "locale" values="de" /> <!-- Specify the paths for translatable code --> <source path = 'client'/> <source path = 'shared'/> </module>以下是修改后的样式表文件war/HelloWorld.css的内容。
body { text-align: center; font-family: verdana, sans-serif; } h1 { font-size: 2em; font-weight: bold; color: #777777; margin: 40px 0px 70px; text-align: center; }以下是修改后的 HTML 主机文件 war/HelloWorld.html 的内容。
<html> <head> <title>Hello World</title> <link rel = "stylesheet" href = "HelloWorld.css"/> <script language = "javascript" src = "helloworld/helloworld.nocache.js"> </script> </head> <body> <h1 id = "gwtAppTitle"></h1> <div id = "gwtContainer"></div> </body> </html>现在在 src/com.tutorialspoint/client 包中创建 HelloWorldMessages.properties 文件,并将以下内容放入其中
enterName = Enter your name clickMe = Click Me applicationTitle = Application Internationalization Demonstration greeting = Hello {0}现在在 src/com.tutorialspoint/client 包中创建 HelloWorldMessages_de.properties 文件,并将以下内容放入其中
enterName = Geben Sie Ihren Namen clickMe = Klick mich applicationTitle = Anwendung Internationalisierung Demonstration greeting = Hallo {0}现在在 src/com.tutorialspoint/client 包中创建 HelloWorldMessages.java 类,并将以下内容放入其中
package com.tutorialspoint.client; import com.google.gwt.i18n.client.Messages; public interface HelloWorldMessages extends Messages { @DefaultMessage("Enter your name") String enterName(); @DefaultMessage("Click Me") String clickMe(); @DefaultMessage("Application Internationalization Demonstration") String applicationTitle(); @DefaultMessage("Hello {0}") String greeting(String name); }让我们获得 Java 文件 src/com.tutorialspoint/HelloWorld.java 的以下内容,我们将使用它来演示 GWT 代码的国际化功能。
package com.tutorialspoint.client; import com.google.gwt.core.client.EntryPoint; import com.google.gwt.core.client.GWT; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.event.dom.client.KeyCodes; import com.google.gwt.event.dom.client.KeyUpEvent; import com.google.gwt.event.dom.client.KeyUpHandler; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.DecoratorPanel; import com.google.gwt.user.client.ui.HasHorizontalAlignment; import com.google.gwt.user.client.ui.HorizontalPanel; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.RootPanel; import com.google.gwt.user.client.ui.TextBox; import com.google.gwt.user.client.ui.VerticalPanel; public class HelloWorld implements EntryPoint { /* create an object of HelloWorldMessages interface using GWT.create() method */ private HelloWorldMessages messages = GWT.create(HelloWorldMessages.class); public void onModuleLoad() { /*create UI */ final TextBox txtName = new TextBox(); txtName.setWidth("200"); txtName.addKeyUpHandler(new KeyUpHandler() { @Override public void onKeyUp(KeyUpEvent event) { if(event.getNativeKeyCode() == KeyCodes.KEY_ENTER){ Window.alert(getGreeting(txtName.getValue())); } } }); Label lblName = new Label(messages.enterName() + ": "); Button buttonMessage = new Button(messages.clickMe() + "!"); buttonMessage.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { Window.alert(getGreeting(txtName.getValue())); } }); HorizontalPanel hPanel = new HorizontalPanel(); hPanel.add(lblName); hPanel.add(txtName); VerticalPanel vPanel = new VerticalPanel(); vPanel.setSpacing(10); vPanel.add(hPanel); vPanel.add(buttonMessage); vPanel.setCellHorizontalAlignment(buttonMessage, HasHorizontalAlignment.ALIGN_RIGHT); DecoratorPanel panel = new DecoratorPanel(); panel.add(vPanel); Label titleLabel = new Label(messages.applicationTitle()); //Add title to the application RootPanel.get("gwtAppTitle").add(titleLabel); // 将小部件添加到根面板。 RootPanel.get("gwtContainer").add(panel); } public String getGreeting(String name){ return messages.greeting(name + "!"); } }完成所有更改后,让我们像在 GWT - 创建应用程序 一章中一样,在开发模式下编译并运行应用程序。如果您的应用程序一切正常,则将产生以下结果 −
现在更新 URL 以包含 locale=de。设置 URL − http://127.0.0.1:8888/HelloWorld.html?gwt.codesvr=127.0.0.1:9997&locale=de。如果您的应用程序一切正常,这将产生以下结果 −
GWT - History 类
GWT 应用程序通常是运行 JavaScript 的单页应用程序,不包含很多页面,因此浏览器不会跟踪用户与应用程序的交互。要使用浏览器的历史记录功能,应用程序应为每个可导航页面生成一个唯一的 URL 片段。
GWT 提供 历史机制 来处理这种情况。
GWT 使用术语 token,它只是一个字符串,应用程序可以解析它以返回到特定状态。应用程序会将此令牌作为 URL 片段保存在浏览器的历史记录中。
例如,名为"pageIndex1"的历史记录令牌将添加到 URL 中,如下所示 −
http://www.tutorialspoint.com/HelloWorld.html#pageIndex0历史记录管理工作流程
步骤 1 - 启用历史记录支持
为了使用 GWT 历史记录支持,我们必须首先将以下 iframe 嵌入到我们的主机 HTML 页面中。
<iframe src = "javascript:''" id = "__gwt_historyFrame" style = "width:0;height:0;border:0"></iframe>步骤 2 - 将令牌添加到历史记录
以下示例统计如何将令牌添加到浏览器历史记录
int index = 0; History.newItem("pageIndex" + index);步骤 3 - 从历史记录中检索令牌
当用户使用浏览器的后退/前进按钮时,我们将检索令牌并相应地更新我们的应用程序状态。
History.addValueChangeHandler(new ValueChangeHandler<String>() { @Override public void onValueChange(ValueChangeEvent<String> event) { String historyToken = event.getValue(); /* parse the history token */ try { if (historyToken.substring(0, 9).equals("pageIndex")) { String tabIndexToken = historyToken.substring(9, 10); int tabIndex = Integer.parseInt(tabIndexToken); /* select the specified tab panel */ tabPanel.selectTab(tabIndex); } else { tabPanel.selectTab(0); } } catch (IndexOutOfBoundsException e) { tabPanel.selectTab(0); } } });现在让我们看看 History 类的实际作用。
History 类 - 完整示例
此示例将带您完成一些简单的步骤来演示 GWT 应用程序的 History 管理。按照以下步骤更新我们在 GWT - 创建应用程序 一章中创建的 GWT 应用程序 −
步骤 描述 1 在 com.tutorialspoint 包下创建一个名为 HelloWorld 的项目,如 GWT - 创建应用程序 一章中所述。 2 修改 HelloWorld.gwt.xml、HelloWorld.css、HelloWorld.html 和 HelloWorld.java,如下所述。其余文件保持不变。 3 编译并运行应用程序以验证实现逻辑的结果。 以下是修改后的模块描述符src/com.tutorialspoint/HelloWorld.gwt.xml的内容。
<?xml version = "1.0" encoding = "UTF-8"?> <module rename-to = 'helloworld'> <!-- Inherit the core Web Toolkit stuff. --> <inherits name = 'com.google.gwt.user.User'/> <!-- Inherit the default GWT style sheet. --> <inherits name = 'com.google.gwt.user.theme.clean.Clean'/> <!-- Specify the app entry point class. --> <entry-point class = 'com.tutorialspoint.client.HelloWorld'/> <!-- Specify the paths for translatable code --> <source path = 'client'/> <source path = 'shared'/> </module>以下是修改后的样式表文件war/HelloWorld.css的内容。
body { text-align: center; font-family: verdana, sans-serif; } h1 { font-size: 2em; font-weight: bold; color: #777777; margin: 40px 0px 70px; text-align: center; }以下是修改后的 HTML 宿主文件 war/HelloWorld.html 的内容
<html> <head> <title>Hello World</title> <link rel = "stylesheet" href = "HelloWorld.css"/> <script language = "javascript" src = "helloworld/helloworld.nocache.js"> </script> </head> <body> <iframe src = "javascript:''"id = "__gwt_historyFrame" style = "width:0;height:0;border:0"></iframe> <h1> History Class Demonstration</h1> <div id = "gwtContainer"></div> </body> </html>让我们拥有 Java 文件 src/com.tutorialspoint/HelloWorld.java 的以下内容,我们将使用它来演示 GWT 代码中的历史管理。
package com.tutorialspoint.client; import com.google.gwt.core.client.EntryPoint; import com.google.gwt.event.logical.shared.SelectionEvent; import com.google.gwt.event.logical.shared.SelectionHandler; import com.google.gwt.event.logical.shared.ValueChangeEvent; import com.google.gwt.event.logical.shared.ValueChangeHandler; import com.google.gwt.user.client.History; import com.google.gwt.user.client.ui.HTML; import com.google.gwt.user.client.ui.RootPanel; import com.google.gwt.user.client.ui.TabPanel; public class HelloWorld implements EntryPoint { /** * This is the entry point method. */ public void onModuleLoad() { /* create a tab panel to carry multiple pages */ final TabPanel tabPanel = new TabPanel(); /* create pages */ HTML firstPage = new HTML("<h1>We are on first Page.</h1>"); HTML secondPage = new HTML("<h1>We are on second Page.</h1>"); HTML thirdPage = new HTML("<h1>We are on third Page.</h1>"); String firstPageTitle = "First Page"; String secondPageTitle = "Second Page"; String thirdPageTitle = "Third Page"; tabPanel.setWidth("400"); /* add pages to tabPanel*/ tabPanel.add(firstPage, firstPageTitle); tabPanel.add(secondPage,secondPageTitle); tabPanel.add(thirdPage, thirdPageTitle); /* add tab selection handler */ tabPanel.addSelectionHandler(new SelectionHandler<Integer>() { @Override public void onSelection(SelectionEvent<Integer> event) { /* add a token to history containing pageIndex History class will change the URL of application by appending the token to it. */ History.newItem("pageIndex" + event.getSelectedItem()); } }); /* add value change handler to History this method will be called, when browser's Back button or Forward button are clicked and URL of application changes. */ History.addValueChangeHandler(new ValueChangeHandler<String>() { @Override public void onValueChange(ValueChangeEvent<String> event) { String historyToken = event.getValue(); /* parse the history token */ try { if (historyToken.substring(0, 9).equals("pageIndex")) { String tabIndexToken = historyToken.substring(9, 10); int tabIndex = Integer.parseInt(tabIndexToken); /* select the specified tab panel */ tabPanel.selectTab(tabIndex); } else { tabPanel.selectTab(0); } } catch (IndexOutOfBoundsException e) { tabPanel.selectTab(0); } } }); /* select the first tab by default */ tabPanel.selectTab(0); /* add controls to RootPanel */ RootPanel.get().add(tabPanel); } }完成所有更改后,让我们像在 GWT - 创建应用程序 一章中一样,在开发模式下编译并运行应用程序。如果您的应用程序一切正常,则将产生以下结果 −
现在单击每个选项卡以选择不同的页面。
您应该注意到,选择每个选项卡时,应用程序 URL 都会更改,并且 #pageIndex 会添加到 URL 中。
您还可以看到浏览器的后退和前进按钮现在已启用。
使用浏览器的后退和前进按钮,您将看到不同的选项卡被相应地选中。
GWT - 书签支持
GWT 使用 History 类支持浏览器历史记录管理,您可以参考 GWT - History Class 一章。
GWT 使用术语 token,它只是一个字符串,应用程序可以解析该字符串以返回特定状态。应用程序会将此令牌作为 URL 片段保存在浏览器的历史记录中。
在 GWT - History Class 一章中,我们通过编写代码来处理令牌的创建和历史记录中的设置。
在本文中,我们将讨论一个特殊的小部件 Hyperlink,它会自动为我们执行令牌创建和历史记录管理,并为应用程序提供书签功能。
书签示例
此示例将带您完成简单的步骤来演示 GWT 应用程序的书签功能。
以下步骤用于更新我们在 GWT - Create Application 一章中创建的 GWT 应用程序 −
步骤 | 描述 |
---|---|
1 | 创建一个项目一个名为 HelloWorld 的包位于 com.tutorialspoint 下,如 GWT - 创建应用程序 一章中所述。 |
2 | 修改 HelloWorld.gwt.xml、HelloWorld.css、HelloWorld.html 和 HelloWorld.java,如下所述。保持其余文件不变。 |
3 | 编译并运行应用程序以验证实现逻辑的结果。 |
以下是修改后的模块描述符 src/com.tutorialspoint/HelloWorld.gwt.xml 的内容。
<?xml version = "1.0" encoding = "UTF-8"?> <module rename-to = 'helloworld'> <!-- Inherit the core Web Toolkit stuff. --> <inherits name = 'com.google.gwt.user.User'/> <!-- Inherit the default GWT style sheet. --> <inherits name = 'com.google.gwt.user.theme.clean.Clean'/> <!-- Specify the app entry point class. --> <entry-point class = 'com.tutorialspoint.client.HelloWorld'/> <!-- Specify the paths for translatable code --> <source path = 'client'/> <source path = 'shared'/> </module>
以下是修改后的样式表文件war/HelloWorld.css的内容。
body { text-align: center; font-family: verdana, sans-serif; } h1 { font-size: 2em; font-weight: bold; color: #777777; margin: 40px 0px 70px; text-align: center; }
以下是修改后的 HTML 宿主文件 war/HelloWorld.html 的内容
<html> <head> <title>Hello World</title> <link rel = "stylesheet" href = "HelloWorld.css"/> <script language = "javascript" src = "helloworld/helloworld.nocache.js"> </script> </head> <body> <iframe src = "javascript:''"id = "__gwt_historyFrame" style = "width:0;height:0;border:0"></iframe> <h1> Bookmarking Demonstration</h1> <div id = "gwtContainer"></div> </body> </html>
让我们获得 Java 文件 src/com.tutorialspoint/HelloWorld.java 的以下内容,我们将使用它来演示 GWT 代码中的书签。
package com.tutorialspoint.client; import com.google.gwt.core.client.EntryPoint; import com.google.gwt.event.logical.shared.ValueChangeEvent; import com.google.gwt.event.logical.shared.ValueChangeHandler; import com.google.gwt.user.client.History; import com.google.gwt.user.client.ui.HTML; import com.google.gwt.user.client.ui.HorizontalPanel; import com.google.gwt.user.client.ui.Hyperlink; import com.google.gwt.user.client.ui.RootPanel; import com.google.gwt.user.client.ui.TabPanel; import com.google.gwt.user.client.ui.VerticalPanel; public class HelloWorld implements EntryPoint { private TabPanel tabPanel; private void selectTab(String historyToken){ /* parse the history token */ try { if (historyToken.substring(0, 9).equals("pageIndex")) { String tabIndexToken = historyToken.substring(9, 10); int tabIndex = Integer.parseInt(tabIndexToken); /* Select the specified tab panel */ tabPanel.selectTab(tabIndex); } else { tabPanel.selectTab(0); } } catch (IndexOutOfBoundsException e) { tabPanel.selectTab(0); } } /** * This is the entry point method. */ public void onModuleLoad() { /* create a tab panel to carry multiple pages */ tabPanel = new TabPanel(); /* create pages */ HTML firstPage = new HTML("<h1>We are on first Page.</h1>"); HTML secondPage = new HTML("<h1>We are on second Page.</h1>"); HTML thirdPage = new HTML("<h1>We are on third Page.</h1>"); String firstPageTitle = "First Page"; String secondPageTitle = "Second Page"; String thirdPageTitle = "Third Page"; Hyperlink firstPageLink = new Hyperlink("1", "pageIndex0"); Hyperlink secondPageLink = new Hyperlink("2", "pageIndex1"); Hyperlink thirdPageLink = new Hyperlink("3", "pageIndex2"); HorizontalPanel linksHPanel = new HorizontalPanel(); linksHPanel.setSpacing(10); linksHPanel.add(firstPageLink); linksHPanel.add(secondPageLink); linksHPanel.add(thirdPageLink); /* If the application starts with no history token, redirect to a pageIndex0 */ String initToken = History.getToken(); if (initToken.length() == 0) { History.newItem("pageIndex0"); initToken = "pageIndex0"; } tabPanel.setWidth("400"); /* add pages to tabPanel*/ tabPanel.add(firstPage, firstPageTitle); tabPanel.add(secondPage,secondPageTitle); tabPanel.add(thirdPage, thirdPageTitle); /* add value change handler to History * this method will be called, when browser's Back button * or Forward button are clicked. * and URL of application changes. * */ History.addValueChangeHandler(new ValueChangeHandler<String>() { @Override public void onValueChange(ValueChangeEvent<String> event) { selectTab(event.getValue()); } }); selectTab(initToken); VerticalPanel vPanel = new VerticalPanel(); vPanel.setSpacing(10); vPanel.add(tabPanel); vPanel.add(linksHPanel); /* add controls to RootPanel */ RootPanel.get().add(vPanel); } }
完成所有更改后,让我们在开发模式下编译并运行应用程序,就像在GWT - 创建应用程序一章中所做的那样。如果您的应用程序一切正常,这将产生以下结果 −
现在单击 1、2 或 3。您可以注意到选项卡随索引而变化。
您应该注意到,当您单击 1、2 或 3 时,应用程序 url 会发生变化,并且 #pageIndex 会添加到 url 中
您还可以看到浏览器的后退和前进按钮现在已启用。
使用浏览器的后退和前进按钮,您将看到相应的不同选项卡被选中。
右键单击 1、2 或 3。您可以看到打开、在新窗口中打开、在新选项卡中打开、添加到收藏夹等选项等等。
右键单击 3。选择添加到收藏夹。将书签保存为第 3 页。
打开收藏夹并选择第 3 页。您将看到第三个选项卡被选中。
GWT - 日志框架
日志框架模拟 java.util.logging,因此它使用相同的语法,并且具有与服务器端日志代码相同的行为
使用 .gwt.xml 文件配置 GWT 日志。
我们可以配置日志以启用/禁用;我们可以启用/禁用特定处理程序,并更改默认日志级别。
记录器的类型
记录器以树结构组织,根记录器位于树的根部。
记录器的名称使用 . 分隔名称的各个部分来确定父/子关系。
例如,如果我们有两个记录器 Hospital.room1 和 Hospital.room2,那么它们是兄弟,其父级是名为 Hospital 的记录器。 Hospital 记录器(以及名称中不包含点"。"的任何记录器)以 Root Logger 作为父级。
private static Logger room1Logger = Logger.getLogger("Hospital.room1"); private static Logger room2Logger = Logger.getLogger("Hospital.room2"); private static Logger hospitalLogger = Logger.getLogger("Hospital"); private static Logger rootLogger = Logger.getLogger("");
日志处理程序
GWT 提供默认处理程序,将显示使用记录器生成的日志条目。
处理程序 | 记录到 | 描述 |
---|---|---|
SystemLogHandler | stdout | 这些消息只能在 DevMode 窗口中的开发模式下看到。 |
DevelopmentModeLogHandler | DevMode 窗口 | 通过调用方法 GWT.log 记录。这些消息只能在 DevMode 窗口中的开发模式下看到。 |
ConsoleLogHandler | javascript 控制台 | 记录到 javascript 控制台,该控制台由 Firebug Lite(适用于 IE)、Safari 和 Chrome 使用。 |
FirebugLogHandler | Firebug | 记录到 firebug 控制台。 |
PopupLogHandler | popup | 启用此处理程序时,记录到位于应用程序左上角的弹出窗口。 |
SimpleRemoteLogHandler | server | 此处理程序将日志消息发送到服务器,服务器将使用服务器端日志记录机制记录这些消息。 |
在 GWT 应用程序中配置日志记录
需要配置 HelloWorld.gwt.xml 文件以启用 GWT 日志记录,如下所示 −
# add logging module <inherits name = "com.google.gwt.logging.Logging"/> # To change the default logLevel <set-property name = "gwt.logging.logLevel" value = "SEVERE"/> # To enable logging <set-property name = "gwt.logging.enabled" value = "TRUE"/> # To disable a popup Handler <set-property name = "gwt.logging.popupHandler" value = "DISABLED" />
Use logger to log user actions
/* Create Root Logger */ private static Logger rootLogger = Logger.getLogger(""); ... rootLogger.log(Level.SEVERE, "pageIndex selected: " + event.getValue()); ...
日志记录框架示例
此示例将带您通过简单的步骤演示 GWT 应用程序的日志记录功能。按照以下步骤更新我们在 GWT - 创建应用程序 一章中创建的 GWT 应用程序 −
步骤 | 描述 |
---|---|
1 | 在 com.tutorialspoint 包下创建一个名为 HelloWorld 的项目,如 GWT - 创建应用程序 一章中所述。 |
2 | 修改 HelloWorld.gwt.xml、HelloWorld.css、HelloWorld.html 和 HelloWorld.java,如下所述。其余文件保持不变。 |
3 | 编译并运行应用程序以验证实现逻辑的结果。 |
以下是修改后的模块描述符src/com.tutorialspoint/HelloWorld.gwt.xml的内容。
<?xml version = "1.0" encoding = "UTF-8"?> <module rename-to = 'helloworld'> <!-- Inherit the core Web Toolkit stuff. --> <inherits name = 'com.google.gwt.user.User'/> <!-- Inherit the default GWT style sheet. --> <inherits name = 'com.google.gwt.user.theme.clean.Clean'/> <inherits name = "com.google.gwt.logging.Logging"/> <!-- Specify the app entry point class. --> <entry-point class = 'com.tutorialspoint.client.HelloWorld'/> <!-- Specify the paths for translatable code --> <source path = 'client'/> <source path = 'shared'/> <set-property name = "gwt.logging.logLevel" value="SEVERE"/> <set-property name = "gwt.logging.enabled" value = "TRUE"/> <set-property name = "gwt.logging.popupHandler" value= "DISABLED" /> </module>
以下是修改后的样式表文件war/HelloWorld.css的内容。
body { text-align: center; font-family: verdana, sans-serif; } h1 { font-size: 2em; font-weight: bold; color: #777777; margin: 40px 0px 70px; text-align: center; }
以下是修改后的 HTML 宿主文件 war/HelloWorld.html 的内容
<html> <head> <title>Hello World</title> <link rel = "stylesheet" href = "HelloWorld.css"/> <script language = "javascript" src = "helloworld/helloworld.nocache.js"> </script> </head> <body> <iframe src = "javascript:''"id = "__gwt_historyFrame" style = "width:0;height:0;border:0"></iframe> <h1> Logging Demonstration</h1> <div id = "gwtContainer"></div> </body> </html>
让我们获得 Java 文件 src/com.tutorialspoint/HelloWorld.java 的以下内容,我们将使用它来演示 GWT 代码中的书签。
package com.tutorialspoint.client; import java.util.logging.Level; import java.util.logging.Logger; import com.google.gwt.core.client.EntryPoint; import com.google.gwt.event.logical.shared.ValueChangeEvent; import com.google.gwt.event.logical.shared.ValueChangeHandler; import com.google.gwt.logging.client.HasWidgetsLogHandler; import com.google.gwt.user.client.History; import com.google.gwt.user.client.ui.HTML; import com.google.gwt.user.client.ui.HorizontalPanel; import com.google.gwt.user.client.ui.Hyperlink; import com.google.gwt.user.client.ui.RootPanel; import com.google.gwt.user.client.ui.TabPanel; import com.google.gwt.user.client.ui.VerticalPanel; public class HelloWorld implements EntryPoint { private TabPanel tabPanel; /* Create Root Logger */ private static Logger rootLogger = Logger.getLogger(""); private VerticalPanel customLogArea; private void selectTab(String historyToken){ /* parse the history token */ try { if (historyToken.substring(0, 9).equals("pageIndex")) { String tabIndexToken = historyToken.substring(9, 10); int tabIndex = Integer.parseInt(tabIndexToken); /* Select the specified tab panel */ tabPanel.selectTab(tabIndex); } else { tabPanel.selectTab(0); } } catch (IndexOutOfBoundsException e) { tabPanel.selectTab(0); } } /** * This is the entry point method. */ public void onModuleLoad() { /* create a tab panel to carry multiple pages */ tabPanel = new TabPanel(); /* create pages */ HTML firstPage = new HTML("<h1>We are on first Page.</h1>"); HTML secondPage = new HTML("<h1>We are on second Page.</h1>"); HTML thirdPage = new HTML("<h1>We are on third Page.</h1>"); String firstPageTitle = "First Page"; String secondPageTitle = "Second Page"; String thirdPageTitle = "Third Page"; Hyperlink firstPageLink = new Hyperlink("1", "pageIndex0"); Hyperlink secondPageLink = new Hyperlink("2", "pageIndex1"); Hyperlink thirdPageLink = new Hyperlink("3", "pageIndex2"); HorizontalPanel linksHPanel = new HorizontalPanel(); linksHPanel.setSpacing(10); linksHPanel.add(firstPageLink); linksHPanel.add(secondPageLink); linksHPanel.add(thirdPageLink); /* If the application starts with no history token, redirect to a pageIndex0 */ String initToken = History.getToken(); if (initToken.length() == 0) { History.newItem("pageIndex0"); initToken = "pageIndex0"; } tabPanel.setWidth("400"); /* add pages to tabPanel*/ tabPanel.add(firstPage, firstPageTitle); tabPanel.add(secondPage,secondPageTitle); tabPanel.add(thirdPage, thirdPageTitle); /* add value change handler to History * this method will be called, when browser's Back button * or Forward button are clicked. * and URL of application changes. * */ History.addValueChangeHandler(new ValueChangeHandler<String>() { @Override public void onValueChange(ValueChangeEvent<String> event) { selectTab(event.getValue()); rootLogger.log(Level.SEVERE, "pageIndex selected: " + event.getValue()); } }); selectTab(initToken); VerticalPanel vPanel = new VerticalPanel(); vPanel.setSpacing(10); vPanel.add(tabPanel); vPanel.add(linksHPanel); customLogArea = new VerticalPanel(); vPanel.add(customLogArea); /* an example of using own custom logging area. */ rootLogger.addHandler(new HasWidgetsLogHandler(customLogArea)); /* add controls to RootPanel */ RootPanel.get().add(vPanel); } }
完成所有更改后,让我们像在 GWT - 创建应用程序 一章中一样,在开发模式下编译并运行应用程序。如果您的应用程序一切正常,则将产生以下结果 −
现在单击 1、2 或 3。您会注意到,当您单击 1、2 或 3 时,您可以看到打印日志并显示页面索引。检查 Eclipse 中的控制台输出。您还可以看到日志也在 Eclipse 控制台中打印。
Fri Aug 31 11:42:35 IST 2012 SEVERE: pageIndex selected: pageIndex0 Fri Aug 31 11:42:37 IST 2012 SEVERE: pageIndex selected: pageIndex1 Fri Aug 31 11:42:38 IST 2012 SEVERE: pageIndex selected: pageIndex2 Fri Aug 31 11:42:40 IST 2012 SEVERE: pageIndex selected: pageIndex0 Fri Aug 31 11:42:41 IST 2012 SEVERE: pageIndex selected: pageIndex1 Fri Aug 31 11:42:41 IST 2012 SEVERE: pageIndex selected: pageIndex2
现在更新模块描述符src/com.tutorialspoint/HelloWorld.gwt.xml以启用popupHandler。
<?xml version = "1.0" encoding = "UTF-8"?> <module rename-to = 'helloworld'> <!-- Inherit the core Web Toolkit stuff. --> <inherits name = 'com.google.gwt.user.User'/> <!-- Inherit the default GWT style sheet. --> <inherits name = 'com.google.gwt.user.theme.clean.Clean'/> <inherits name = "com.google.gwt.logging.Logging"/> <!-- Specify the app entry point class. --> <entry-point class = 'com.tutorialspoint.client.HelloWorld'/> <!-- Specify the paths for translatable code --> <source path = 'client'/> <source path = 'shared'/> <set-property name = "gwt.logging.logLevel" value = "SEVERE"/> <set-property name = "gwt.logging.enabled" value = "TRUE"/> <set-property name="gwt.logging.popupHandler" value = "ENABLED" /> </module>
完成所有更改后,刷新浏览器窗口(按浏览器的 F5/重新加载按钮)重新加载应用程序。请注意,应用程序左上角现在有一个弹出窗口。
现在单击 1、2 或 3。您会注意到,当您单击 1、2 或 3 时,您可以看到日志正在打印,并在弹出窗口中显示页面索引。