在Java中使用WebSocket实现网页聊天室

时间:2022-05-16 10:08:17
关于WebSocket的例子貌似不多,但最好的例子已经有了。偶然间发现tomcat的自带的例子中,已经有了基于WebSocket实现的聊天室例子。这里就不献丑,直接拿来用了。

首先,服务端的实现ChatAnnotation.Java 

[java] view plain copy 在Java中使用WebSocket实现网页聊天室在Java中使用WebSocket实现网页聊天室
  1. /* 
  2.  *  Licensed to the Apache Software Foundation (ASF) under one or more 
  3.  *  contributor license agreements.  See the NOTICE file distributed with 
  4.  *  this work for additional information regarding copyright ownership. 
  5.  *  The ASF licenses this file to You under the Apache License, Version 2.0 
  6.  *  (the "License"); you may not use this file except in compliance with 
  7.  *  the License.  You may obtain a copy of the License at 
  8.  * 
  9.  *      http://www.apache.org/licenses/LICENSE-2.0 
  10.  * 
  11.  *  Unless required by applicable law or agreed to in writing, software 
  12.  *  distributed under the License is distributed on an "AS IS" BASIS, 
  13.  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
  14.  *  See the License for the specific language governing permissions and 
  15.  *  limitations under the License. 
  16.  */  
  17. package websocket.chat;  
  18.   
  19. import java.io.IOException;  
  20. import java.util.Set;  
  21. import java.util.concurrent.CopyOnWriteArraySet;  
  22. import java.util.concurrent.atomic.AtomicInteger;  
  23.   
  24. import javax.websocket.OnClose;  
  25. import javax.websocket.OnError;  
  26. import javax.websocket.OnMessage;  
  27. import javax.websocket.OnOpen;  
  28. import javax.websocket.Session;  
  29. import javax.websocket.server.ServerEndpoint;  
  30.   
  31. @ServerEndpoint(value = "/chat")  
  32. public class ChatAnnotation {  
  33.   
  34.     private static final String GUEST_PREFIX = "Guest";  
  35.     private static final AtomicInteger connectionIds = new AtomicInteger(0);  
  36.     private static final Set<ChatAnnotation> connections =  
  37.             new CopyOnWriteArraySet<>();  
  38.   
  39.     private final String nickname;  
  40.     private Session session;  
  41.   
  42.     public ChatAnnotation() {  
  43.         nickname = GUEST_PREFIX + connectionIds.getAndIncrement();  
  44.     }  
  45.   
  46.     @OnOpen  
  47.     public void start(Session session) {  
  48.         this.session = session;  
  49.         connections.add(this);  
  50.         String message = String.format("* %s %s", nickname, "has joined.");  
  51.         broadcast(message);  
  52.     }  
  53.   
  54.     @OnClose  
  55.     public void end() {  
  56.         connections.remove(this);  
  57.         String message = String.format("* %s %s",  
  58.                 nickname, "has disconnected.");  
  59.         broadcast(message);  
  60.     }  
  61.   
  62.     @OnMessage  
  63.     public void incoming(String message) {  
  64.         // Never trust the client  
  65.         // TODO: 过滤输入的内容  
  66.         broadcast(message);  
  67.     }  
  68.   
  69.     @OnError  
  70.     public void onError(Throwable t) throws Throwable {  
  71.         System.out.println("Chat Error: " + t.toString());  
  72.     }  
  73.   
  74.     private static void broadcast(String msg) {  
  75.         for (ChatAnnotation client : connections) {  
  76.             try {  
  77.                 synchronized (client) {  
  78.                     client.session.getBasicRemote().sendText(msg);  
  79.                 }  
  80.             } catch (IOException e) {  
  81.                 System.out.println("Chat Error: Failed to send message to client");  
  82.                 connections.remove(client);  
  83.                 try {  
  84.                     client.session.close();  
  85.                 } catch (IOException e1) {  
  86.                     // Ignore  
  87.                 }  
  88.                 String message = String.format("* %s %s",  
  89.                         client.nickname, "has been disconnected.");  
  90.                 broadcast(message);  
  91.             }  
  92.         }  
  93.     }  
  94. }  

稍微解释下上面这段代码。

@ServerEndpoint(value = "/websocket/chat")定义一个WebSocket服务端。value即访问地址。这个例子中:客户端通过 ws://{domain}/{context}/chat 来进行连接
Set<ChatAnnotation> connections用于存储聊天室中的连接实例
@OnPen,连接创建时调用的方法
@OnClose,连接关闭时调用的方法
@OnMessage,传输信息过程中调用的方法
@OnError,发生错误时调用的方法
broadcast(String msg),通过connections,对所有其他用户推送信息的方法

客户端的实现chat.xhtml 

[java] view plain copy 在Java中使用WebSocket实现网页聊天室在Java中使用WebSocket实现网页聊天室
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <!--  
  3.   Licensed to the Apache Software Foundation (ASF) under one or more  
  4.   contributor license agreements.  See the NOTICE file distributed with  
  5.   this work for additional information regarding copyright ownership.  
  6.   The ASF licenses this file to You under the Apache License, Version 2.0  
  7.   (the "License"); you may not use this file except in compliance with  
  8.   the License.  You may obtain a copy of the License at  
  9.   
  10.       http://www.apache.org/licenses/LICENSE-2.0  
  11.   
  12.   Unless required by applicable law or agreed to in writing, software  
  13.   distributed under the License is distributed on an "AS IS" BASIS,  
  14.   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
  15.   See the License for the specific language governing permissions and  
  16.   limitations under the License.  
  17. -->  
  18. <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">  
  19. <head>  
  20.     <title>Apache Tomcat WebSocket Examples: Chat</title>  
  21.     <style type="text/css"><![CDATA[  
  22.         input#chat {  
  23.             width: 410px  
  24.         }  
  25.   
  26.         #console-container {  
  27.             width: 400px;  
  28.         }  
  29.   
  30.         #console {  
  31.             border: 1px solid #CCCCCC;  
  32.             border-right-color: #999999;  
  33.             border-bottom-color: #999999;  
  34.             height: 170px;  
  35.             overflow-y: scroll;  
  36.             padding: 5px;  
  37.             width: 100%;  
  38.         }  
  39.   
  40.         #console p {  
  41.             padding: 0;  
  42.             margin: 0;  
  43.         }  
  44.     ]]></style>  
  45.     <script type="application/javascript"><![CDATA[  
  46.         "use strict";  
  47.   
  48.         var Chat = {};  
  49.   
  50.         Chat.socket = null;  
  51.   
  52.         Chat.connect = (function(host) {  
  53.             if ('WebSocket' in window) {  
  54.                 Chat.socket = new WebSocket(host);  
  55.             } else if ('MozWebSocket' in window) {  
  56.                 Chat.socket = new MozWebSocket(host);  
  57.             } else {  
  58.                 Console.log('Error: WebSocket is not supported by this browser.');  
  59.                 return;  
  60.             }  
  61.   
  62.             Chat.socket.onopen = function () {  
  63.                 Console.log('Info: WebSocket connection opened.');  
  64.                 document.getElementById('chat').onkeydown = function(event) {  
  65.                     if (event.keyCode == 13) {  
  66.                         Chat.sendMessage();  
  67.                     }  
  68.                 };  
  69.             };  
  70.   
  71.             Chat.socket.onclose = function () {  
  72.                 document.getElementById('chat').onkeydown = null;  
  73.                 Console.log('Info: WebSocket closed.');  
  74.             };  
  75.   
  76.             Chat.socket.onmessage = function (message) {  
  77.                 Console.log(message.data);  
  78.             };  
  79.         });  
  80.   
  81.         Chat.initialize = function() {  
  82.             if (window.location.protocol == 'http:') {  
  83.                 Chat.connect('ws://' + window.location.host + '/websocket/chat');  
  84.             } else {  
  85.                 Chat.connect('wss://' + window.location.host + '/websocket/chat');  
  86.             }  
  87.         };  
  88.   
  89.         Chat.sendMessage = (function() {  
  90.             var message = document.getElementById('chat').value;  
  91.             if (message != '') {  
  92.                 Chat.socket.send(message);  
  93.                 document.getElementById('chat').value = '';  
  94.             }  
  95.         });  
  96.   
  97.         var Console = {};  
  98.   
  99.         Console.log = (function(message) {  
  100.             var console = document.getElementById('console');  
  101.             var p = document.createElement('p');  
  102.             p.style.wordWrap = 'break-word';  
  103.             p.innerHTML = message;  
  104.             console.appendChild(p);  
  105.             while (console.childNodes.length > 25) {  
  106.                 console.removeChild(console.firstChild);  
  107.             }  
  108.             console.scrollTop = console.scrollHeight;  
  109.         });  
  110.   
  111.         Chat.initialize();  
  112.   
  113.         document.addEventListener("DOMContentLoaded", function() {  
  114.             // Remove elements with "noscript" class - <noscript> is not allowed in XHTML  
  115.             var noscripts = document.getElementsByClassName("noscript");  
  116.             for (var i = 0; i < noscripts.length; i++) {  
  117.                 noscripts[i].parentNode.removeChild(noscripts[i]);  
  118.             }  
  119.         }, false);  
  120.   
  121.     ]]></script>  
  122. </head>  
  123. <body>  
  124. <div class="noscript"><h2 style="color: #ff0000">Seems your browser doesn't support Javascript! Websockets rely on Javascript being enabled. Please enable  
  125.     Javascript and reload this page!</h2></div>  
  126. <div>  
  127.     <p>  
  128.         <input type="text" placeholder="type and press enter to chat" id="chat" />  
  129.     </p>  
  130.     <div id="console-container">  
  131.         <div id="console"/>  
  132.     </div>  
  133. </div>  
  134. </body>  
  135. </html>  

客户端的代码也是很简单,就是载入页面的时候,创建跟服务器的WebSocket连接。

[javascript] view plain copy 在Java中使用WebSocket实现网页聊天室在Java中使用WebSocket实现网页聊天室
  1. Chat.connect('ws://' + window.location.host + '/websocket/chat');  

然后就是发送信息,接收信息了。
完成上述代码之后,就可以部署了。这里我使用的servlet容器是tomcat 8。以下是我的配置: 

[html] view plain copy 在Java中使用WebSocket实现网页聊天室在Java中使用WebSocket实现网页聊天室
  1. <Context path="/websocket" docBase="/Users/cevin/Documents/workspace/tomcat_websocket_chat/web" reloadable="true"/>  

部署结束,启动tomcat,访问:http://localhost:8080/websocket/chat.xhtml,见到下面这个页面,说明部署成功了。

在Java中使用WebSocket实现网页聊天室

基本上,通过这个例子就可以知道如何使用WebSocket来进行开发了。这么强大的WebSocket,想一想都觉得兴奋!


转自【http://www.open-open.com/lib/view/open1425526066775.html】via http://my.oschina.NET/cevin15/blog/382582