目录

GWT - 快速指南

GWT - Overview

什么是GWT?

Google Web Toolkit(GWT)是一个用于创建RICH Internet Applications (RIA)的开发工具包。 以下是一些值得注意的功能 -

  • GWT为开发人员提供了在JAVA中编写客户端应用程序的选项。

  • GWT将用JAVA编写的代码编译为JavaScript代码。

  • 用GWT编写的应用程序是跨浏览器兼容的。 GWT自动生成适合每个浏览器的javascript代码。

  • GWT是开源的,完全免费的,并被全球数千名开发人员使用。 它是根据Apache许可证2.0版许可的。

总体而言,GWT是一个构建大规模和高性能Web应用程序的framework ,同时使它们易于维护。

为什么要使用GWT?

基于Java,您可以使用Eclipse等JAVA IDE来开发GWT应用程序。

开发人员可以使用代码自动完成/重构/导航/项目管理以及IDEs.GWT的所有功能,它提供完整的调试功能。 开发人员可以像Java应用程序一样调试客户端应用程序。

  • GWT提供与Junit和Maven的轻松集成。

  • 作为基于Java的,GWT对Java开发人员的学习曲线较低。

  • GWT生成优化的javascript代码,自己生成浏览器的特定javascript代码。

  • GWT提供的Widgets库提供了应用程序所需的大部分任务。

  • GWT是可扩展的,可以创建自定义小部件以满足应用程序需求。

最重要的是,GWT应用程序可以在所有主流浏览器和智能手机上运行,​​包括基于Android和iOS的手机/平板电脑。

GWT的缺点

虽然GWT提供了很多优点,但它有以下缺点 -

  • Not Indexable - GWT生成的网页不会被搜索引擎索引,因为这些应用程序是动态生成的。

  • Not Degradable - 如果您的应用程序用户禁用Javascript,那么用户只会看到基本页面而已。

  • Not Designer's Friendly - GWT不适合那些喜欢使用普通HTML和占位符来在以后插入动态内容的网页设计师。

GWT组件

GWT框架可分为以下三个主要部分 -

  • GWT Java to JavaScript compiler - 这是GWT最重要的部分,使其成为构建RIA的强大工具。 GWT编译器用于将用Java编写的所有应用程序代码转换为JavaScript。

  • JRE Emulation library - Google Web Toolkit包含一个模拟Java运行时库子集的库。 该列表包括java.lang,java.lang.annotation,java.math,java.io,java.sql,java.util和java.util.logging

  • GWT UI building library - GWT的这一部分由许多子部分组成,其中包括实际的UI组件,RPC支持,历史记录管理等等。

GWT还提供了一个GWT托管Web浏览器,它允许您以托管模式运行和执行GWT应用程序,其中您的代码在Java虚拟机中作为Java运行,而无需编译为JavaScript。

GWT - Environment Setup

本教程将指导您如何准备开发环境以开始使用GWT Framework。 本教程还将教您如何在设置GWT框架之前在您的机器上设置JDK,Tomcat和Eclipse -

系统需求 (System Requirement)

GWT需要JDK 1.6或更高版本,因此第一个要求是在您的计算机上安装JDK。

JDK 1.6或以上。
记忆 没有最低要求。
磁盘空间 没有最低要求。
操作系统 没有最低要求。

按照给定的步骤设置环境以开始GWT应用程序开发。

步骤1 - 验证计算机上的Java安装

现在打开控制台并执行以下java命令。

OS 任务 命令
Windows 打开命令控制台 c:\> java -version
Linux 打开命令终端 $ java -version
Mac 开放式终端 机器:~joseph $ java -version

让我们验证所有操作系统的输出

Sr.No. 操作系统和生成的输出
1

Windows

java版“1.6.0_21”

Java(TM)SE运行时环境(版本1.6.0_21-b07)

Java HotSpot(TM)客户端VM(版本17.0-b17,混合模式,共享)

2

Linux

java版“1.6.0_21”

Java(TM)SE运行时环境(版本1.6.0_21-b07)

ava HotSpot(TM)客户端VM(版本17.0-b17,混合模式,共享)

3

Mac

java版“1.6.0_21”

Java(TM)SE运行时环境(版本1.6.0_21-b07)

Java HotSpot(TM)64位服务器VM(内置17.0-b17,混合模式,共享)

第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. 操作系统和输出
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 JBuilder,Eclipse,IntelliJ IDEA或Sun ONE Studio等集成开发环境(IDE),请编译并运行一个简单程序以确认IDE知道您在何处安装Java,否则请按照给定文档进行正确设置的IDE。

第3步 - 安装Eclipse IDE

本教程中的所有示例都是使用Eclipse IDE编写的。 因此,我建议您根据操作系统在计算机上安装最新版本的Eclipse。

要安装Eclipse IDE,请从https://www.eclipse.org/downloads/下载最新的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

成功启动后,如果一切正常,那么它应显示以下结果 -

Eclipse主页

第4步:为Eclipse安装GWT SDK和插件

按照Eclipse插件(包括SDK)链接中的说明安装机器上安装的Eclipse版本的GWT SDK和插件。

成功设置GWT插件后,如果一切正常,则应显示以下屏幕,其中Google icon标有红色矩形,如下所示 -

Eclipse与谷歌

第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
or
C:\apache-tomcat-6.0.33\bin\startup.bat

成功启动后,Tomcat附带的默认Web应用程序将通过访问http://localhost:8080/ 。 如果一切都很好,那么它应该显示以下结果 -

Tomcat主页

有关配置和运行Tomcat的更多信息,请参见此处包含的文档以及Tomcat网站 - https://tomcat.apache.org/

可以通过在Windows机器上执行以下命令来停止Tomcat -

%CATALINA_HOME%\bin\shutdown
or
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 - Applications

在我们开始使用GWT创建实际的“HelloWorld”应用程序之前,让我们看看GWT应用程序的实际部分是什么 -

GWT应用程序包含以下四个重要部分,其中最后一部分是可选的,但前三部分是必需的。

  • 模块描述符
  • 公共资源
  • 客户端代码
  • 服务器端代码

典型gwt应用程序HelloWord的不同部分的样本位置如下所示 -

名称 地点
Project rootHelloWorld/
模块描述符 src/com/iowiki/HelloWorld.gwt.xml
公共资源 src/com/iowiki/war/
客户端代码 src/com/iowiki/client/
服务器端代码 src/com/iowiki/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.iowiki.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应用程序中的import一样。 可以以这种方式继承任意数量的模块。

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或图像。

可以使用模块配置文件中的元素配置这些资源的位置。 默认情况下,它是存储模块XML文件的公共子目录。

将应用程序编译为JavaScript时,可以在公共路径中找到的所有文件都复制到模块的输出目录中。

最重要的公共资源是主页,用于调用实际的GWT应用程序。 应用程序的典型HTML主机页面可能根本不包含任何可见的HTML正文内容,但总是希望通过标记包含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;
}

Client-side Code

这是实现应用程序业务逻辑的实际Java代码,GWT编译器转换为JavaScript,最终将在浏览器中运行。 可以使用模块配置文件中的元素配置这些资源的位置。

例如, 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 - Create Application

由于GWT的功能在于使用Java Write in Java, Run in JavaScriptWrite in Java, Run in JavaScript ,我们将使用Java IDE Eclipse来演示我们的示例。

让我们从一个简单的HelloWorld应用程序开始 -

第1步 - 创建项目

第一步是使用Eclipse IDE创建一个简单的Web应用程序项目。 使用Google Icon Google服务和开发工具 》 New Web Application Project...选项启动项目向导 Google Icon Google服务和开发工具 》 New Web Application Project... Google Icon Google服务和开发工具 》 New Web Application Project... 现在使用向导窗口将项目命名为HelloWorld ,如下所示 -

创建GWT项目向导

取消选择Use Google App Engine因为我们没有在此项目中使用它并保留其他默认值(保持选中Generate Sample project code选项)并单击Finish按钮。

成功创建项目后,您将在Project Explorer中拥有以下内容 -

GWT项目结构

以下是所有重要文件夹的简要说明

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,hots HTML将调用GWT UI Application。

第2步 - 修改模块描述符:HelloWorld.gwt.xml

GWT插件将创建一个默认模块描述符文件src/com.iowiki/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.iowiki.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.iowiki/HelloWorld.java ,它保留了应用程序的入口点。

让我们修改此文件以显示“Hello,World!”

package com.iowiki.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 Icon Google服务和开发工具 》 GWT Compile Project...选项 Google Icon Google服务和开发工具 》 GWT Compile Project... Google Icon Google服务和开发工具 》 GWT Compile Project...启动GWT Compile对话框,如下图所示 -

编译GWT项目向导

保持默认值不变,然后单击“编译”按钮。 如果一切顺利,您将在Eclipse控制台中看到以下输出

Compiling module com.iowiki.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应用程序以运行该应用程序。

GWT运行按钮

如果一切正常,您必须在Eclipse中看到包含URL的GWT开发模式,如下所示。 双击URL以打开GWT应用程序。

GWT运行应用程序

因为您在开发模式下运行应用程序,所以您需要为浏览器安装GWT插件。 只需按照屏幕上的说明安装插件即可。

如果您已经为浏览器设置了GWT插件,那么您应该能够看到以下输出

GWT申请结果

恭喜! 您已使用Google Web Toolkit(GWT)实施了第一个应用程序。

GWT - Deploy Application

本教程将向您解释如何创建应用程序"war"文件以及如何在Apache Tomcat Websever根目录中部署它。

如果您理解了这个简单的示例,那么您还可以按照相同的步骤部署复杂的GWT应用程序。

让我们使用Eclipse IDE和GWT插件,并按照以下步骤创建GWT应用程序 -

描述
1com.iowiki包下创建一个名为HelloWorld的项目,如GWT - Create Application一章中所述。
2 修改HelloWorld.gwt.xmlHelloWorld.cssHelloWorld.htmlHelloWorld.java ,如下所述。 保持其余文件不变。
3 编译并运行应用程序以确保业务逻辑按照要求运行。
4 最后,以war文件的形式压缩应用程序的war文件夹的内容,并将其部署在Apache Tomcat Webserver中。
5 使用适当的URL启动Web应用程序,如下面的最后一步所述。

以下是修改后的模块描述符src/com.iowiki/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.iowiki.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>,我们将使用我们的入口点java类插入一些内容。
因此,让我们有以下Java文件src/com.iowiki/HelloWorld.java
package com.iowiki.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);
   }
}

这里我们创建了基本的widgest HTML并将其添加到id =“gwtContainer”的div标签中。 我们将在接下来的章节中研究不同的GWT小部件。

一旦准备好完成所有更改,让我们像在GWT - 创建应用程序章节中那样在开发模式下编译和运行应用程序 。 如果您的应用程序一切正常,这将产生以下结果 -

GWT申请结果2

创建WAR文件

现在我们的应用程序运行正常,我们准备将其导出为war文件。

请按照以下步骤操作 -

  • 进入项目的war目录C:\workspace\HelloWorld\war

  • 选择war目录中可用的所有文件和文件夹。

  • 将所有选定的文件和文件夹压缩到名为HelloWorld.zip的文件中。

  • HelloWorld.zip重命名为HelloWorld.war

部署WAR文件

  • 停止tomcat服务器。

  • HelloWorld.war文件复制到tomcat installation directory 》 webapps folder.

  • 启动tomcat服务器。

  • 查看webapps目录,应该创建一个helloworld文件夹。

  • 现在HelloWorld.war已成功部署在Tomcat Webserver根目录中。

运行应用程序

在Web浏览器中输入URL: http://localhost:8080/HelloWorld以启动应用程序

服务器名称(localhost)和端口(8080)可能因tomcat配置而异。

GWT申请结果3

GWT - Style with CSS

GWT小部件依赖于级联样式表(CSS)来实现视觉样式。 默认情况下,每个组件的类名是gwt-《classname》

例如,Button小部件的默认样式为gwt-Button ,类似的方式TextBox widgest的默认样式为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");

主要和次要样式

默认情况下,窗口小部件的primary style名称将是其窗口小部件类的默认样式名称,例如按钮窗口小部件的gwt-Button 。 当我们使用AddStyleName()方法添加和删除样式名称时,这些样式称为辅助样式。

窗口小部件的最终外观由添加到其中的所有辅助样式的总和以及其主要样式确定。 您可以使用setStylePrimaryName(String)方法设置窗口小部件的主要样式。 为了说明,假设我们有一个Label小部件。 在我们的CSS文件中,我们定义了以下规则 -

.MyText {
   color: blue;
}
.BigText {
   font-size: large;
}
.LoudText {
   font-weight:  bold;
}

假设我们希望特定标签小部件始终显示蓝色文本,并且在某些情况下,使用更大的粗体字体来增加重点。

我们可以这样做 -

// set up our primary style
Label someText = new Label();
someText.setStylePrimaryName("MyText");
...
// later on, to really grab the user's attention
someText.addStyleName("BigText");
someText.addStyleName("LoudText");
...
// after the crisis is over
someText.removeStyleName("BigText");
someText.removeStyleName("LoudText");

关联CSS文件

有多种方法可以将CSS文件与模块相关联。 现代GWT应用程序通常使用CssResource和UiBinder的组合。 我们在示例中仅使用第一种方法。

  • 在主机HTML页面中使用标记。

  • 使用模块XML文件中的元素。

  • 使用ClientBundle包含的CssResource

  • UiBinder模板中使用内联<ui:style>元素。

GWT CSS示例

此示例将指导您完成在GWT widgest上应用不同CSS规则的简单步骤。 让我们使用Eclipse IDE和GWT插件,并按照以下步骤创建GWT应用程序 -

描述
1com.iowiki包下创建一个名为HelloWorld的项目,如GWT - Create Application一章中所述。
2 修改HelloWorld.gwt.xmlHelloWorld.cssHelloWorld.htmlHelloWorld.java ,如下所述。 保持其余文件不变。
3 编译并运行应用程序以验证实现的逻辑的结果。

以下是修改后的模块描述符src/com.iowiki/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.iowiki.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.iowiki/HelloWorld.java ,它将负责在HTML中添加两个按钮,并将应用自定义CSS样式。

package com.iowiki.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() {
   // add button to change font to big when clicked.
   Button Btn1 = new Button("Big Text");
   Btn1.addClickHandler(new ClickHandler() {
      public void onClick(ClickEvent event) {
         RootPanel.get("mytext").setStyleName("gwt-Big-Text");
      }
   });
   // add button to change font to small when clicked.
   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 - 创建应用程序章节中那样在开发模式下编译和运行应用程序 。 如果您的应用程序一切正常,这将产生以下结果 -

GWT CSS应用程序结果

现在点击显示的两个按钮,观察“Hello,World!” 单击两个按钮时不断更改字体的文本。

GWT - Basic Widgets

每个用户界面都考虑以下三个主要方面 -

  • UI elements - 这是用户最终看到并与之交互的核心视觉元素。 GWT提供了大量广泛使用的常用元素,从基本到复杂,我们将在本教程中介绍。

  • Layouts - 它们定义了如何在屏幕上组织UI元素,并为GUI(图形用户界面)提供最终外观。 这一部分将在布局章节中介绍。

  • Behavior - 这些是用户与UI元素交互时发生的事件。 这部分将在事件处理章节中介绍。

GWT UI元素

GWT库在明确定义的类层次结构中提供类,以创建复杂的基于Web的用户界面。 此组件层次结构中的所有类都是从UIObject基类派生的,如下所示 -

GWT组件

每个Basic UI小部件都从Widget类继承属性,Widget类继承UIObject的属性。 树和菜单将包含在复杂的小部件教程中。

Sr.No. 小部件和描述
1 GWT UIObject类

此窗口小部件包含文本,不使用

元素解释为HTML,从而使其以块布局显示。
2 GWT Widget类

此窗口小部件可以包含HTML文本,并使用

元素显示html内容,使其以块布局显示。

基本小部件

以下是几个重要的Basic Widgets -

Sr.No. 小部件和描述
1 Label

此窗口小部件包含文本,不使用

元素解释为HTML,从而使其以块布局显示。
2 HTML

此窗口小部件可以包含HTML文本,并使用

元素显示html内容,使其以块布局显示。
3 Image

此小组件显示给定URL的图像。

4 Anchor

此小部件表示一个简单的元素。

GWT - Form Widgets

表单小部件允许用户输入数据并为应用程序提供交互功能。 每个Form小部件都从Widget类继承属性,Widget类继承UIObject和Wigdet类的属性。

Sr.No. 小部件和描述
1 GWT UIObject类

此窗口小部件包含文本,不使用

元素解释为HTML,从而使其以块布局显示。
2 GWT Widget类

此窗口小部件可以包含HTML文本,并使用

元素显示html内容,使其以块布局显示。

表单小部件

以下是几个重要的Form Widgets -

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 元素。

13 Hidden

此小部件表示HTML表单中的隐藏字段。

GWT - Complex Widgets

“复杂小部件”允许用户与应用程序进行高级交互功能。 每个Complex小部件都从Widget类继承属性,Widget类继承UIObject的属性。

Sr.No. 小部件和描述
1 GWT UIObject类

此窗口小部件包含文本,不使用

元素解释为HTML,从而使其以块布局显示。
2 GWT Widget类

此窗口小部件可以包含HTML文本,并使用

元素显示html内容,使其以块布局显示。

复杂小部件

以下是一些重要的复杂小部件 -

Sr.No. 小部件和描述
1 Tree

此小组件表示标准分层树小组件。 树包含TreeItem的层次结构,用户可以打开,关闭和选择。

2 MenuBar

此小组件代表标准菜单栏小部件。 菜单栏可以包含任意数量的菜单项,每个菜单项可以触发命令或打开级联菜单栏。

3 DatePicker

此小组件代表标准GWT日期选择器。

4 CellTree

此小组件表示树的视图。 此小部件仅在标准模式下工作,这要求运行它的HTML页面具有明确的声明。

5 CellList

此小组件表示单个列的单元格列表。

6 CellTable

此小组件表示支持分页和列的表格视图。

7 CellBrowser

此窗口小部件表示树的browsable视图,其中每个级别只能打开一个节点。 此小部件仅在标准模式下工作,这要求运行它的HTML页面具有明确的“!DOCTYPE”声明。

GWT - Layout Panels

布局面板可以包含其他小部件。 这些面板控制在用户界面上显示小部件的方式。 每个Panel小部件都从Panel类继承属性,而Panel类继承Widget类的属性,而后者继承UIObject类的属性。

Sr.No. 小部件和描述
1 GWT UIObject类

此窗口小部件包含文本,不使用

元素解释为HTML,从而使其以块布局显示。
2 GWT Widget类

此窗口小部件可以包含HTML文本,并使用

元素显示html内容,使其以块布局显示。
3 GWT小组课程

这是所有面板的抽象基类,它是可以包含其他小部件的小部件。

布局面板

以下是几个重要的Layout Panels -

Sr.No. 小部件和描述
1 FlowPanel

此窗口小部件表示使用默认HTML布局行为格式化其子窗口小部件的面板。

2 HorizontalPanel

此窗口小部件表示一个面板,它将所有窗口小部件放在一个水平列中。

3 VerticalPanel

此窗口小部件表示一个面板,它将所有窗口小部件放在一个垂直列中。

4 HorizontalSplitPanel

此窗口小部件表示一个面板,它在单个水平行中排列两个窗口小部件,并允许用户以交互方式更改专用于两个窗口小部件中每个窗口小部件的宽度比例。 必要时,Horizo​​ntalSplitPanel中包含的小部件将使用滚动条自动修饰。

5 VerticalSplitPanel

此窗口小部件表示一个A面板,它在单个垂直列中排列两个窗口小部件,并允许用户以交互方式更改专用于两个窗口小部件中每个窗口小部件的高度比例。 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

元素中的面板。
17 PopupPanel

此窗口小部件表示可以pop up其他窗口小部件的面板。 它覆盖了浏览器的客户区(以及任何以前创建的弹出窗口)。

18 DialogBox

此窗口小部件表示一种弹出窗口,其顶部有一个标题区域,可由用户拖动。 与PopupPanel不同,对PopupPanel.setWidth(String)和PopupPanel.setHeight(String)的调用将设置对话框本身的宽度和高度,即使尚未添加窗口小部件。

GWT - Event Handling

GWT提供类似于Java AWT或SWING用户界面框架的事件处理程序模型。

  • 侦听器接口定义窗口小部件调用以宣告事件的一个或多个方法。 GWT提供与各种可能事件对应的接口列表。

  • 希望接收特定类型事件的类实现关联的处理程序接口,然后将对其自身的引用传递给窗口小部件以订阅一组事件。

例如, Button类发布click events因此您必须编写一个类来实现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()来注册事件处理程序,如下所示 -

/**
 * create button and attach click handler
 */
Button button = new Button("Click Me!");
button.addClickHandler(new MyClickHandler());

支持事件类型的每个小部件将具有HandlerRegistration形式的方法添加Foo Handler( Foo事件),其中Foo是实际事件,如Click,Error,KeyPress等。

以下是重要的GWT事件处理程序和相关事件以及处理程序注册方法的列表 -

Sr.No. 事件接口 事件方法和描述
1 在选择处理程序之前

void on Before Selection (Before Selection Event《I》 event);

在触发BeforeSelectionEvent时调用。

2BlurHandler

void on Blur(Blur Event event);

在模糊事件被触发时调用。

3ChangeHandler

void on Change(ChangeEvent event);

触发更改事件时调用。

4ClickHandler

void on Click(ClickEvent event);

触发本机点击事件时调用。

5CloseHandler<T>

void on Close(CloseEvent《T》 event);

在触发CloseEvent时调用。

6 上下文菜单处理程序

void on Context Menu(Context Menu Event event);

在触发本机上下文菜单事件时调用。

7 双击处理程序

void on Double Click(Double Click Event event);

触发双击事件时调用。

8 错误处理程序

void on Error(Error Event event);

触发错误事件时调用。

9 焦点处理程序

void on Focus(Focus Event event);

在Focus事件被触发时调用。

10 Form Panel.Submit Complete Handler

void on Submit Complete(Form Panel.Submit Complete Event event);

成功提交表单时触发。

11FormPanel.SubmitHandler

void on Submit(Form Panel.Submit Event event);

提交表单时触发。

12 按键处理程序

void on Key Down(Key Down Event event);

在触发KeyDownEvent时调用。

13KeyPressHandler

void on KeyPress(KeyPressEvent event);

触发KeyPressEvent时调用。

14KeyUpHandler

void on KeyUp(KeyUpEvent event);

在触发KeyUpEvent时调用。

15LoadHandler

void on Load(LoadEvent event);

在触发LoadEvent时调用。

16MouseDownHandler

void on MouseDown(MouseDownEvent event);

在MouseDown被触发时调用。

17MouseMoveHandler

void on MouseMove(MouseMoveEvent event);

在触发MouseMoveEvent时调用。

18MouseOutHandler

void on MouseOut(MouseOutEvent event);

在触发MouseOutEvent时调用。

19MouseOverHandler

void on MouseOver(MouseOverEvent event);

在触发MouseOverEvent时调用。

20MouseUpHandler

void on MouseUp(MouseUpEvent event);

在MouseUpEvent被触发时调用。

21MouseWheelHandler

void on MouseWheel(MouseWheelEvent event);

在触发MouseWheelEvent时调用。

22ResizeHandler

void on Resize(ResizeEvent event);

调整窗口小部件时触发。

23ScrollHandler

void on Scroll(ScrollEvent event);

触发ScrollEvent时调用。

24SelectionHandler<I>

void on Selection(SelectionEvent《I》 event);

在SelectionEvent被触发时调用。

25ValueChangeHandler<I>

void on ValueChange(ValueChangeEvent《I》 event);

触发ValueChangeEvent时调用。

26Window.ClosingHandler

void on WindowClosing(Window.ClosingEvent event);

在浏览器窗口关闭或导航到其他站点之前触发。

27Window.ScrollHandler

void on WindowScroll(Window.ScrollEvent event);

滚动浏览器窗口时触发。

事件方法

如前所述,每个处理程序都有一个方法,其中包含一个保存事件对象的参数,例如void onClick(ClickEvent event)void onKeyDown(KeyDownEvent event)ClickEventKeyDownEvent等事件对象的常用方法很少,如下所示 -

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()此方法终止事件

例子 (Example)

此示例将指导您完成在GWT中显示Click事件和KeyDown事件处理的使用的简单步骤。 按照以下步骤更新我们在GWT - Create Application的GWT应用程序GWT - Create Application章节 -

描述
1com.iowiki包下创建一个名为HelloWorld的项目,如GWT - Create Application一章中所述。
2 修改HelloWorld.gwt.xmlHelloWorld.cssHelloWorld.htmlHelloWorld.java ,如下所述。 保持其余文件不变。
3 编译并运行应用程序以验证实现的逻辑的结果。

以下是修改后的模块描述符src/com.iowiki/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.iowiki.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.iowiki/HelloWorld.java ,它将演示在GWT中使用事件处理。

package com.iowiki.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 - Custom Widgets

GWT提供了三种创建自定义用户界面元素的方法。 有三种一般策略可供遵循 -

  • Create a widget by extending Composite Class - 这是创建自定义小部件的最常用和最简单的方法。 在这里,您可以使用现有小部件来创建具有自定义属性的复合视图。

  • Create a widget using GWT DOM API in JAVA - 以这种方式创建GWT基本窗口小部件。 仍然是创建自定义小部件的一种非常复杂的方式,应谨慎使用。

  • Use JavaScript and wrap it in a widget using JSNI - 这通常只能作为最后的手段来完成。 考虑到本机方法的跨浏览器含义,它变得非常复杂并且也变得更难以调试。

使用复合类创建自定义小组件

此示例将指导您完成在GWT中创建自定义窗口小部件的简单步骤。 按照以下步骤更新我们在GWT - Basic Widgets章节中创建的GWT应用程序 -

这里我们将通过扩展Composite类来创建自定义小部件,这是构建自定义小部件的最简单方法。

描述
1com.iowiki包下创建一个名为HelloWorld的项目,如GWT - Create Application一章中所述。
2 修改HelloWorld.gwt.xmlHelloWorld.cssHelloWorld.htmlHelloWorld.java ,如下所述。 保持其余文件不变。
3 编译并运行应用程序以验证实现的逻辑的结果。

以下是修改后的模块描述符src/com.iowiki/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.iowiki.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.iowiki/HelloWorld.java ,它将演示Custom小部件的创建。

package com.iowiki.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) {
         // place the check above the text box using a vertical panel.
         HorizontalPanel panel = new HorizontalPanel();
         // panel.setBorderWidth(1);
         panel.setSpacing(10);
         panel.add(checkBox);
         panel.add(textBox);
         // all composites must call initWidget() in their constructors.
         initWidget(panel);
         //set style name for entire widget
         setStyleName("optionalTextWidget");
         //set style name for text box
         textBox.setStyleName("optionalTextBox");
         //set style name for check box
         checkBox.setStyleName("optionalCheckBox");
         textBox.setWidth("200");
         // Set the check box's caption, and check it by default.
         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() {
      // Create an optional text box and add it to the root panel.
      OptionalTextBox otb = new OptionalTextBox(
         "Want to explain the solution?");
      otb.setEnabled(true);
      RootPanel.get().add(otb);
   }    
} 

一旦准备好完成所有更改,让我们像在GWT - 创建应用程序章节中那样在开发模式下编译和运行应用程序 。 如果您的应用程序一切正常,这将产生以下结果 -

GWT Custom Widget

You can notice following points

  • 通过扩展Composite小部件来创建Custom Widget非常简单。

  • 我们使用GWT内置小部件,TextBox和CheckBox创建了一个小部件,因此使用了可重用性的概念。

  • 根据复选框的状态禁用/启用TextBox。 我们提供了一个API来启用/禁用控件。

  • 我们通过记录的CSS样式公开了内部小部件样式。

GWT - UiBinder

介绍 (Introduction)

UiBinder是一个旨在分离功能和用户界面视图的框架。

  • UiBinder框架允许开发人员将gwt应用程序构建为HTML页面,并在其中配置GWT小部件。

  • UiBinder框架使与UI设计人员的协作变得更容易,他们比XML源代码更熟悉XML,HTML和CSS

  • UIBinder提供了一种定义用户界面的声明方式。

  • UIBinder从UI中分离出程序逻辑。

  • UIBinder类似于JSP对Servlets的作用。

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.iowiki.client.LoginResources'>
   <ui:with type = "com.iowiki.client.LoginResources" field = "res">
   </ui:with>
   <gwt:HTMLPanel>
   ...  
   </gwt:HTMLPanel>
</ui:UiBinder> 

第2步:使用ui:字段进行后期绑定

使用XML/HTML元素中的ui:field属性将XML中的UI字段与JAVA文件中的UI字段相关联,以便以后绑定。

<gwt:Label ui:field = "completionLabel1" />
<gwt:Label ui:field = "completionLabel2" />       

第3步:创建UI XML的Java对应物

通过扩展Composite小部件,创建基于XML的基于XML的布局。 我们在示例中创建了一个Login.java文件。

package com.iowiki.client;
   ...
public class Login extends Composite {
   ...
}

步骤4:使用UiField批注绑定Java UI字段

Login.java使用@UiField注释来指定要在Login.java中绑定到基于XML的字段的对应类成员

public class Login extends Composite {
   ...
   @UiField
   Label completionLabel1;
   @UiField
   Label completionLabel2;  
   ...
}

步骤5:使用带有UiTemplate注释的UI XML绑定Java UI

指示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和基于Java的Resource LoginResources.java文件,相当于css样式

.blackText {
   font-family: Arial, Sans-serif;
   color: #000000;
   font-size: 11px;
   text-align: left;
}
...

步骤7:为CSS文件创建基于Java的资源文件

package com.iowiki.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.java

public Login() {
   this.res = GWT.create(LoginResources.class);
   res.style().ensureInjected();
   initWidget(uiBinder.createAndBindUi(this));
}

UIBinder完整示例

此示例将指导您完成在GWT中显示UIBinder使用情况的简单步骤。 按照以下步骤更新我们在GWT - Create Application的GWT应用程序GWT - Create Application章节 -

描述
1com.iowiki包下创建一个名为HelloWorld的项目,如GWT - Create Application一章中所述。
2 修改HelloWorld.gwt.xmlHelloWorld.cssHelloWorld.htmlHelloWorld.java ,如下所述。 保持其余文件不变。
3 编译并运行应用程序以验证实现的逻辑的结果。

以下是修改后的模块描述符src/com.iowiki/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.iowiki.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)。

GWT UiBinder向导步骤1

选择项目的客户端软件包,然后将其命名为Login。 保留所有其他默认值。 单击Finish按钮,插件将创建一个新的UiBinder模板和所有者类。

GWT UiBinder向导步骤2

现在在src/com.iowiki/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.iowiki/client包中创建LoginResources.java文件并在其中放置以下内容

package com.iowiki.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.iowiki/client包中的src/com.iowiki/client的内容

<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.iowiki.client.LoginResources'>
   <ui:with type = "com.iowiki.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.iowiki/client包中的src/com.iowiki/client的内容

package com.iowiki.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.iowiki/HelloWorld.java ,它将演示UiBinder的使用。

package com.iowiki.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 UiBinder演示

GWT - RPC Communication

基于GWT的应用程序通常由客户端模块和服务器端模块组成。 客户端代码在浏览器中运行,服务器端代码在Web服务器中运行。 客户端代码必须在网络上发出HTTP请求才能访问服务器端数据。

RPC,远程过程调用是GWT使用的机制,其中客户端代码可以直接执行服务器端方法。

  • GWT RPC是基于servlet的。

  • GWT RPC是异步的,客户端在通信期间从不被阻止。

  • 使用GWT RPC Java对象可以直接在客户端和服务器之间发送(由GWT框架自动序列化)。

  • 服务器端servlet称为service

  • 从客户端代码调用服务器端servlet方法的远程过程调用称为invoking a service

GWT RPC组件

以下是GWT RPC通信机制中使用的三个组件

  • 在服务器上运行的远程服务(服务器端servlet)。
  • 用于调用该服务的客户端代码。
  • 将在客户端和服务器之间传递的Java数据对象。

GWT客户端和服务器都自动序列化和反序列化数据,因此开发人员不需要序列化/反序列化对象,数据对象可以通过HTTP传输。

下图显示了RPC体系结构。

GWT 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.iowiki.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处理程序以处理RPC回调,其中服务器将Message返回给客户端

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 - Create Application的GWT应用程序GWT - Create Application章节 -

描述
1com.iowiki包下创建一个名为HelloWorld的项目,如GWT - Create Application一章中所述。
2 修改HelloWorld.gwt.xmlHelloWorld.cssHelloWorld.htmlHelloWorld.java ,如下所述。 保持其余文件不变。
3 编译并运行应用程序以验证实现的逻辑的结果。

以下是修改后的模块描述符src/com.iowiki/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.iowiki.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.iowiki/client包中创建Message.java文件,并在其中放置以下内容

package com.iowiki.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.iowiki/client包中创建MessageService.java文件,并在其中放置以下内容

package com.iowiki.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.iowiki/client包中创建MessageServiceAsync.java文件并在其中放置以下内容

package com.iowiki.client;
import com.google.gwt.user.client.rpc.AsyncCallback;
public interface MessageServiceAsync {
   void getMessage(String input, AsyncCallback<Message> callback);
}

现在在src/com.iowiki/server包中创建MessageServiceImpl.java文件并在其中放置以下内容

package com.iowiki.server;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import com.iowiki.client.Message;
import com.iowiki.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.iowiki.server.MessageServiceImpl
      </servlet-class>
   </servlet>
   <servlet-mapping>
      <servlet-name>messageServiceImpl</servlet-name>
      <url-pattern>/helloworld/message</url-pattern>
   </servlet-mapping>
</web-app>

使用以下内容替换src/com.iowiki/client包中的HelloWorld.java的内容

package com.iowiki.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) {
         /* server side error occured */
         Window.alert("Unable to obtain server response: " + caught.getMessage());	
      }
      @Override
      public void onSuccess(Message result) {
          /* server returned result, show user the message */
         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){
               /* make remote call to server to get the message */
               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) {
            /* make remote call to server to get the message */
            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);
      // Add widgets to the root panel.
      RootPanel.get("gwtContainer").add(panel);
   }    
} 

一旦准备好完成所有更改,让我们像在GWT - 创建应用程序章节中那样在开发模式下编译和运行应用程序 。 如果您的应用程序一切正常,这将产生以下结果 -

GWT RPC演示

GWT - JUnit Integration

GWT使用JUnit测试框架为客户端代码的自动测试提供了极好的支持。 在本文中,我们将演示GWT和JUNIT集成。

下载Junit存档

JUnit官方网站 - http://www.junit.org

下载Junit-4.10.jar

OS 存档名称
Windowsjunit4.10.jar
Linuxjunit4.10.jar
Macjunit4.10.jar

将下载的jar文件存储到计算机上的某个位置。 我们把它存放在C:/ 》 JUNIT

找到GWT安装文件夹

OS GWT安装文件夹
WindowsC:\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.iowiki.HelloWorld

值得注意的要点

  • 我们正在执行webAppCreator命令行实用程序。
  • HelloWorld是要创建的项目的名称
  • -junit选项指示webAppCreator将junit suppport添加到项目中
  • com.iowiki.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\iowiki
Created directory HelloWorld\src\com\iowiki\client
Created directory HelloWorld\src\com\iowiki\server
Created directory HelloWorld\src\com\iowiki\shared
Created directory HelloWorld\test\com\iowiki
Created directory HelloWorld\test\com\iowiki\client
Created file HelloWorld\src\com\iowiki\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\iowiki\client\HelloWorld.java
Created file 
HelloWorld\src\com\iowiki\client\GreetingService.java
Created file 
HelloWorld\src\com\iowiki\client\GreetingServiceAsync.java
Created file 
HelloWorld\src\com\iowiki\server\GreetingServiceImpl.java
Created file HelloWorld\src\com\iowiki\shared\FieldVerifier.java
Created file HelloWorld\build.xml
Created file HelloWorld\README.txt
Created file HelloWorld\test\com\iowiki\HelloWorldJUnit.gwt.xml
Created file HelloWorld\test\com\iowiki\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.iowiki.client;
import com.iowiki.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 tests must extend GWTTestCase.
 */
public class HelloWorldTest extends GWTTestCase {
   /**
    * must refer to a valid module that sources this class.
    */
   public String getModuleName() {
      return "com.iowiki.HelloWorldJUnit";
   }
   /**
    * tests the 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"));
   }
   /**
    * this test will send a request to the server using the greetServer
    *  method in GreetingService and verify the response.
    */
   public void testGreetingService() {
      /* create the service that we will test. */
      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);
      /* send a request to the server. */
      greetingService.greetServer("GWT User", 
         new AsyncCallback<String>() {
         public void onFailure(Throwable caught) {
            /* The request resulted in an unexpected error. */
            fail("Request failure: " + caught.getMessage());
         }
         public void onSuccess(String result) {
            /* verify that the response is correct. */
            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.iowiki.client包中生成的。
2 HelloWorldTest类将包含HelloWorld的单元测试用例。
3 HelloWorldTest类扩展了com.google.gwt.junit.client包中的GWTTestCase类。
4 HelloWorldTest类有一个抽象方法(getModuleName),它必须返回GWT模块的名称。 对于HelloWorld,这是com.iowiki.HelloWorldJUnit。
5 生成HelloWorldTest类有两个示例测试用例testFieldVerifier,testSimple。 我们添加了testGreetingService。
6 这些方法使用从JUnit Assert类继承的许多assert *函数之一,该类是GWTTestCase的祖先。
7 assertTrue(boolean)函数断言传入的boolean参数的计算结果为true。 如果不是,则在JUnit中运行时测试将失败。

GWT - JUnit集成完整示例

此示例将指导您完成在GWT中显示JUnit Integration示例的简单步骤。

按照以下步骤更新我们在上面创建的GWT应用程序 -

描述
1 使用导入现有项目向导(文件→导入→常规→现有项目到工作空间)在eclipse中使用名称HelloWorld导入项目。
2 修改HelloWorld.gwt.xmlHelloWorld.cssHelloWorld.htmlHelloWorld.java ,如下所述。 保持其余文件不变。
3 编译并运行应用程序以验证实现的逻辑的结果。

以下是eclipse中的项目结构。

项目结构

以下是修改后的模块描述符src/com.iowiki/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.iowiki.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.iowiki/client包中的HelloWorld.java的内容

package com.iowiki.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);
      // Add widgets to the root panel.
      RootPanel.get("gwtContainer").add(panel);
   }  
   public String getGreeting(String name){
      return "Hello "+name+"!";
   }
} 

使用以下内容替换test/com.iowiki/client包中的HelloWorldTest.java的内容

package com.iowiki.client;
import com.iowiki.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 tests must extend GWTTestCase.
 */
public class HelloWorldTest extends GWTTestCase {
   /**
    * must refer to a valid module that sources this class.
    */
   public String getModuleName() {
      return "com.iowiki.HelloWorldJUnit";
   }
   /**
    * tests the 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"));
   }
   /**
    * this test will send a request to the server using the greetServer
    *  method in GreetingService and verify the response.
    */
   public void testGreetingService() {
      /* create the service that we will test. */
      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);
      /* send a request to the server. */
      greetingService.greetServer("GWT User", 
         new AsyncCallback<String>() {
         public void onFailure(Throwable caught) {
            /* The request resulted in an unexpected error. */
            fail("Request failure: " + caught.getMessage());
         }
         public void onSuccess(String result) {
            /* verify that the response is correct. */
            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();
         }
      });
      /**
       * tests the getGreeting method.
       */
      public void testGetGreeting() {
         HelloWorld helloWorld = new HelloWorld();
         String name = "Robert";
         String expectedGreeting = "Hello "+name+"!";
         assertEquals(expectedGreeting,helloWorld.getGreeting(name));
      }
   }
}

使用生成的启动配置在Eclipse中运行测试用例。

我们将使用webAppCreator为开发模式和生产模式生成的启动配置在Eclipse中运行单元测试。

在开发模式下运行JUnit测试。

  • 从Eclipse菜单栏中,选择Run→Run Configurations ...
  • 在JUnit部分下,选择HelloWorldTest-dev
  • 要将更改保存到参数,请按“应用”
  • 要运行测试,请按“运行”

如果您的应用程序一切正常,这将产生以下结果 -

GWT Junit结果

在生产模式下运行JUnit测试。

  • 从Eclipse菜单栏中,选择Run→Run Configurations ...
  • 在JUnit部分下,选择HelloWorldTest-prod
  • 要将更改保存到参数,请按“应用”
  • 要运行测试,请按“运行”

如果您的应用程序一切正常,这将产生以下结果 -

GWT Junit结果

GWT - Debugging Application

GWT提供了调试客户端和服务器端代码的强大功能。

在开发模式期间,GWT Application基于Java代码,不会转换为JavaScript。

当应用程序在开发模式下运行时,Java虚拟机(JVM)实际上将应用程序代码作为编译的Java字节码执行,使用GWT功能连接到浏览器窗口。

GWT使用基于浏览器的插件连接到JVM。

因此,开发人员可以自由地使用任何基于Java的IDE来调试客户端GWT代码以及服务器端代码。

在本文中,我们将演示如何使用Eclipse调试GWT客户端代码。 我们将完成以下任务 -

  • 在代码中设置断点并在BreakPoint Explorer中查看它们。
  • 在调试期间逐行执行代码。
  • 查看变量的值。
  • 检查所有变量的值。
  • 检查表达式的值。
  • 显示悬挂线程的堆栈帧。

调试示例

此示例将指导您演示调试GWT应用程序的简单步骤。 按照以下步骤更新我们在GWT - Create Application的GWT应用程序GWT - Create Application章节 -

描述
1com.iowiki包下创建一个名为HelloWorld的项目,如GWT - Create Application一章中所述。
2 修改HelloWorld.gwt.xmlHelloWorld.cssHelloWorld.htmlHelloWorld.java ,如下所述。 保持其余文件不变。
3 编译并运行应用程序以验证实现的逻辑的结果。

以下是修改后的模块描述符src/com.iowiki/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.iowiki.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.iowiki/HelloWorld.java ,我们将使用它来演示GWT Code的调试功能。

package com.iowiki.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);
      // Add widgets to the root panel.
      RootPanel.get("gwtContainer").add(panel);
   }  
   public String getGreeting(String name){
      return "Hello "+name+"!";
   }
} 

第1步 - 放置BreakPoints

在HelloWorld.java的onModuleLoad()的第一行放置一个断点

GWT应用断点

第2步 - 调试应用程序

现在点击 调试应用程序 调试应用程序菜单并选择HelloWorld应用程序来调试应用程序。

GWT调试按钮

如果一切正常,您必须在Eclipse中看到包含URL的GWT开发模式,如下所示。 双击URL以打开GWT应用程序。

GWT调试应用程序

一旦Application启动,您将看到关注Eclipse断点,因为我们已将断点放在入口点方法的第一行。

GWT调试应用程序

您可以看到挂起线程的堆栈跟踪。

GWT Debug Stacktrace

您可以看到表达式的值。

GWT调试表达式

您可以看到放置的断点列表。

GWT调试断点

现在继续按F6直到到达onModuleLoad()方法的最后一行。 作为功​​能键的参考,F6逐行检查代码,F5逐步进入内部,F8将恢复应用程序。 现在,您可以看到onModuleLoad()方法的所有变量的值列表。

GWT调试变量

可以使用与调试Java应用程序相同的方式调试GWT客户端代码。 将断点放在任何一行,并使用GWT的调试功能。

GWT - Internationalization

GWT提供了三种方式来实现GWT应用程序的国际化。我们将演示静态字符串国际化在项目中最常用的用法。

Sr.No. 技术与描述
1

Static String Internationalization

这种技术最为普遍,在运行时只需要很少的开销; 是一种非常有效的翻译常量和参数化字符串的技术;最简单的实现。

静态字符串国际化使用标准Java属性文件来存储已翻译的字符串和参数化消息,并创建强类型的Java接口以检索其值。

2

Dynamic String Internationalization

这种技术非常灵活,但比静态字符串国际化要慢。 主机页面包含本地化字符串,因此,当我们添加新的语言环境时,不需要重新编译应用程序。 如果要将GWT应用程序与现有服务器端本地化系统集成,则应使用此技术。

3

Localizable Interface

这种技术是三种技术中最强大的。 实现Localizable允许我们创建自定义类型的本地化版本。 这是一种先进的国际化技术。

国际化GWT应用程序的工作流程

第1步:创建属性文件

创建包含要在应用程序中使用的消息的属性文件。 我们在示例中创建了一个HelloWorldMessages.properties文件。

enterName = Enter your name
clickMe = Click Me
applicationTitle = Application Internationalization Demonstration
greeting = Hello {0}

创建包含特定于语言环境的翻译值的属性文件。 我们在示例中创建了一个HelloWorldMessages_de.properties文件。 此文件包含德语翻译。 _de指定德语区域设置,我们将在我们的应用程序中支持德语。

如果要使用Eclipse创建属性文件,请将文件的编码更改为Other UTF-8 。选择该文件,然后在其中右键单击以打开其属性窗口。选择文本文件编码为Other UTF-8 。 应用并保存更改。

enterName = Geben Sie Ihren Namen
clickMe = Klick mich
applicationTitle = Anwendung Internationalisierung Demonstration
greeting = Hallo {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接口,以包括对内部化的支持。 它应包含与属性文件中的键相同的方法名称。 占位符将替换为String参数。

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组件中使用消息接口。

HelloWorldMessages中使用HelloWorld对象来获取消息。

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 - Create Application的GWT应用程序GWT - Create Application章节 -

描述
1com.iowiki包下创建一个名为HelloWorld的项目,如GWT - Create Application一章中所述。
2 修改HelloWorld.gwt.xmlHelloWorld.cssHelloWorld.htmlHelloWorld.java ,如下所述。 保持其余文件不变。
3 编译并运行应用程序以验证实现的逻辑的结果。

以下是修改后的模块描述符src/com.iowiki/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.iowiki.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.iowiki/client包中创建HelloWorldMessages.properties文件并在其中放置以下内容

enterName = Enter your name
clickMe = Click Me
applicationTitle = Application Internationalization Demonstration
greeting = Hello {0}

现在在src/com.iowiki/client包中创建HelloWorldMessages_de.properties文件并在其中放置以下内容

enterName = Geben Sie Ihren Namen
clickMe = Klick mich
applicationTitle = Anwendung Internationalisierung Demonstration
greeting = Hallo {0}

现在在src/com.iowiki/client包中创建HelloWorldMessages.java类并将以下内容放入其中

package com.iowiki.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.iowiki/HelloWorld.java ,我们将使用它来演示GWT Code的国际化能力。

package com.iowiki.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);
      // Add widgets to the root panel.
      RootPanel.get("gwtContainer").add(panel);
   }  
   public String getGreeting(String name){
      return messages.greeting(name + "!");
   }
} 

一旦准备好完成所有更改,让我们像在GWT - 创建应用程序章节中那样在开发模式下编译和运行应用程序 。 如果您的应用程序一切正常,这将产生以下结果 -

GWT国际化演示

现在更新URL以包含locale = de.Set URL - http://127.0.0.1:8888/HelloWorld.html?gwt.codesvr=127.0.0.1:9997 &locale=de 。 如果您的应用程序一切正常,这将产生以下结果 -

GWT实习德语

GWT - History Class

GWT应用程序通常是运行JavaScripts的单页面应用程序,并且不包含大量页面,因此浏览器不会跟踪用户与Application的交互。 要使用浏览器的历史记录功能,应用程序应为每个可导航页面生成唯一的URL片段。

GWT提供History Mechanism来处理这种情况。

GWT使用一个术语token ,它只是一个应用程序可以解析为返回特定状态的字符串。 应用程序将此标记作为URL片段保存在浏览器的历史记录中。

例如,名为“pageIndex1”的历史记录将添加到URL,如下所示 -

http://www.iowiki.com/HelloWorld.html#pageIndex0

历史管理工作流程

第1步:启用历史记录支持

为了使用GWT History支持,我们必须首先将以下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);
      }
   }
});	

现在让我们看看行动中的历史类。

历史课 - 完整的例子

此示例将指导您完成演示GWT应用程序的历史记录管理的简单步骤。 按照以下步骤更新我们在GWT - Create Application的GWT应用程序GWT - Create Application章节 -

描述
1com.iowiki包下创建一个名为HelloWorld的项目,如GWT - Create Application一章中所述。
2 修改HelloWorld.gwt.xmlHelloWorld.cssHelloWorld.htmlHelloWorld.java ,如下所述。 保持其余文件不变。
3 编译并运行应用程序以验证实现的逻辑的结果。

以下是修改后的模块描述符src/com.iowiki/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.iowiki.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.iowiki/HelloWorld.java ,我们将使用它来演示GWT Code中的历史管理。

package com.iowiki.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 - 创建应用程序章节中那样在开发模式下编译和运行应用程序 。 如果您的应用程序一切正常,这将产生以下结果 -

GWT历史演示
  • 现在单击每个选项卡以选择不同的页面。

  • 您应该注意到,当选择每个选项卡时,将更改应用程序URL并将#pageIndex添加到URL。

  • 您还可以看到浏览器的后退和前进按钮现在已启用。

  • 使用浏览器的后退和前进按钮,您将看到相应的选项被选中。

GWT - Bookmark Support

GWT使用History类支持浏览器历史记录管理,您可以参考GWT - History Class章节。

GWT使用一个术语token ,它只是一个应用程序可以解析为返回特定状态的字符串。 应用程序将此标记作为URL片段保存在浏览器的历史记录中。

GWT - History Class章节中,我们通过编写代码来处理GWT - History Class的令牌创建和设置。

在本文中,我们将讨论一个特殊的小部件Hyperlink,它自动为我们完成令牌创建和历史管理,并提供书签的应用程序功能。

书签示例

此示例将指导您完成演示GWT应用程序的书签的简单步骤。

以下步骤更新我们在GWT - Create Application的GWT应用程序GWT - Create Application章节 -

描述
1com.iowiki包下创建一个名为HelloWorld的项目,如GWT - Create Application一章中所述。
2 修改HelloWorld.gwt.xmlHelloWorld.cssHelloWorld.htmlHelloWorld.java ,如下所述。 保持其余文件不变。
3 编译并运行应用程序以验证实现的逻辑的结果。

以下是修改后的模块描述符src/com.iowiki/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.iowiki.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.iowiki/HelloWorld.java ,我们将使用它来演示GWT代码中的书签。

package com.iowiki.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 - 创建应用程序章节中那样在开发模式下编译和运行应用程序 。 如果您的应用程序一切正常,这将产生以下结果 -

GWT书签演示
  • 现在单击1,2或3.您可以注意到选项卡随索引一起更改。

  • 您应该注意到,当您单击1,2或3时,应用程序URL将更改,并且#pageIndex将添加到该URL

  • 您还可以看到浏览器的后退和前进按钮现在已启用。

  • 使用浏览器的后退和前进按钮,您将看到相应的选项被选中。

  • 右键单击1,2或3.您可以看到打开,在新窗口中打开,在新选项卡中打开,添加到收藏夹等选项。

  • 右键单击3.选择添加到收藏夹。 将书签保存为第3页。

  • 打开收藏夹并选择第3页。您将看到选中的第三个选项卡。

GWT - Logging Framework

日志记录框架模拟java.util.logging,因此它使用相同的语法并具有与服务器端日志记录代码相同的行为

使用.gwt.xml文件配置GWT日志记录。

我们可以配置启用/禁用日志记录; 我们可以启用/禁用特定处理程序,并更改默认日志记录级别。

记录器的类型

记录器以树结构组织,根记录器位于树的根部。

记录器的名称确定使用的父/子关系. 分隔名称的部分。

举个例子,如果我们有两个记录器Hospital.room1和Hospital.room2,那么他们就是兄弟姐妹,他们的父母是名为Hospital的记录器。 医院记录器(以及任何名称不包含点“。”的记录器)将根记录器作为父记录器。

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提供默认处理程序,它将显示使用记录器创建的日志条目。

处理器 登录到 描述
SystemLogHandlerstdout 这些消息只能在DevMode窗口的开发模式中看到。
DevelopmentModeLogHandlerDevMode Window 通过调用方法GWT.log进行日志记录。 这些消息只能在DevMode窗口的开发模式中看到。
ConsoleLogHandler javascript控制台 登录到firebug Lite(适用于IE),Safari和Chrome使用的javascript控制台。
FirebugLogHandlerFirebug 登录到firebug控制台。
PopupLogHandlerpopup 启用此处理程序时,记录位于应用程序左上角的弹出窗口。
SimpleRemoteLogHandlerserver 此处理程序将日志消息发送到服务器,使用服务器端日志记录机制记录它们。

配置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" /> 

使用记录器记录用户操作

/* Create Root Logger */
private static Logger rootLogger = Logger.getLogger("");
...
rootLogger.log(Level.SEVERE, "pageIndex selected: " + event.getValue());
...

记录框架示例

此示例将指导您完成演示GWT应用程序的日志记录功能的简单步骤。 按照以下步骤更新我们在GWT - Create Application的GWT应用程序GWT - Create Application章节 -

描述
1com.iowiki包下创建一个名为HelloWorld的项目,如GWT - Create Application一章中所述。
2 修改HelloWorld.gwt.xmlHelloWorld.cssHelloWorld.htmlHelloWorld.java ,如下所述。 保持其余文件不变。
3 编译并运行应用程序以验证实现的逻辑的结果。

以下是修改后的模块描述符src/com.iowiki/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.iowiki.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.iowiki/HelloWorld.java ,我们将使用它来演示GWT代码中的书签。

package com.iowiki.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 - 创建应用程序章节中那样在开发模式下编译和运行应用程序 。 如果您的应用程序一切正常,这将产生以下结果 -

GWT记录演示

现在单击1,2或3.您可以注意到,当您单击1,2或3时,您可以看到显示pageIndex的日志正在打印。 检查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.iowiki/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.iowiki.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时,您可以看到日志正在打印,在弹出窗口中显示pageIndex。

GWT Popup Logging演示
↑回到顶部↑
WIKI教程 @2018