先人一步
VMware 提供培训和认证,助力您的进步。
了解更多我们正在探索各种方法来帮助开发者创建富裕、现代化的前端,这些前端可以轻松地与 Spring 后端集成。如果您参加了今年的 SpringOne 大会,您已经看到了一些我们一直在努力实现的东西
简而言之,我们希望让 Spring 后端和客户端之间的高效通信变得容易,并轻松集成最好和最流行的客户端技术。
JSON Patch 是一种用于发送结构化数据增量更改的格式。我认为尝试通过 STOMP 将 JSON Patch 格式的更新流式传输到 Web UI 中会很有趣。
Craig Walls 已经使用新的 Spring Sync 项目构建了一个简单的足球比分概念验证,该项目通过 STOMP 使用 JSON Patch 将比分更新推送到浏览器。我利用了他的概念验证,引入了 RaveJS,添加了客户端响应式流,并将更新集成到一个 React UI 组件中。
您可以在我的 github 仓库的 rave-most-react 分支中找到完整的代码。服务器与 Craig 的原始版本保持不变。Web 客户端是主要操作发生的地方。在我们深入了解具体细节之前,请先查看 main.js 以了解整个应用的大致情况。
我使用 RaveJS 和 npm 管理我的客户端依赖项,所以我的启动很简单
> cd src/main/resources/public
> npm init
<answer a few questions>
> npm install --save rave most jiff react rave-load-jsx rave-node-process stompjs
然后我只需要在现有的 HTML 中添加一个脚本标签,就可以开始编写代码了!
<script src="node_modules/rave/rave.js"></script>
感谢 Craig,我已有一个(JSON Patch 格式的)更新流通过 STOMP 流向客户端。我认为处理补丁流的最佳方式是(惊喜!)*实际使用流*。
Most.js 是 cujoJS 的新 JavaScript 响应式流包。它提供了一组小而强大的 API,用于创建、转换和使用事件流。我用它来包装 stompjs API。
事实证明,有两个 STOMP 订阅:一个携带所有比分数据的初始完整副本,另一个携带所有后续更改。我能够通过使用 jiff.js 应用到达的 JSON Patch,将这两个订阅包装成一个表示“最新比分集”的单一响应式流。
这段代码从 STOMP 对初始数据的订阅创建了一个流,获取第一个事件(所有比分的完整快照),并将其与另一个仅包含 JSON Patch 更新的流结合,从而产生一个随时间变化的比分视图。
function getScoresStream(initDestination, updateDestination, client) {
// Create a stream containing one full copy of the data, and
// flatMap that to a stream containing the time-varying
// current set of scores, by accumulating each patch
// and emitting the updated scores data.
return getInitialDataStream(initDestination, client)
.flatMap(function(data) {
return getUpdatesStream(updateDestination, client, data);
});
}
function getInitialDataStream (initDestination, client) {
// Await a copy of the data from the STOMP subscription
// that is sending the full scores data, then unsubscribe.
return streamFromStompJson(initDestination, client)
.take(1);
}
function getUpdatesStream (updateDestination, client, data) {
// Incrementally accumulate patches from the STOMP subscription
// that is carrying JSON Patches onto the scores data to produce
// an updated view of the scores.
return streamFromStompJson(updateDestination, client)
.startWith([])
.scan(updateWithJsonPatch, data);
}
Most.js 在流结束时还会自动清理底层资源。在接收到完整比分数据的初始副本后,可以轻松安排取消第一个订阅,只留下一个订阅:变更订阅。
现在我已经有了代表最新比分的单一 most.js 流,我创建了一个 React 组件来显示它们。我安装了(见上文)rave-load-jsx 扩展,这是一个由社区成员创建的 RaveJS 扩展,它可以在 RaveJS 中直接加载 JSX 组件。我只需要创建一个 Scoreboard.jsx 文件,然后开始编写一个简单的 React 记分板组件。
React 组件有一个内部的 state
对象,其中包含用于渲染组件的数据。我只需在创建组件时传递最新的比分流,然后让组件观察该流并更新其 state
。相关的代码只有几行
// this.props.scores is the scores stream provided when the
// Scoreboard component is created
this.props.scores.observe(function(scores) {
self.setState({ scores: scores });
});
React 负责自动保持 DOM 与 state
同步。
诚然,这是一个玩具应用。然而,它在一个非常小的空间内,用非常少的代码展示了许多强大的概念协同工作:小型的服务器生成增量通过 STOMP + WebSocket 流动,到达客户端的响应式流,并被 React 组件观察。变化从 Spring 后端一直流向 UI——可以说是从字节到像素。
我希望这个小应用也能让您一窥我们未来的方向。我们希望提供工具和客户端包,帮助开发者构建富裕、现代化的客户端应用,这些应用可以与主流的客户端技术和 Spring 后端集成。