2012年3月30日 星期五

區分 GWT 程式碼的執行環境

這是在勁過呂布的噗浪上遇到的問題。

起因是傳給 String.split() 的 RegExp,Java 與 JavaScript 的寫法相似、但不是完全相同(參見 GWT 文件),也就會遇到「development mode 下正確、但 compile 之後得不到預期結果」的窘況。再者,如果 client/server 端都用 Java 寫,也會擴大這個問題的麻煩度。

這時候我們需要 GWT

(謎之聲:你不就在寫 GWT 了 [指])

這裡是指 com.google.gwt.core.client.GWT。這個 class 提供 isClient()isScript()isProdMode() 理論上與 isScript() 等意)這兩個 static method。

isScript() 是辨別程式碼是以 JavaScript 的方式執行、還是以 Java 的方式執行。在 development mode 下會回傳 false,在 compile 時才由 GWT compiler 改成回傳 true。

isClient()(邏輯上)不會區分是不是 development mode,純粹辨別程式碼是在瀏覽器上頭執行,還是在 JVM 上頭執行。

理解這種文字遊戲有點麻煩,還是來寫個程式比較實在。首先是 client 端的程式:
public class Foo extends Composite
 public static final RpcServiceAsync rpc = GWT.create(RpcService.class);
 private VerticalPanel panel = new VerticalPanel();
 public Foo(){
  String result = "[client] GWT.isClient() = " + GWT.isClient()
    + ", GWT.isScript() = " + GWT.isScript();
  panel.add(new Label(result));

  rpc.gwtMethod(new AsyncCallback<String>() {
   @Override
   public void onSuccess(String result) {
    panel.add(new Label("[server] "+result));
   }
   
   @Override
   public void onFailure(Throwable caught) {}
  });
  
  this.initWidget(panel);
 }
}

而 Server 端 RpcServiceImpl 的 method 長這樣:
 public String gwtMethod() {
  return "GWT.isClient() = "+GWT.isClient()
   + ", GWT.isScript() = "+GWT.isScript();
 }

在 development mode 下,會得到:
[client] GWT.isClient() = true, GWT.isScript() = false
[server] GWT.isClient() = false, GWT.isScript() = false
實際 deploy 到 web server 上,會得到:
[client] GWT.isClient() = true, GWT.isScript() = true
[server] GWT.isClient() = false, GWT.isScript() = false
如此一來,雖然遇到了抽象滲漏的現象,但我們還是可以藉由  GWT.isClient()GWT.isScript() 判斷是 development mode 還是 production mode、是 client 端還是 server 端、給予對應 RegExp,來解決這個問題。

沒有留言:

張貼留言