我正在(与我的团队一起)编写一个GWT应用程序,该应用程序解析并表示某些特定于域的语言 - 例如,使用文本,视频和UI控件播放媒体演示文稿。因此,应用程序有一组组件:1 - 用于保存模型,1用于控制例程(控制器),当然我们有View类。
现在我们遇到了一个问题 - 在以下意义上使其全部可插拔:
应该是一个核心插件,它可以生成所有常见内容。此coer块必须是JavaScript文件(每个排列一个)
应该能够扩展核心类,编写自定义类 - 并将其编译为单独的JS文件(每个排列一个)
每个插件必须注册(将其类等)本身注册到核心平台,因此可以使用它。
问题:
对于第二个一个问题我找到了http://code.google.com/p/gwt-exporter/,它将GWT类导出到外部世界,因此可以从纯JS中调用它们。 / p>
此外,我有一个想法是为新插件创建新模块,因此它将被编译为单独的文件(第一个问题)。
您是否有构建此类架构的经验,在这种情况下,您有一些最佳实践吗?
答案 0 :(得分:3)
自GWT 1.5以来,我已经尝试过同样的问题,每当我想出更优雅的解决方案时,他们都会更改链接器并将其打破。我提出的唯一可以独立于链接器设计的方法就是完全按照你所说的去做,并为永久插件创建一个新模块。然后使用GWT导出器创建一个抽象类,插件必须扩展,该抽象类将有一个抽象方法,该方法将核心传递给它的插件的根元素并填充它。此方法的问题是必须在页面的初始加载时将所有插件模块添加到DOM,因为从2.0开始,iFrame链接器依赖于页面加载事件,因此动态添加的模块不会完全加载。因此,您需要将导出的填充方法包装在runAsync中,以便在使用模块之前不要下载模块。
编辑:
以下是我所谈论的一个粗略的例子。请注意,我在几年内没有做任何GWT,现在可能有更好的方法。
public final class PluginManager
{
public static final PluginManager INSTANCE = new PluginManager();
private PluginManager()
{
}
private static native void loadPlugin( AbstractPlugin plugin )
/*-{
if (!$wnd.Plugins) {
$wnd.Plugins = {};
}
var name = plugin.@com.example.PluginManager.AbstractPlugin::getName()();
$wnd.Plugins[name] = $entry(plugin.@com.example.PluginManager.AbstractPlugin::load(Ljava/lang/String;));
}-*/;
private static native void unloadPlugin( AbstractPlugin plugin )
/*-{
if ($wnd.Plugins) {
var name = plugin.@com.example.PluginManager.AbstractPlugin::getName()();
delete $wnd.Plugins[name];
}
}-*/;
private static native JsArrayString getPlugins()
/*-{
if ($wnd.Plugins) {
return Object.keys($wnd.Plugins);
}
return undefined;
}-*/;
public static abstract class AbstractPlugin implements EntryPoint
{
@Override
public final void onModuleLoad()
{
PluginManager.INSTANCE.loadPlugin( this );
}
protected final void unload()
{
PluginManager.INSTANCE.unloadPlugin( this );
}
protected abstract String getName();
protected abstract void load( String rootPanelId );
}
}