Java EE 7: EJB 发布 CDI事件通过WebSocket到浏览器客户端

Java EE 7: EJB publishing CDI Events that are pushed over WebSocket to browser client谈了如何实现通过EJB发布事件经过WebSocket管道推送到客户端浏览器。

1.无态会话Bean每3秒定时启动CDI事件
2.元注解为WebSocket EndPoint 管理的类作为WS 客户端
3.WebSocket Endpoint观察CDI事件,是其观察者,负责将CDI事件发布到每个WebSocket 客户端。

如下图:

大致步骤如下:
创建一个事件对象:

创建一个事件的元注解,用来标注某个发送事件的方法:

准备工作完成,下面正式开始:
1. 创建事件的发送者:

2. 创建一个中间者协调者,用来作为上面事件的消费者(onTimeEvent 方法),同时又是WebSocket事件的消费者,也就是浏览器客户端的消费者(onMessage 方法)。

3.创建浏览器客户端JS代码:

html代码:

输出在div id="output"这一行。

运行结果:

昨天我们刚刚看完传统架构的事件实现:Java EE 7: EJB 发布 CDI事件通过WebSocket到浏览器客户端,今天介绍一下使用Scala的Play框架和AngularJS这对事件函数语言全新组合:
http://matthiasnehlsen.com/blog/2013/06/23/angularjs-and-play-framework/,架构图如下,聊天案例:

聊天的服务器端协调者Mediator如下:


object ChatApplication extends Controller {

/** Central hub for distributing chat messages */
val (chatOut, chatChannel) = Concurrent.broadcast[JsValue]

/** Controller action serving chat page */
def index = Action { Ok(views.html.index(
"Chat using Server Sent Events")) }

/** Controller action for POSTing chat messages */
def postMessage = Action(parse.json) { req => chatChannel.push(req.body); Ok }

/** Enumeratee for filtering messages based on room */
def filter(room: String) = Enumeratee.filter[JsValue] { json: JsValue => (json \
"room").as[String] == room }

/** Controller action serving activity based on room */
def chatFeed(room: String) = Action { Ok.stream(chatOut &> filter(room) &> EventSource()).as(
"text/event-stream") }

}

这段代码实现了Chat房价分发,如下:


浏览器客户端AngularJS


/** Controllers */
angular.module('sseChat.controllers', ['sseChat.services']).
controller('ChatCtrl', function ($scope, $http, chatModel) {
$scope.rooms = chatModel.getRooms();
$scope.msgs = [];
$scope.inputText =
"";
$scope.user =
"Jane Doe #" + Math.floor((Math.random() * 100) + 1);
$scope.currentRoom = $scope.rooms[0];

/** change current room, restart EventSource connection */
$scope.setCurrentRoom = function (room) {
$scope.currentRoom = room;
$scope.chatFeed.close();
$scope.listen();
};

/** posting chat text to server */
$scope.submitMsg = function () {
$http.post(
"/chat", { text: $scope.inputText, user: $scope.user,
time: (new Date()).toUTCString(), room: $scope.currentRoom.value });
$scope.inputText =
"";
};

/** handle incoming messages: add to messages array */
$scope.addMsg = function (msg) {
$scope.$apply(function () { $scope.msgs.push(JSON.parse(msg.data)); });
};

/** start listening on messages from selected room */
$scope.listen = function () {
$scope.chatFeed = new EventSource(
"/chatFeed/" + $scope.currentRoom.value);
$scope.chatFeed.addEventListener(
"message", $scope.addMsg, false);
};

$scope.listen();
});

Html代码如下:


<div ng-controller="ChatCtrl">
<div id=
"header">
Your Name: <input type=
"text" name="user" id="userField" value="John Doe"
ng-model=
"user" />
<select ng-model=
"currentRoom" ng-change="setCurrentRoom(currentRoom)"
ng-options=
"r.name for r in rooms"></select>
</div>

<div id=
"chat">
<div class=
" msg" ng-repeat="msg in msgs | limitTo:-10"
ng-class=
"msg.user !== user ? 'others' : ''"
data-ng-show=
"hidden == false" data-ng-hide="hidden == true"
data-ng-animate=
"'fadeIn'"><br/>
<strong> says: </strong><br/>
</div>
</div>

<div id=
"footer">
<form ng-submit=
"submitMsg()">
Say something: <input type=
"text" name="chat" id="textField"
ng-model=
"inputText" />
<input type=
"button" id="saySomething" value="Submit"
ng-click=
"submitMsg()" />
</form>
</div>
</div>

[该贴被banq于2013-06-25 09:33修改过]