6

有没有办法从 GWT“订阅”到 JSON 对象流并在保持连接的情况下监听传入事件,而不是一次尝试全部获取它们?我相信这项技术的流行语是“彗星”。

假设我有一个 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 组件(表、标签)。任何想法如何做到这一点?

4

8 回答 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 代码站点下载 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。

于 2009-07-22T21:19:22.123 回答
5

我已经在几个项目中使用了这种技术,尽管它确实存在问题。我应该注意,我只是专门通过 GWT-RPC 完成了这项工作,但无论您使用何种机制来处理数据,原理都是相同的。取决于你到底在做什么,可能没有太多需要过度复杂的事情。

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

从服务器端,您只需进入一个等待周期(java 并发包特别方便地处理阻塞和超时),直到有新数据可用。在那个时间点,服务器可以将数据包返回给客户端,客户端将相应地更新。根据您的数据流的情况,有很多考虑因素,但这里有一些需要考虑:

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

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

于 2009-03-08T05:27:27.810 回答
3

确实有一个类似彗星的 gwt 库 - http://code.google.com/p/gwteventservice/

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

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

于 2009-03-08T04:56:44.233 回答
1

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

于 2009-03-06T12:27:17.803 回答
1

此外,那里还提供了一些关于 GWT/Comet 集成的见解,使用了更尖端的技术:“Jetty Continuations”。值得一看。

于 2009-03-06T14:38:33.557 回答
0

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

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

于 2010-01-29T16:35:19.120 回答
0

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

于 2011-12-02T20:45:23.533 回答
0

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

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

我们目前在生产环境中使用它,在集群环境中有 1000 多个并发用户。我们在途中遇到了一些问题,必须通过修改 Atmosphere 源来解决。文档也很薄。

框架可以免费使用。

于 2014-02-26T10:43:36.680 回答