JavaEE 7教程

JavaEE7 Websocket 案例与源码

  首先在Maven中加入JavaEE 7依赖:

<project>
...
<properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <!-- Java EE 7 -->
        <javaee.api.version>7.0</javaee.api.version>
</properties

<dependencies>
        <dependency>
                <groupId>javax</groupId>
                <artifactId>javaee-api</artifactId>
                <version>${javaee.api.version}</version>
                <scope>provided</scope>
        </dependency>
</dependencies>
...
</project>

本案例以JBoss的 WildFly为java EE 7服务器。

服务端点代码:

@ServerEndpoint(
                value = "/matches/{match-id}", 
                        decoders = { MessageDecoder.class },
                        encoders = { MatchMessageEncoder.class, BetMessageEncoder.class }
                )
public class MatchEndpoint {

        private static final Logger logger = Logger.getLogger("MatchEndpoint");

         /** All open WebSocket sessions */
        static Set<Session> peers = Collections.synchronizedSet(new HashSet<Session>());

        /** Handle number of bets by match */
        static Map<String, AtomicInteger> nbBetsByMatch = new ConcurrentHashMap<>();

        @Inject StarterService ejbService;

        @OnOpen
        public void openConnection(Session session,
                                        @PathParam("match-id") String matchId) {
            session.getUserProperties().put(matchId, true);
            peers.add(session);

            //Send live result for this match
            send(new MatchMessage(ejbService.getMatches().get(matchId)), matchId);
        }

        public static void send(MatchMessage msg, String matchId) {
          try {
            /* Send updates to all open WebSocket sessions for this match */
            for (Session session : queue) {
              if (Boolean.TRUE.equals(session.getUserProperties().get(matchId))){
                if (session.isOpen()){
                      session.getBasicRemote().sendObject(msg);       
                }
              }
            }
          } catch (IOException | EncodeException e) {
            logger.log(Level.INFO, e.toString());
          }
        }

        public static void sendBetMessage(Session session, BetMessage betMsg, String matchId)
        {
          try {
              betMsg.setNbBets(nbBetsByMatch.get(matchId).get());
              session.getBasicRemote().sendObject(betMsg);
                  logger.log(Level.INFO, "BetMsg Sent: {0}", betMsg.toString());
          } catch (IOException | EncodeException e) {
                  logger.log(Level.SEVERE, e.toString());
          }
        }

        @OnMessage
        public void message(final Session session, BetMessage msg,   
                                        @PathParam("match-id") String matchId) {
          session.getUserProperties().put("bet", msg.getWinner());

          //Send betMsg with bet count
          if (!nbBetsByMatch.containsKey(matchId)){
             nbBetsByMatch.put(matchId, new AtomicInteger());
          }
          nbBetsByMatch.get(matchId).incrementAndGet();
          sendBetMessages(null, matchId, false);
        }

        @OnClose
        public void closedConnection(Session session,
                            @PathParam("match-id") String matchId) {
          if (session.getUserProperties().containsKey("bet")){
                  nbBetsByMatch.get(matchId).decrementAndGet();
                  sendBetMessages(null, matchId, false);
          }
          /* Remove this connection from the queue */
          peers.remove(session);
        }
...
}

JSON消息的转码和解码:

public class MatchMessageEncoder implements Encoder.Text<MatchMessage> {

        @Override
        public String encode(MatchMessage m) throws EncodeException {
                StringWriter swriter = new StringWriter();
                try (JsonWriter jsonWrite = Json.createWriter(swriter)) {
                        JsonObjectBuilder builder = Json.createObjectBuilder();
                        builder.add(
                                "match",
                                Json.createObjectBuilder()
                                        .add("serve", m.getMatch().getServe())
                                        .add("title", m.getMatch().getTitle())
                                        ...
                        }

                        jsonWrite.writeObject(builder.build());
                }
                return swriter.toString();
        }
}

客户端实现Websocket的javascript库包:websocket.js

var wsUrl;
if (window.location.protocol == 'https:') { 
        wsUrl = 'wss://' + window.location.host + ':8443/usopen/matches/1234';
} else {
        wsUrl = 'ws://' + window.location.host + ':8000/usopen/matches/1234';
}

function createWebSocket(host) {
        if (!window.WebSocket) {   
        ...
        } else {
                socket = new WebSocket(host);  
                socket.onopen = function() {
                        document.getElementById("m1-status").innerHTML = 'CONNECTED...';
                };
                socket.onclose = function() {
                        document.getElementById("m1-status").innerHTML = 'FINISHED';
                };
                ...
                socket.onmessage = function(msg) {
                        try {
                                console.log(data);
                                var obj = JSON.parse(msg.data);    
                                if (obj.hasOwnProperty("match")){  
                                        //title
                                        m1title.innerHTML = obj.match.title;
                                        // comments
                                        m1comments.value = obj.match.comments;
                                        // serve
                                        if (obj.match.serve === "player1") {
                                                m1p1serve.innerHTML = "S";
                                                m1p2serve.innerHTML = "";
                                        } else {
                                                m1p1serve.innerHTML = "";
                                                m1p2serve.innerHTML = "S";
                                        }
                                        ..
                                }
                                ...
                        } catch (exception) {
                                data = msg.data;
                                console.log(data);
                        }
                }
        }
}

 

本案例源码下载

 

WebSocket详解

JavaEE教程

Java学习心得