`
fastwind
  • 浏览: 324409 次
  • 性别: Icon_minigender_1
  • 来自: 天津
社区版块
存档分类
最新评论

GWT 入门介绍(续)

阅读更多

GWT 入门介绍(续)

功能介绍(集成JUnit)

@TODO


功能介绍(国际化)

      项目开发过程中经常需要一些可配置的常量,例如查询最大条数,目录位置等。在传统的Java应用程序中这些内容通常会放在

属性文件中(Properties文件),但是使用属性文件有些弊端,第一,不支持类型,所有的内容都是String,第二是,只有在具体使用

的时候才能发现有些属性没有定义,而不能在编译的时候发现。

      那么GWT如何处理这个问题呢?GWT中有一个特殊的接口com.google.gwt.i18n.client.Constants可以使用这个接口达到

定义常量的效果,并且这些常量在编译的时候被绑定,而且可以支持类型。

     使用GWT主要有以下几步:

第一步,建立一个集成于Constants的接口,例如:

public interface NumberFormatConstants extends Constants {
/**
   * @return the localized decimal separator
   */
String decimalSeparator();

/**
   * @return the localized thousands separator
   */
String thousandsSeparator();
}

第二步,根据接口中定义的方法定义一个跟接口同名的属性文件,例如:

#NumberFormatConstants.properties

decimalSeparator = ,
thousandsSeparator = .

 

第三步,获取文件中定义的内容,例如:

public void useNumberFormatConstants() {
NumberFormatConstants constants = (NumberFormatConstants) GWT.create(NumberFormatConstants.class);
String decimalSep = constants.decimalSeparator();
String thousandsSep = constants.thousandsSeparator();
String msg = "Decimals are separated using '" + decimalSep + "'";
msg += ", and thousands are separated using '" + thousandsSep + "'";
showMessage(msg);
}

上述三步中在第二步和第三步中间隐含了伊特特殊的步骤,就是GWT编译器结合接口文件和属性文件编译出了一个

类,这个类实现了这个接口,每一个方法返回属性文件中的值。

其中GWT.create()方法可以获得生成的中间类的引用。

 

通常情况下,接口方法明和属性文件中的名字相同,例如:

String decimalSeparator(); 和 thousandsSeparator = .

但是也可以自定义接口方法和属性文件中内容的映射,例如:

 

public interface NumberFormatConstantsWithAltKey extends Constants {
/**
   * @gwt.key fmt.sep.decimal
   * @return the localized decimal separator
   */
String decimalSeparator();

/**
   * @gwt.key fmt.sep.decimal
   * @return the localized thousands separator
   */
String thousandsSeparator();
}

@gwt.key fmt.sep.decimal 定义了属性文件中key的内容,所以属性文件应该为:

#NumberFormatConstants.properties

fmt.sep.decimal = .
fmt.sep.thousands = ,

Constants子接口中定义的方法必须满足如下形式:

 

T methodName()

 

这里T是一个返回值,T可以使用如下表中的所有类型:

T类型                        属性文件定义
String                        简单的字符串
String[]                     使用逗号分割的字符串,如果某个字符串中包含逗号需要使用\\作为转移字符,例如:'\\,'
int                            int值,在编译的时候做类型检查
float                         float值,在编译的时候做类型检查
double                       double值,在编译的时候做类型检查
boolean                     boolean值"true" 或者 "false"), 在编译的时候做类型检查
Map                          使用逗号分隔的字符产,每一个字符产在属性文件中有一条定义,定义了一个Key-Value值

 

Map示例:

a = X
b = Y
c = Z
someMap = a, b, c

 

Map someMap();方法得到的内容为:{a:X, b:Y, c:Z}

 

ConstantsWithLookup

ConstantsWithLookup是Constants的子接口,用法一样,只不过ConstantsWithLookup有一组通过属性名字获取属性值的方法:

getBoolean(String)        通过名字找到boolean型内容
getDouble(String)         通过名字找到double型内容
getFloat(String)            通过名字找到float型内容
getInt(String)              通过名字找到int型内容
getMap(String)            通过名字找到Map型内容
getString(String)          通过名字找到String型内容
getStringArray(String)   通过名字找到String[]型内容

 

效率问题:Constants效率比ConstantsWithLookup高,为什么呢?Constants在编译的时候会生成对应的JavaScript代码,

GWT Compiler会根据程序中是否使用了某些属性来决定这些内容是否会被编译为JavaScript,所以及时在Constants中声明

了某些方法,如果在代码中不使用的话,不会被编译为JavaScript代码的。

但是ConstantsWithLookup有根据属性名字查找属性内容的方法,所以,GWT Compiler不能根据上述方法确定属性是否被使用,

所以所有的属性内容都回被编译为JavaScript代码。

这是ConstantsWithLookup的优点,也是缺点!

 

Message类

在使用Constants(或者ConstantsWithLookup)的时候,我们只能使用预定义的消息,有些时候我们需要可变的消息。

例如:

    我们需要一个通用的消息再加上一个功能名字的参数怎么实现呢?

 

Message类相当于Java中的Properties,ResourceBundle和MessageFormat的联合体,例如:

 

消息文件类:

public interface GameStatusMessages extends Messages {
/**
   * @param username the name of a player
   * @param numTurns the number of turns remaining
   * @return a message specifying the remaining turns for a player
   */
String turnsLeft(String username, int numTurns);

/**
   * @param numPoints the number of points
   * @return a message describing the current score for the current player
   */
String currentScore(int numPoints);
}


属性文件定义:
turnsLeft = Turns left for player ''{0}'': {1}
currentScore = Current score: {0}

使用:
public void beginNewGameRound(String username) {
GameStatusMessages messages = (GameStatusMessages) GWT.create(GameStatusMessages.class);

// Tell the new player how many turns he or she has left.
int turnsLeft = computeTurnsLeftForPlayer(username);
showMessage(messages.turnsLeft(username, turnsLeft));

// Tell the current player his or her score.
int currentScore = computeScore(username);
setCurrentPlayer(username);
showMessage(messages.currentScore(currentScore));
}

 

我们可以看到在使用的时候基本一致,但是,可以使用参数配置原有的消息。

另外Message的方法的格式为:

    String methodName(optional-params)

从中我们也可以看出区别,Message只能使用String类型的参数。

 

Constants(或者ConstantsWithLookup)和Message的区别是:
Constants用来定义系统的常量,支持多种类型。
Message用来定义系统的消息,可以支持参数化消息,但是只支持String类型的内容。

 

在使用Constants和Message的时候,可以将属性文件的编码设置为UTF-8这样,就不用
使用Native2ascii将正常的文件转移为utf-8的替换文件了。
当然如果你觉得不麻烦也可以使用传统的Java属性文件(使用native2ascii处理过得文件)。

 

 

功能介绍(JavaScript Native Interface)
JavaScript Native Interface = JSNI
JSNI定义了在GWT环境下,Java与JavaScript交互的一种方法。

虽然GWT的一些核心的方法是用JavaScript编写的,但是这里还是不推荐使用JNI,应为这样做与GWT的初衷相悖,

并且,有一定的难度,开发调试也相对困难。


Java调用JavaScript方法:

JSNI方法定义需要使用native关键字,并且需要在参数列表之后,结尾的分号之前定义。JSNI方法的开始使用/*-{

结尾使用}-*/,例如:

 

public static native void alert(String msg) /*-{
$wnd.alert(msg);
}-*/;

 

当上述方法在Java中调用的时候,实际上将会调用Window的alert方法,将传入的内容打印出来。

在Hosted Mode下,断点可以设置在上述方法中,可以方便的查看传入的参数。

 

JavaScript调用Java方法:

方法调用方式:

    [instance-expr.]@class-name::method-name(param-signature)(arguments)

属性访问方式:

    [instance-expr.]@class-name::field-name

 

[instance-expr.]

    用来区分实例方法调用还是静态方法调用。在调用实例方法的时候必须出现,在调用静态方法的时候不能出现。

class-name

    类的名字。

method-name

    方法的名字

param-signature

    方法的参数列表,这里使用的是内部形式(参考Java虚拟机Class格式),但是不需要写返回值类型。
arguments
    调用方法的实际参数。

例如:

public class JSNIExample {

String myInstanceField;
static int myStaticField;

void instanceFoo(String s) {
    // use s
}

static void staticFoo(String s) {
    // use s
}

 

// 该方法被调用的时候将在JavaScript中执行,并且

// 可以使用JavaScript中的内容。

public native void bar(JSNIExample x, String s) /*-{
    // 调用这个实例本身的instanceFoo方法
    this.@com.google.gwt.examples.JSNIExample::instanceFoo(Ljava/lang/String;)(s);

    // 调用x实例(输入参数)上的instanceFoo实例方法
    x.@com.google.gwt.examples.JSNIExample::instanceFoo(Ljava/lang/String;)(s);

    // 调用静态方法 staticFoo()
    @com.google.gwt.examples.JSNIExample::staticFoo(Ljava/lang/String;)(s);

    // 读取这个实例的变量
    var val = this.@com.google.gwt.examples.JSNIExample::myInstanceField;

    // 设置x上的实例变量
    x.@com.google.gwt.examples.JSNIExample::myInstanceField = val + " and stuff";

    // Read static field (no qualifier)
    @com.google.gwt.examples.JSNIExample::myStaticField = val + " and stuff";
}-*/;

}

 

Java和JavaScript之间参数的传递:

Java -> JavaScript

Java type                              JavaScript Type
numeric primitive                     a JavaScript numeric value, as in var x = 42;
String                                   a JavaScript string, as in var s = "my string";
boolean                                 a JavaScript boolean value, as in var b = true;
JavaScriptObject (see notes)    a JavaScriptObject that must have originated from JavaScript code, typically as the return value of some other JSNI method
Java array            an opaque value that can only be passed back into Java code
any other Java Object        an opaque value accessible through special syntax

 

异常
调用JSNI方法的时候会抛出一个JavaScriptException的异常,但是由于JavaScript不是一个强类型的语言,所以
无法想Java一样处理JavaScript异常。一个好的方式是在Java中处理Java异常,在JavaScript中处理JavaScript异常。

另外在JSNI方法,Java普通方法混掉的过程中,异常可以从最底层移植抛到最想的调用层,例如:

1. Java method foo() calls JSNI method bar()
2. JavaScript method bar() calls Java method baz()
3. Java method baz() throws an exception
baz()中抛出的异常可以蔓延到bar方法,可以在foo方法中捕获。

 

 

从Host Model到 Web Model

在Host Model方式下,GWT并不将Java代码编译为JavaScript,而是在GWT环境中直接运行Java bytecode,

但是项目正式部署之后使用的是Web Model,那么如何从Host Model迁移到Web Model呢?

 

首先需要将Java代码编译为JavaScript代码。

使用如下命令可以将Java代码编译为JavaScript代码:

java -cp "%~dp0\src;%~dp0\bin;%~dp0\../../gwt-user.jar;%~dp0\../../gwt-dev-windows.jar" com.google.gwt.dev.GWTCompiler -out "%~dp0\www" %* com.google.gwt.sample.hello.Hello

 

-cp 指定源代码目录,Class目录,和GWT的jar文件的路径

-out 指定JavaScript代码的输出路径

com.google.gwt.sample.hello.Hello 指定编译的Module,一般是gwt.xml文件中entry-point类去掉client之后的内容。

 

当代码量比较大的时候,需要指定Java使用内存的大小,否则会内存溢出。

java -Xmx512m -Xms128m -cp "%~dp0\src;%~dp0\bin;%~dp0\../../gwt-user.jar;%~dp0\../../gwt-dev-windows.jar" com.google.gwt.dev.GWTCompiler -out "%~dp0\www" %* com.google.gwt.sample.hello.Hello

 

之后将编译成的JavaScript代码拷贝到Web项目的根目录中,与WEB-INF相同层次的目录。

 

最后需要将gwt.xml文件中定义的service编程对应的Servlet。

 

 

=>

 

 

     Calendar

     com.google.gwt.sample.dynatable.server.SchoolCalendarServiceImpl

 

 

 

     Calendar

     /calendar

 

 

使用数据源

Hosted Mode 虽然开发起来很方便,但是也有缺点,例如,数据源的配置就有问题。

在GWT Hosted Mode下无法配置数据源,一种可选的方式是使用一个假的数据库链接

管理类,这个类的接口返回Connection,内部以DriverManager的方式实现,等待

后续部署之后再切换到数据源模式。

 

日志处理(Log4J)

回想GWT应用程序,client包内部的代码将会被编译为客户端JavaScript代码,所以这里
不需要记录日志,也不可能使用Log4j。
但是Server包内的内容在服务器上运行,需要合理的使用日志。

 

 

一个简单的Login示例

代码结构如下:

 

└─src
    └─com
        └─jpleasure
            └─gwt
                └─logon
                    │ LogonDemo.gwt.xml                       GWT配置模块文件
                    │
                    ├─client                                          客户端代码包
                    │ │ LogonDemo.java                        GWT代码的入口点
                    │ │ LogonDemoController.java           画面迁移控制类
                    │ │
                    │ ├─exception                                 异常定义包
                    │ │      ApplicationException.java        应用程序异常
                    │ │     
                    │ ├─panel                                       页面Panel包

分享到:
评论

相关推荐

    GWT入门 GWT中文教程

    EXT-GWT的API和DOC文档对于学习和使用EXT-GWT至关重要,它们详尽地介绍了各个组件的用法和功能,帮助开发者了解如何在项目中集成和使用这些组件。 接下来,“Gwt-Ext基础-中级-进阶”这部分教程可能涵盖了从基础到...

    Gwt中文手册,GWt入门

    Gwt中文手册,GWt入门Gwt中文手册,GWt入门Gwt中文手册,GWt入门

    GWT入门与经典实例解析

    扫描完整版

    GWT入门教程+实例代码

    **GWT 入门教程与实例解析** Google Web Toolkit(GWT)是Google推出的一款用于构建高性能、跨浏览器的Web应用程序的开源开发工具。它基于Java语言,通过编译Java源代码为JavaScript,使得开发者可以利用Java的强大...

    SmartGWT 入门 SmartGWT 入门

    ### SmartGWT 入门详解 #### 一、SmartGWT 概述 **SmartGWT** 是一款基于 **Google Web Toolkit (GWT)** 的高级Web应用开发框架,旨在简化企业级Web 2.0应用的开发过程。自从 **GWT** 发布以来,它吸引了大量的...

    GWT入门和进阶

    ### GWT入门 **1. 安装与配置** 首先,你需要下载GWT SDK,并在Eclipse或其他IDE中配置GWT插件。安装SDK后,创建一个新的GWT项目,包括设置模块文件.gwt.xml,定义项目的源代码路径和库依赖。 **2. 编写客户端代码...

    面向 Java 开发人员的 Ajax: Google Web Toolkit 入门(GWT入门)

    **Java开发人员的Ajax:Google Web Toolkit (GWT) 入门** Google Web Toolkit (GWT) 是一个强大的工具,它允许Java开发人员使用熟悉的Java语言来构建高性能、跨浏览器的Ajax应用程序。GWT通过将Java代码编译为优化...

    gwt入门项目代码

    本"gwt入门项目代码"是一个很好的起点,适合初学者了解和学习GWT和GXT框架。这个项目中,你可以期待找到以下几个关键的知识点: 1. **GWT的基础概念**:理解GWT如何将Java代码转换为跨浏览器兼容的JavaScript,以及...

    gwt入门资料,helloworld级别

    gwt入门.chm gwt入门资料,helloworld级别

    gwt入门-gwt从这里开始

    以下是关于 GWT 入门的详细知识点: 1. **GWT 编译器**: GWT 的核心部分是其编译器,它能够将 Java 代码转换为浏览器可执行的 JavaScript。这使得开发者可以利用 Java 的强大功能和成熟的开发工具,同时享受 ...

    GWT入门与经典实例解析源码

    GWT入门与经典实例解析源码提供了一个学习和实践GWT开发的宝贵资源,下面将详细介绍GWT的关键概念、核心特性以及通过实例解析来深入理解其工作原理。 1. **GWT的安装与设置**: 在开始GWT项目之前,你需要安装Java...

    GWT入门教程的好东西啊

    ### GWT入门教程知识点详解 #### 一、GWT简介 **Google Web Toolkit (GWT)** 是由Google推出的一款强大的Ajax应用开发包,它允许开发者使用熟悉的Java语言来进行Web应用程序的构建。对于初学者而言,这无疑是一个...

    GWT入门实例

    标题 "GWT入门实例" 指向的是Google Web Toolkit(GWT)的初学者教程。GWT 是一个开源的Java开发框架,它允许开发者使用Java语言来编写客户端的Web应用,然后自动编译成优化过的JavaScript代码。GWT通过提供丰富的...

    GWT入门,进阶,中级

    **入门GWT:** 在入门阶段,你需要了解GWT的基本概念和工作原理。GWT项目是基于Maven或Gradle构建的,包含一系列模块,每个模块代表一个独立的JavaScript输出。首先,你需要设置开发环境,安装Eclipse或IntelliJ ...

    GWT入门教程

    **GWT(Google Web Toolkit)入门教程** GWT(Google Web Toolkit)是一个开源的Java开发框架,由Google推出,主要用于构建高性能、富交互式的Web应用程序。这个框架允许开发者使用Java语言编写前端代码,并自动...

    GWT入门中级高级教程,基础教程。全中文。pdf、ppt、word格式

    本教程集合了从入门到高级的全方位学习资源,包括PDF、PPT和Word格式的文档,覆盖了GWT的基础概念、核心组件、实际应用以及Ajax技术。 **一、GWT入门** 在入门阶段,首先需要理解GWT的基本概念,包括模块系统、事件...

Global site tag (gtag.js) - Google Analytics