GWT:如何在两个模块之间共享java对象(即:EventBus)

时间:2013-03-24 21:13:29

标签: java javascript gwt jsni event-bus

我正在构建一个大型应用程序,我想将它拆分为几个模块,如核心模块,用于初始化,用户管理等...,客户模块,生产模块等......

我想将它拆分为多个GWT模块(不使用GWT拆分技术)并共享一个EventBus,用于广播一些事件,如LoginEvent,LogoutEvent。我不想使用代码分割技术,因为我想减少编译时间并仅重新编译我修改的模块。 这也允许通过在HTML主页中注释脚本标记来启用或禁用模块。

我使用JSNI编写以下代码:

CoreModule’s EntryPoint:

private static SimpleEventBus eventBus = null;

public void onModuleLoad() {
    export();
    getEventBus().addHandler(MyEvent.TYPE, new MyEventHandler() {

        @Override
        public void onEvent(MyEvent myEvent) {
            Window.alert(myEvent.getMessage());
        }
    });
}

public static SimpleEventBus getEventBus() {
    if (eventBus == null)
        eventBus = new SimpleEventBus();
    return eventBus;
}

public static native void export() /*-{
    $wnd.getEventBus = $entry(@testExporter.client.TestExporter::getEventBus());
}-*/;

CustomerModule’s EntryPoint:

public void onModuleLoad() {
    Button button = new Button("Click me");
    button.addClickHandler(new ClickHandler() {

        @Override
        public void onClick(ClickEvent event) {
            getEventBus().fireEvent(new MyEvent("Button clicked !"));
        }
    });
    RootPanel.get().add(button);
}

public static native SimpleEventBus getEventBus() /*-{
    // Create a useless eventBus because the GWT compiler make a call to a null instance
    var eventBus = @com.google.gwt.event.shared.SimpleEventBus::new()();
    eventBus = $wnd.getEventBus();
    return eventBus;
}-*/;

但是在浏览器中执行时,我在Firebug中遇到以下异常:

uncaugth exception [object Object]

我还复制了实现/接口客户事件的MyEvent和MyEventHandler类。

P.S。:我也知道一种技术,它可以评论其他模块引用,以避免编译它。

3 个答案:

答案 0 :(得分:1)

您不能在不同的GWT编译模块之间共享代码,除非您通过jsni使代码的某些部分可用,并通过jsni调用这些导出的方法,就像您在查询中尝试一样。

但要注意:首先,共享类是不兼容的,因为每个编译都会以不同的方式重命名类/方法,其次,每个编译都会删除不同的死代码片段。

因此,在您的情况下,SimpleEventBus导出方法中返回的window.getEventBus在其他模块中是未知的,尽管其他模块也使用SimpleEventBus

最简单的方法是使用GWT-exporter。首先正确选择要在每个模块中导出的js-api,如何命名,以及方便地实现Exportable和注释方法。第二,考虑将您用于通信的对象,因为其中一些可能是不兼容的。我会使用GWT-exporter

支持的原始类型,javascript对象和函数

我认为对于GWT-exporter,对于共享类,如果你在同一个命名空间中注释它们并导出相同的方法,希望你可以在所有模块中使用,但我不确定。

因此,通过jsni或gwt-exporter导出js API,并在它们之间传输纯原始或js对象。

答案 1 :(得分:1)

更简单的答案是不使用多个入口点。

==========================================

如果您要实现的目标是将代码分解为可管理的单元但希望在同一页面中使用所有代码,则可以:

  • 创建一个带有入口点的“Application.gwt.xml”模块(相当于您的初始化模块,如果我理解正确的话)
  • 创建“UserManagement.gwt.xml”模块,不含入口点类
  • 创建其他XXX模块不带入口点

要创建没有入口点的模块,只需删除

即可
<entry-point class='xxx'/>

来自你的gwt.xml文件,除了“Application”一个

然后,您需要使用

将这些模块包含到“应用程序”模块中
<inherits name="com.yourpackage.Module1Name" />
<inherits name="com.yourpackage.Module2Name" />

然后,您需要在模块“com.yourpackage.Application”的一个GWT构建中一起编译所有这些。

执行此操作时,请确保所有模块的已编译* .class和源.java文件在类路径中都可用。

您的“应用程序”入口点只需要初始化并使用其他模块中的对象

答案 2 :(得分:0)

您可以通过WebMessage协议使用框架并在模块之间建立通信。只有当一个页面中的模块和模块处于分离的战争中时,它才有用。