zoukankan      html  css  js  c++  java
  • GWT多模块间解耦合调用(一)

    使用GWT已经半年了,查了很多资料,但发现国内关注它的人很少,而且骂声也不少(当然GWT也有让我恶心的地方),所以就把平时实验的结果和感想,在这里和大家分享一下。



    GWT困扰我的一个最恶心的缺点,就是凡事要编译。系统一大,模块之间依赖很强,修改一个客户端(界面)的小功能,就要重编译整个项目,费时费劲,我们项目现在重编一次已经需要800多秒了——好在有Development mode(感叹这个东东的强大)。


    之前看到过GWT提供JSNI的功能,能够使gwt 的java code与纯JavaScript互通信,因此打算尝试使用JSNI作为中介,看看能不能减轻模块间的依赖——或者实现多模块之间实现分模块编译。



    想法是这样的,大部分模块基本是不变的,希望不要经常编译,假设其为Dll1;有些为客户开发的模块Dll2,它依赖于Dll1,而且经常发生变化(需求总是变化的)。希望修改了Dll2后,不重新编译Dll1。

    Dll1和Dll2只是一个命名,并不是真正的dll啊!




    如果按照GWT的依赖实现,Dll2中的gwt.xml中,声明inherit name="demo1.Dll1"后,重编Dll2其实就包含重编Dll1


    使用JSNI,见http://code.google.com/webtoolkit/doc/latest/DevGuideCodingBasicsJSNI.html


    将Dll1的接口,使用$entry方法,发布成为标准的javascript;Dll2不直接依赖Dll1,使用JSNI,调用Dll1发布成为javascript的接口。


    Dll1中,用GWT的java实现了3个方法

    代码
    package demo1.client;
    import java.util.Date;
    import com.extjs.gxt.ui.client.data.BaseModel;
    import com.extjs.gxt.ui.client.js.JsonConverter;
    import com.extjs.gxt.ui.client.widget.TabItem;
    import com.extjs.gxt.ui.client.widget.TabPanel;
    import com.extjs.gxt.ui.client.widget.layout.FitLayout;
    import com.google.gwt.dom.client.Element;
    import com.google.gwt.json.client.JSONObject;
    import com.google.gwt.user.client.Window;
    import com.google.gwt.user.client.ui.RootPanel;
    public class DllImpl {
        
    public static void method1(String value) {
            Window.alert(value);
        }
        
    public static String methodJson() {
            BaseModel result 
    = new BaseModel();
            result.set(
    "int"1);
            result.set(
    "double"new Double(1.2));
            result.set(
    "string""str");
            result.set(
    "date"new Date());
            result.set(
    "boolean"true);
            JSONObject obj 
    = JsonConverter.encode(result.getProperties());
            String str 
    = obj.toString();
            
    return str;
        }
        
    public static Element methodJS() {
            TabPanel p 
    = new TabPanel();
            TabItem item 
    = new TabItem();
            item.setClosable(
    true);
            item.setText(
    "dll 1");
            item.setLayout(
    new FitLayout());
            p.add(item);
            RootPanel.get(
    "cross").add(p);
            
    return item.getElement();
        }
        
    public static native void exportStaticMethod() /*-{
            $wnd.method1 =
            $entry(@demo1.client.DllImpl::method1(Ljava/lang/String;));
            $wnd.methodJson =
            $entry(@demo1.client.DllImpl::methodJson());
            $wnd.methodJS =
            $entry(@demo1.client.DllImpl::methodJS());
        }-
    */;
    }

    exportStaticMothod是将类中的3个方法,发布为javascript,其路径就是$wnd.method1、$wnd.methodJson和$wnd.methodJS,参数列表参考google文档中的JSNI。

    在Dll1的EntryPoint中,调用这个exportStaticMethod方法。

    Dll1的Entry代码
    package demo1.client;
    import com.google.gwt.core.client.EntryPoint;
    /**
     * Entry point classes define <code>onModuleLoad()</code>.
     
    */
    public class Dll1 implements EntryPoint {
        
    public void onModuleLoad() {
            DllImpl.exportStaticMethod();
        }
    }

     在Dll2中,就使用JSNI调用javascript,路径就是之前的$wnd.method1、$wnd.methodJson和$wnd.methodJS

    代码
    package demo2.client;
    import java.util.Date;
    import java.util.Map;
    import com.extjs.gxt.ui.client.data.BaseModel;
    import com.extjs.gxt.ui.client.js.JsonConverter;
    import com.extjs.gxt.ui.client.widget.form.FormPanel;
    import com.google.gwt.core.client.EntryPoint;
    import com.google.gwt.dom.client.Element;
    import com.google.gwt.user.client.Timer;
    /**
     * Entry point classes define <code>onModuleLoad()</code>.
     
    */
    public class Dll2 implements EntryPoint {
        
    public void onModuleLoad() {
            Timer t = new Timer() {
                @Override
                
    public void run() {
                    
    // 由于Dll1和Dll2没有声明依赖,所以使用Timer强制延时
                    callMethod1("Hello world form dll2.");
                    String json = callMethodJSON();
                    Map<String, Object> map = JsonConverter.decode(json);
                    BaseModel m = new BaseModel(map);
                    System.out.println(m.get("int"instanceof Integer);
                    System.out.println(m.get("double"instanceof Double);
                    System.out.println(m.get("string"instanceof String);
                    System.out.println(m.get("date"instanceof Date);
                    System.out.println(m.get("boolean"instanceof Boolean);
                    Element x = callMethodJS();
                    FormPanel f2 = new FormPanel();
                    f2.setHeading("dll 2");
                    f2.render((com.google.gwt.user.client.Element) x);
                }
            };
            t.schedule(2000);
        }
        
    protected native void callMethod1(String value)/*-{
            $wnd.method1(value);
        }-*/;
        
    protected native String callMethodJSON()/*-{
            return $wnd.methodJson();
        }-*/;
        
    protected native Element callMethodJS()/*-{
            var x = $wnd.methodJS();
            //alert(x);
            return x;
        }-*/;
    }

     之所以要用timer,是因为Dll2没有直接依赖Dll1,所以HTML声明加载Dll1和Dll2时,不能确定Dll2就是在Dll1加载后才被加载。如果Dll2在Dll1前加载,则调用的$wnd.method1()就还没被Dll1所“导出”,调用就会失败。

    HTML是这样加载2个模块的——"mce:"是CSDN的blog自动添加上去的,主要参考那两个script标记,分别使html加载dll1模块和dll2模块。

    代码
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html>
    <head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
    <link type="text/css" rel="stylesheet" href="DoubleMain.css" mce_href="DoubleMain.css">
    <title>Web Application Starter Project</title>
    <mce:script type="text/javascript" language="javascript"
        src
    ="doublemain/doublemain.nocache.js"></mce:script>
    <mce:script type="text/javascript" language="javascript"
        src
    ="doublemain2/doublemain2.nocache.js"></mce:script>
    </head>
    <body>
    <!-- OPTIONAL: include this if you want history support -->
    <iframe src="javascript:''" mce_src="javascript:''" id="__gwt_historyFrame" tabIndex='-1'
        
    style="position: absolute;  0; height: 0; border: 0"></iframe>
    </body>
    </html>

    至此,实现了一个简单的多模块间解耦合的调用,但是这里面的问题很多,不是一劳永逸,留待下篇博文来分解。 


  • 相关阅读:
    Spring IoC
    常见切入点表达式的例子(aop execution 表达式 )
    数据结构与算法(2)栈、中缀表达式、递归
    数据结构与算法(1)稀疏数组、队列、链表
    airflow实践
    head first 设计模式笔记13-与设计模式相处,剩下的模式,模式的分类
    head first 设计模式笔记12-复合模式
    head first 设计模式笔记11-代理模式
    head first 设计模式笔记10-状态模式
    WebDriver自动化测试常用处理方法
  • 原文地址:https://www.cnblogs.com/anic/p/1662184.html
Copyright © 2011-2022 走看看