GWT / Comet:有任何经验吗?

6
有没有一种方法可以从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组件(表格、标签)。有什么想法吗?
8个回答

6

有一个适用于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);
...

从Google Code网站下载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。


嘿,有没有办法禁用浏览器在光标上显示烦人的“加载”符号,例如在Chrome中加载会出现一个烦人的白色圆圈。正如你所想象的那样,如果需要长时间打开应用程序并且不断出现加载符号,会变得非常烦人!谢谢。 - Federer

5
我在几个项目中使用过这种技术,虽然它也有一些问题。需要注意的是,我只是通过GWT-RPC具体实现了这一点,但无论您使用什么机制处理数据,原则都是相同的。根据您具体要做什么,可能没有必要过于复杂化。
首先,在客户端,我不认为GWT能够正确支持任何类型的流数据。连接必须在客户端实际处理数据之前关闭。从服务器推送的角度来看,这意味着您的客户端将连接到服务器并阻塞,直到数据可用,此时它将返回。在完成连接后执行的任何代码应立即重新打开与服务器的新连接以等待更多数据。
从服务器端的角度来看,您只需进入等待循环(Java并发包对此特别方便,带有块和超时),直到有新数据可用。此时,服务器可以向客户端返回一组数据,客户端将相应地更新。根据您的数据流如何,有许多考虑因素,但以下是一些需要考虑的:
- 是否重要让客户端获取每个单独的更新?如果是,则服务器需要缓存客户端获取某些数据并重新连接之间的任何潜在事件。 - 是否会有大量更新?如果是这种情况,最好将多个更新打包,并每隔几秒钟推送一次块,而不是让客户端每次获取一个更新。 - 服务器可能需要一种方法来检测客户端是否已离开,以避免为该客户端堆积大量缓存包。
我发现使用服务器推送方法存在两个问题。对于大量的客户端,这意味着Web服务器上有大量打开的连接。根据所涉及的Web服务器,这可能意味着创建和保持打开的许多线程。第二个问题与典型浏览器的每个域名的2个请求限制有关。如果您能够从二级域名为图像、CSS和其他静态内容提供服务,则可以减轻此问题。

+1 这正是我做事的方式。在Servlet 3.0规范中,“可暂停请求”是解决“大量线程”问题的方法。Jetty在7.0版本中早期支持此功能。Tomcat称其为其他名称。 - Per Wiklander

3

1

在GWT中实现Comet的一些初步想法可以在这里...找到,但我想知道是否有更成熟的方案。


1
此外,还有一些关于GWT/Comet集成的见解可以在这里找到,使用了更加前沿的技术:"Jetty Continuations"。值得一看。

0

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

我在这个设置中的经验是积极的,除了安全问题以外没有任何问题。在这种情况下,实际上并不清楚如何为comet实现安全性...似乎Comet更新servlet应该具有不同的URL,然后可以应用J2EE安全性。


0

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

在客户端方面,该框架具有相当简单的GWT集成。在服务器端,它使用普通的Servlet。

我们目前在集群环境下生产中使用它,拥有1000多个并发用户。在使用过程中,我们遇到了一些问题,不得不通过修改Atmosphere源代码来解决。此外,文档非常薄弱。

该框架可免费使用。


0
JBoss Errai项目具有消息总线,提供双向通信,是cometd的一个很好的替代方案。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接