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

13-06-24 banq
              

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"这一行。

运行结果:

              

banq
2013-06-25 09:26

昨天我们刚刚看完传统架构的事件实现: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") }
  
}
<p>

这段代码实现了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();
    });
<p>

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>
<p>

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