MVP For GWT 系列资料十一:彻底了解 GWT Part 1:JSNI

源文出自:https://txt.appspot.com/pt2club.blogspot.com/2010/02/gwt-part-1jsni.html

 

彻底了解 GWT Part 1:JSNI

 

原文:http://googlewebtoolkit.blogspot.com/2008/07/getting-to-really-know-gwt-part-1-jsni.html

技术校正、审阅:tkcn

[前面略过一段很口语、很难翻译、但是不太重要的一段 XD]

彻底了解 GWT,第一步:JSNI
如果你是 GWT 新手,你可能觉得奇怪:到底有什么好激动的?GWT 跟其他 framework 有什么不同?GWT 是一个基础技术、串起许多工具,而不只是特定 application 的 framework。因此,虽然 GWT「有」很多 library,觉得有用的话,要用多用少都可以。不喜欢 GWT 的 UI?你可以用 DOM 建立自己的 UI。不想用 RPC 而想要用 JSON?那也没问题。事实上,要用 GWT 重头开始打造自己的  framework 是绝对没问题的,也能保留所有 GWT debug 跟 compile 方面的优点。

所以,用一个宏观的角度来思考:为什么你要考虑使用 GWT 来开发下一个大的 web application 呢?

相较于传统 server-centric 的方式,如果 AJAX 设计得好,因为本身的特性,在许多种类的 application 上会提供更好的使用经验。你都已经在读这个 blog 了,可能早就知道啦。

GWT compiler 产生的 JavaScript 码通常会比你自己撰写的程式码还要小、还要快。

用 GWT 开发可以让你更有产能、而且产生的 JavaScript 也更加可靠。

You get the opportunity to say "Gwit" a lot.

 

我们担心你是那种容易被一些主张或是行销说词给影响了,所以我们在接下来几篇 blog 文章中,会看到 GWT 如何实现性能的提升、以及如何让 JavaScript 使用起来更容易。

 

在深入技术细节之前,还有一件事。我们有时会问两个跟 GWT 本质有关的问题:

为什么 GWT 以 Java 语言和工具为核心?

跟手写的 JavaScript 比起来,GWT 是不是比较多限制、也比较 heavyweight?

 

先回答第一个问题,请了解我们的目标跟满腔热血,是为了彻底改善网页使用者的使用者经验,这表示 GWT 产生的 JavaScript 必须有最好的效能跟可靠度。为了做到这一点,我们自然想加入一堆程式码的最佳化,并且尽可能的提早抓出 bug。这两个目标都容易在 Java 的 static type、以及既有的 Java IDE 来达成。这是为什么我们冷静地选择了 Java 技术作为 GWT 的核心。就是这样—没啥语言圣战的梗。

 

再来回答第二个问题,有些开发人员在第一次听到 GWT 时,会假设它是一个 abstraction 的「Walled Garden」,让你永远只能用 Java 写程式而不让你使用或是整合手写的 JavaScript。这实在错的很离谱......

 

GWT 中的 JavaScript Native Interface(JSNI)

你可以轻松地把手写的 JavaScript 直接嵌入 GWT 程式码当中。反正最后都会变成 JavaScript,那为什么不提供 GWT 的开发人员一个有用的方法,让他们能够混合这两个东西?这方法就叫做 JSNI 啦。它的名字跟 JNI(Java Native Interface)很像,因为他们的基本想法也一样:把一个 Java method 宣告成「native」然后用另一个语言来实做内容。在 JSNI 当中,就是用 JavaScript 来实做内容。

 

用 JavaScript 写 Java Method

JSNI 在创造功能最底层的 abstraction 是非常有用的,它很自然地使用 JavaScript、而不是 Java 语法。例如 Regular Expression 在 JavaScript 是相当简洁的,所以你可以透过 JSNI 在 GWT 程式码当中直接使用它们。假设你想把某人的名字(Ps Monkey)转过来,让姓在后面、名字在前面(Monkey, Ps)(当然,这在 I18N 当中会是一场恶梦)。你可以建立一个很简短的 JSNI method 来做到:

// Java method declaration...

native String flipName(String name) /*-{

  // ...implemented with JavaScript

  var re = /(\w+)\s(\w+)/;

  return name.replace(re, '$2, $1');

}-*/;

请注意,method 的内容整个被特殊标记「/*-」、「-*/」给包围起来,变成一段 Java 的注解。

 

在 JSNI 中呼叫 Java method

你也可以反过来,在 JavaScript 呼叫一个 Java 的 method。假设我们修改上面的例子,改成这样:

package org.example.foo;

public class Flipper {

  public native void flipName(String name) /*-{

    var re = /(\w+)\s(\w+)/;

    var s = name.replace(re, '$2, $1');

    [email protected]::onFlip(Ljava/lang/String;)(s);

  }-*/;

 

  private void onFlip(String flippedName) {

    // do something useful with the flipped name

  }

}

 

用 JSNI 存取外部的 JavaScript 程式码

当然,你可以在 GWT module 存取任何外部的 JavaScript 程式码。举例来说,如果你的 HTML 页面看起来像这样:

<html>

  <head>

    <SCRIPT>

    function sayHello(name) {

        alert("Hello from JavaScript, " + name);

    }

    </script>    

    <-- Include the GWT module called "Spiffy" -->

    <script src="/pt2club.blogspot.com/2010/02/org.example.yourcode.Spiffy.nocache.js"></script>

  </head>

...

在 Java 程式码,您可以用 JSNI 去呼叫 JavaScript 的 sayHello() function:

// A Java method using JSNI

native void sayHelloInJava(String name) /*-{

  $wnd.sayHello(name); // $wnd is a JSNI synonym for 'window'

}-*/;

GWT compiler 把外部的 method 呼叫给内嵌进来,所以在 Java 当中呼叫 sayHelloInJava() 的效率并不会比直接在 JavaScript 当中呼叫来的差。

 

用 GWT 建立 JavaScript library

你甚至可以用 GWT 创造一个 JavaScript 可以呼叫的 library。这是一个非常棒的技巧:

package org.example.yourcode.format.client;

public class DateFormatterLib implements EntryPoint {

 

  // Expose the following method into JavaScript.

  private static String formatAsCurrency(double x) {

    return NumberFormat.getCurrencyFormat().format(x);

  }

  // Set up the JS-callable signature as a global JS function.

  private native void publish() /*-{

  $ wnd.formatAsCurrency =

    @org.example.yourcode.format.client.DateFormatterLib::formatAsCurrency(D);

}-*/;

 

  // Auto-publish the method into JS when the GWT module loads.

  public void onModuleLoad() {

    publish();

  }

}

 

接著,你可以在任何 HTML 或是 JavaScript library 当中存取这个 GWT 做出来的功能:

<html>

  <head>

  

    <-- Include the GWT module that publishes the JS API -->

    <script src="/pt2club.blogspot.com/2010/02/org.example.yourcode.FormatLib.nocache.js"></script>

 

    <-- Write some JS that uses that GWT code -->

    <SCRIPT>

    function doStuff() {

      alert(formatAsCurrency(1530281));

    }

    </script>

  </head>

...

 

Ray Cromwell(最有名的是 GWT Extreme!)在他的 GWT Exporter 淋漓尽致地采用了上述的 JavaScript 发布技术。它用 GWT compile 期的 code 产生器来自动创造所有发布出的程式码。(「compile 阶段的程式码产生器」听起来很酷吧?如果你也这样觉得,那请期待这个系列的后续文章。)

 

掺在一起作撒尿牛丸

用 JSNI,你可以用你想要的方式,自由地混和手工撰写的 JavaScript、外部的 JavaScript library、以及 Java 程式码。这就是我们说 GWT 并不是一个 abstraction 的「walled garden」,因为你可以逐步地将 GWT 融入到既有的 web application 当中。更棒的是,你可以用你喜欢的 Java debugger 来 debug 所有 Java 程式码。

 

想要了解更多的话,请看 GWT Developer Guide 的 JavaScript Native Interface。或著,让 GWT compiler 的设计师 Scott Blum 解释给你听也不错喔。

你可能感兴趣的:(JavaScript,java,UI,jni,gwt)