TIP:这部分相应的代码在step-10文件夹中(https://github.com/vert-x3/vertx-guide-for-java-devs)
在之前的guide中,我们可以看到用event bus来连接verticles通讯,通过传递消息的形式,开发者仅仅需要
注册消费者来接受和发送订阅消息。
SockJS event bus bridge拓展了客户端,浏览器的能力,创建一个分布式的event bus,不仅可以是集群中不同的verticle实例,也可以是客户端浏览器上运行的JavaScript程序。因此我们可以创建包含浏览器和服务端的大的分布式event bus,在基于消息分布式应用中需要确定结果一致性。
在这个章节,我们将会修改step-9中的代码:
Markdown的内容渲染发送到服务端,不发送HTTP请求
如果用户编辑的页面已经被其他用户编辑将提示一个warning
建立 SockJS event bus bridge
NOTE:SockJS是个客户端的JavaScript库,遵守提供一个类似WebSocket接口的协议,不论实际的浏览器或网络WebSockets,它支持各种不同的浏览器和服务器之间传输,选择一个运行的。
第一步,我们需要装上vertx-web提供的SockJSHandler:
1.为Vert.x实例创建一个新的SockJSHandler
2.允许浏览器传递的消息来着app.markdown地址,我们也用这个地址来获取服务器执行我们在页面上执行的编辑的Markdown内容。
3.允许发送消息到page.saved地址的浏览器,我们将使用这个地址来通知浏览器,当页面被编辑的时候。
4.配置bridge SockJS traffic到Event bus
5.处理/ eventbus路径下所有的请求。
CAUTION:对于大多数应用程序,您可能不希望客户端JavaScript能够发送任何消息给服务器上的任何处理程序,或其他浏览器。例如:
1.你可能有一个service在event bus上,可以访问或删除数据的服务,显然我们不希望表现差的或恶意的客户能够删除数据库中的所有数据。
2.我们没有必要让客户端可以监听任何事件总线地址。
为了解决这个问题,一个SockJS bridge将默认拒绝任何信息。这就是为什么它是由你来告诉我的消息是否通过该桥(作为例外,回复消息总是允许通过)
在客户端
现在服务端已经准备好接受消息,我们将配置客户端
第一,我们SockJS和Vert.x event bus JavaScript端需要load,最简单的方式是从网络服务中获取:
NOTE:事件总线客户端可以先下载预捆绑应用,可以使用maven,npm,bower,甚至wevjars仓库
然后创建一个EventBus Javascript实例:
var eb = new EventBus(window.location.protocol + "//" + window.location.host + "/eventbus");
发送Markdown内容到event bus
SockJS bridge 运行起来后,为了将Markdown内容发送到服务端,我们需要注册一个消费者,这个消费者将消息发送到app.markdown地址:
vertx.eventBus().<String>consumer("app.markdown", msg -> {
String html = Processor.process(msg.body());
msg.reply(html);
});
这里没有什么新东西,我们之前已经创建了一个event bus消费者,然后我们看看在付端端修改了什么代码:
1.reply程序方法有两个参数:一个error(如果需要)和一个reply对象,reply对象的内容包含在body中
2.因为 event bus client没有被AngularJS管理,$scope.$apply用于生命周期的回调
3.当我们使用$http,借助updateRendering来处理HTML结果。
诚然,这代码和HTTP endpoint代码类似,然而好处是不依赖于代码的行数编号。事实上,如果你在 event bus进行服务端的通信,bridge透明的处理分布的注册消费者的消息。因此,当Vert.x运行在集群模式中,这浏览不是联系一个当以的服务器程序(除了sockjs连接),更重要的是对服务器的连接是永远不会关闭,所以HTTP / 1.1这节省了为每个请求建立一个TCP连接,这可能是有用的,如果你有服务器和客户端之间的交流很多。
当页面被他人修改提示Warning
在很多的应用中,我们总是以最后的提交为准则来处理这个冲突:当两个用户在同一个时间编辑相同的资源,最后一个提交保存的会覆盖前个的修改。
针对这个问题我们有多重方式,像实体版本,或者分布式的拓展字段。然而,让我们坚持一个简单的解决方案,看看我们如何能够通知用户当变化,至少他得到一个机会来处理情况。一旦数据库中的内容修改,用户可以决定最好的行动是什么:改写或重新加载。
我们需要添加一个 alert alert-warning 信息到 div中,但是我们仅仅在pageModified设置为true的情况下展示。
<div class="col-md-12">
<div class="alert alert-warning ng-class:{'invisible': !pageModified};" role="alert">
The page has been modified by another user.
<a href="#" ng-click="load(pageId)">Reload</a>
</div>
</div>
当页面被保存的时候pageModified设置为true,我们从page.saved地址注册event bus程序:
1.我们不想打印警告如果我们修改自己的内容,我们需要一个客户端标识符
2.回调地址将会出发在消息被page.saved地址接收
3.检查body是否为空
4.确定event是关联到当前wiki 页面
5.确定没有修改
6.设置pageModified true
当页面的额内容被保存到数据库的时候需要发送消息:
1.rxSavePage返回Single<Void>对象,成功后发送一个event
2.消息包含一个页面标识
3.消息包含一个客户端标识
4.event被发送到page.saved 地址
如果我们打开应用在两个不同的tabs,可以是同一个浏览器或者是不同的,选择相同的页面,在其中一个更新信息,另一个个提示警告信息:
我们可以简单的拓展SockJS bridge为了其他目的,像有多少用户在同一个页面,支持一个实时聊天的窗口等等。关键的一点是,在服务器和客户端共享相同的编程模型,通过消息传递的事件总线。
原文链接:http://vertx.io/docs/guide-for-java-devs/
我的微信公众号: