【问题标题】:GWT: How to share a java Object (ie: EventBus) between two modulesGWT:如何在两个模块之间共享一个 java 对象(即:EventBus)
【发布时间】:2013-03-24 21:13:29
【问题描述】:

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

我想将它拆分为多个 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.:我也知道注释其他模块引用以避免编译它的技术。

【问题讨论】:

    标签: java javascript gwt jsni event-bus


    【解决方案1】:

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

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

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

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

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

    <entry-point class='xxx'/>
    

    来自您的 gwt.xml 文件,“应用程序”文件除外

    然后您需要将这些模块包含到“应用程序”模块中

    <inherits name="com.yourpackage.Module1Name" />
    <inherits name="com.yourpackage.Module2Name" />
    

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

    当您这样做时,请确保所有模块的已编译 *.class 和源 .java 文件都在类路径中可用。

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

    【讨论】:

      【解决方案2】:

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

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

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

      做你想做的最简单的方法是使用GWT-exporter。首先在每个模块中正确选择要导出的js-api,如何命名,方便实现Exportable和注解方法。其次考虑您将使用哪些对象进行通信,因为其中一些对象可能不兼容。我会使用 GWT-exporter 支持的原始类型、javascript 对象和函数

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

      所以通过 jsni 或 gwt-exporter 导出一个 js API 并在它们之间传输纯原始或 js 对象。

      【讨论】:

        【解决方案3】:

        您可以使用框架并通过 WebMessage 协议设置模块之间的通信。只有在一页中的模块和分开的战争中的模块才会有帮助。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-05-04
          • 2010-10-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多