GWT / Comet:有经验吗?

时间:2009-03-06 12:18:31

标签: json gwt comet

有没有办法从GWT“订阅”到JSON对象流并监听keep-alive连接上的传入事件,而不是试图一次性获取它们?我相信这项技术的流行语是“彗星”。

让我们假设我有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组件(表格,标签)。任何想法怎么做?

8 个答案:

答案 0 :(得分:6)

StreamHub有一个GWT Comet模块:

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

StreamHub是具有免费社区版的Comet服务器。行动中有一个例子here

您需要下载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。

答案 1 :(得分:5)

我在几个项目中使用过这种技术,虽然它确实存在问题。我应该注意到我只是通过GWT-RPC专门完成了这个,但是无论你用什么机制来处理数据,原理都是一样的。根据您的具体操作,可能没有太多需要使事情复杂化。

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

从服务器端,您只需进入一个等待周期(对于块和超时,Java并发包特别方便),直到有新数据可用。在那个时间点,服务器可以将数据包返回到客户端,该客户端将相应地更新。根据您的数据流的不同,有很多注意事项,但这里有一些需要考虑的事项:

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

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

答案 2 :(得分:3)

gwt - http://code.google.com/p/gwteventservice/

确实有一个类似于文明的库

但是我个人并没有亲自使用它,所以不能保证它的优点与否,但是doco看起来相当不错。值得一试。

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

答案 3 :(得分:1)

可以找到关于GWT Comet实现的一些初步想法here...,但我想知道是否有更成熟的东西。

答案 4 :(得分:1)

此外,有关GWT / Comet集成的一些见解可以使用there,使用更多切割技术:“Jetty Continuations”。值得一看。

答案 5 :(得分:0)

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

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

答案 6 :(得分:0)

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

答案 7 :(得分:0)

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

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

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

框架可以免费使用。