有没有办法从 GWT“订阅”JSON 对象流并监听保持活动连接上的传入事件,而无需尝试一次获取所有事件?我相信这项技术的流行词是“Comet”。

假设我有 HTTP 服务,它打开保持活动连接,并将带有传入股票报价的 JSON 对象实时放入其中:

{"symbol": "AAPL", "bid": "88.84", "ask":"88.86"}
{"symbol": "AAPL", "bid": "88.85", "ask":"88.87"}
{"symbol": "IBM", "bid": "87.48", "ask":"87.49"}
{"symbol": "GOOG", "bid": "305.64", "ask":"305.67"}
...

我需要监听此事件并实时更新 GWT 组件(表、标签)。有什么想法如何去做吗?

有帮助吗?

解决方案

StreamHub有一个GWT Comet模块:

http://code.google.com/p/gwt-comet-streamhub /

StreamHub 是一款带有免费社区版的Comet服务器。有一个例子,它在行动这里

您需要下载StreamHub Comet服务器并创建一个新的SubscriptionListener,使用StockDemo示例作为起点,然后创建一个新的JsonPayload来流式传输数据:

Payload payload = new JsonPayload("AAPL");
payload.addField("bid", "88.84");
payload.addField("ask", "88.86");
server.publish("AAPL", payload);
...

从谷歌代码网站下载JAR,将其添加到您的GWT项目类路径并将包含添加到您的GWT模块:

<inherits name="com.google.gwt.json.JSON" />
<inherits name="com.streamhub.StreamHubGWTAdapter" />

连接并订阅您的GWT代码:

StreamHubGWTAdapter streamhub = new StreamHubGWTAdapter();
streamhub.connect("http://localhost:7979/");
StreamHubGWTUpdateListener listener = new StockListener();
streamhub.subscribe("AAPL", listener);
streamhub.subscribe("IBM", listener);
streamhub.subscribe("GOOG", listener);
...

然后在更新侦听器中处理更新(也在GWT代码中):

public class StockListener implements StreamHubGWTUpdateListener {
      public void onUpdate(String topic, JSONObject update) {
          String bid = ((JSONString)update.get("bid")).stringValue();
          String ask = ((JSONString)update.get("ask")).stringValue();
          String symbol = topic;
          ...
      }
}

不要忘记在您的GWT项目主HTML页面中包含streamhub-min.js。

其他提示

我已经在几个项目中使用了这种技术,尽管它确实存在问题。我应该注意的是,我只是通过 GWT-RPC 专门完成了此操作,但无论您使用什么机制来处理数据,其原理都是相同的。根据您具体在做什么,可能没有必要让事情变得过于复杂。

首先,在客户端,我不相信 GWT 能够正确支持任何类型的流数据。在客户端可以实际处理数据之前,连接必须关闭。从服务器推送的角度来看,这意味着您的客户端将连接到服务器并阻塞,直到数据可用为止,此时它将返回。无论在已完成的连接上执行什么代码,都应立即重新打开与服务器的新连接以等待更多数据。

从服务器端来看,您只需进入等待周期(java 并发包对于具有块和超时的情况特别方便),直到有新数据可用。那时,服务器可以将数据包返回给客户端,客户端将进行相应更新。根据您的数据流情况,有很多注意事项,但以下是一些需要考虑的事项:

  • 客户获得每一次更新都很重要吗?如果是这样,那么服务器需要缓存客户端获取一些数据然后重新连接之间的任何潜在事件。
  • 会有大量更新吗?如果是这种情况,打包多个更新并每隔几秒一次推送块可能比让客户端一次获取一个更新更明智。
  • 服务器可能需要一种方法来检测客户端是否已经离开,以避免为该客户端堆积大量的缓存包。

我发现服务器推送方法存在两个问题。对于大量客户端,这意味着 Web 服务器上有大量开放连接。根据相关的 Web 服务器,这可能意味着要创建大量线程并保持打开状态。第二个与典型浏览器每个域 2 个请求的限制有关。如果您能够从二级域提供图像、CSS 和其他静态内容,则可以缓解此问题。

确实有一个像gwt这样的类似于文件的库 - http://code.google.com / p / gwteventservice /

但是我没有亲自使用它,所以不能保证它的好坏,但是doco看起来相当不错。值得一试。

还有其他一些我见过的,比如 gwt-rocket's cometd 库。

有关GWT Comet实施的一些初步想法可以在这里...... 找到。虽然我想知道是否有更成熟的东西。

此外,那里提供了有关GWT / Comet集成的一些见解,甚至使用更多切割边缘技术:“Jetty Continuations”。值得一看。

这里你可以找到一个描述(有一些源样本)如何为IBM WebSphere Application Server执行此操作。与Jetty或任何其他启用Comet的J2EE服务器不应该有太大的不同。简而言之,这个想法是:通过GWT RPC将您的Java对象编码为JSON字符串,然后使用cometd将其发送到客户端,Dojo接收它,触发您的JSNI代码,调用您的窗口小部件方法,在其中反序列化对象再次使用GWT RPC。瞧! :)

我对此设置的体验是积极的,除了安全问题之外没有任何问题。在这种情况下,如何实现彗星的安全性并不是很清楚...似乎Comet更新servlet应该有不同的URL,然后可以应用J2EE安全性。

JBoss Errai项目有一条消息总线,提供双向消息传递,为cometd提供了一个很好的替代方案。

我们正在使用Atmosphere Framewrok( http://async-io.org/ )获取ServerPush / Comet在GWT应用程序中。

在客户端,Framework具有非常简单的GWT集成。在服务器端,它使用普通的Servlet。

我们目前正在集群环境中使用1000多名用户进行生产。我们在通过修改Atmosphere源必须解决的方式上遇到了一些问题。文档也很薄。

框架可以免费使用。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top