java WebSocket 简易聊天消息推送实例方法介绍



java WebSocket 简易聊天消息推送实例方法介绍。

环境:

JDK.1.7.0_51

apache-tomcat-7.0.53

java jar包:tomcat-coyote.jar、tomcat-juli.jar、websocket-api.jar

ChatAnnotation消息发送类:

 

  1. import java.io.IOException;
  2. import java.util.HashMap;
  3. import java.util.Map;
  4. import java.util.concurrent.atomic.AtomicInteger;
  5. import javax.websocket.OnClose;
  6. import javax.websocket.OnError;
  7. import javax.websocket.OnMessage;
  8. import javax.websocket.OnOpen;
  9. import javax.websocket.Session;
  10. import javax.websocket.server.ServerEndpoint;
  11. import org.apache.juli.logging.Log;
  12. import org.apache.juli.logging.LogFactory;
  13. import com.util.HTMLFilter;
  14. /**
  15.  * WebSocket 消息推送服务类
  16.  * @author 胡汉三
  17.  *
  18.  * 2014-11-18 下午7:53:13
  19.  */
  20. @ServerEndpoint(value = ”/websocket/chat”)
  21. public class ChatAnnotation {
  22.     private static final Log log = LogFactory.getLog(ChatAnnotation.class);
  23.     private static final String GUEST_PREFIX = ”Guest”;
  24.     private static final AtomicInteger connectionIds = new AtomicInteger(0);
  25.     private static final Map<String,Object> connections = new HashMap<String,Object>();
  26.     private final String nickname;
  27.     private Session session;
  28.     public ChatAnnotation() {
  29.         nickname = GUEST_PREFIX + connectionIds.getAndIncrement();
  30.     }
  31.     @OnOpen
  32.     public void start(Session session) {
  33.         this.session = session;
  34.         connections.put(nickname, this);
  35.         String message = String.format(“* %s %s”, nickname, ”has joined.”);
  36.         broadcast(message);
  37.     }
  38.     @OnClose
  39.     public void end() {
  40.         connections.remove(this);
  41.         String message = String.format(“* %s %s”,
  42.                 nickname, ”has disconnected.”);
  43.         broadcast(message);
  44.     }
  45.     /**
  46.      * 消息发送触发方法
  47.      * @param message
  48.      */
  49.     @OnMessage
  50.     public void incoming(String message) {
  51.         // Never trust the client
  52.         String filteredMessage = String.format(“%s: %s”,
  53.                 nickname, HTMLFilter.filter(message.toString()));
  54.         broadcast(filteredMessage);
  55.     }
  56.     @OnError
  57.     public void onError(Throwable t) throws Throwable {
  58.         log.error(“Chat Error: ” + t.toString(), t);
  59.     }
  60.     /**
  61.      * 消息发送方法
  62.      * @param msg
  63.      */
  64.     private static void broadcast(String msg) {
  65.         if(msg.indexOf(“Guest0″)!=-1){
  66.             sendUser(msg);
  67.         } else{
  68.             sendAll(msg);
  69.         }
  70.     }
  71.     /**
  72.      * 向所有用户发送
  73.      * @param msg
  74.      */
  75.     public static void sendAll(String msg){
  76.         for (String key : connections.keySet()) {
  77.             ChatAnnotation client = null ;
  78.             try {
  79.                 client = (ChatAnnotation) connections.get(key);
  80.                 synchronized (client) {
  81.                     client.session.getBasicRemote().sendText(msg);
  82.                 }
  83.             } catch (IOException e) {
  84.                 log.debug(“Chat Error: Failed to send message to client”, e);
  85.                 connections.remove(client);
  86.                 try {
  87.                     client.session.close();
  88.                 } catch (IOException e1) {
  89.                     // Ignore
  90.                 }
  91.                 String message = String.format(“* %s %s”,
  92.                         client.nickname, ”has been disconnected.”);
  93.                 broadcast(message);
  94.             }
  95.         }
  96.     }
  97.     /**
  98.      * 向指定用户发送消息
  99.      * @param msg
  100.      */
  101.     public static void sendUser(String msg){
  102.         ChatAnnotation c = (ChatAnnotation)connections.get(“Guest0″);
  103.         try {
  104.             c.session.getBasicRemote().sendText(msg);
  105.         } catch (IOException e) {
  106.             log.debug(“Chat Error: Failed to send message to client”, e);
  107.             connections.remove(c);
  108.             try {
  109.                 c.session.close();
  110.             } catch (IOException e1) {
  111.                 // Ignore
  112.             }
  113.             String message = String.format(“* %s %s”,
  114.                     c.nickname, ”has been disconnected.”);
  115.             broadcast(message);
  116.         }
  117.     }
  118. }

 

HTMLFilter工具类:

 

  1. /**
  2.  * HTML 工具类
  3.  *
  4.  * @author 胡汉三
  5.  */
  6. public final class HTMLFilter {
  7.     public static String filter(String message) {
  8.         if (message == null)
  9.             return (null);
  10.         char content[] = new char[message.length()];
  11.         message.getChars(0, message.length(), content, 0);
  12.         StringBuilder result = new StringBuilder(content.length + 50);
  13.         for (int i = 0; i < content.length; i++) {
  14.             switch (content[i]) {
  15.             case ’<’:
  16.                 result.append(“<”);
  17.                 break;
  18.             case ’>’:
  19.                 result.append(“>”);
  20.                 break;
  21.             case ’&’:
  22.                 result.append(“&”);
  23.                 break;
  24.             case ’”‘:
  25.                 result.append(“”");
  26.                 break;
  27.             default:
  28.                 result.append(content[i]);
  29.             }
  30.         }
  31.         return (result.toString());
  32.     }
  33. }

 


页面:

 

  1. <%@ page language=”java” import=”java.util.*” pageEncoding=”UTF-8″%>
  2. <%
  3. String path = request.getContextPath();
  4. String basePath = request.getScheme()+”://”+request.getServerName()+”:”+request.getServerPort()+path+”/”;
  5. %>
  6. <?xml version=”1.0″ encoding=”UTF-8″?>
  7. <html xmlns=”http://www.w3.org/1999/xhtml” xml:lang=”en”>
  8. <head>
  9.     <title>测试</title>
  10.     <style type=”text/css”>
  11.         input#chat {
  12.             width: 410px
  13.         }
  14.         #console-container {
  15.             width: 400px;
  16.         }
  17.         #console {
  18.             border: 1px solid #CCCCCC;
  19.             border-right-color: #999999;
  20.             border-bottom-color: #999999;
  21.             height: 170px;
  22.             overflow-y: scroll;
  23.             padding: 5px;
  24.             width: 100%;
  25.         }
  26.         #console p {
  27.             padding: 0;
  28.             margin: 0;
  29.         }
  30.  </style>
  31.     <script type=”text/javascript”>
  32.         var Chat = {};
  33.         Chat.socket = null;
  34.         Chat.connect = (function(host) {
  35.             if (‘WebSocket’ in window) {
  36.                 Chat.socket = new WebSocket(host);
  37.             } else if (‘MozWebSocket’ in window) {
  38.                 Chat.socket = new MozWebSocket(host);
  39.             } else {
  40.                 Console.log(‘Error: WebSocket is not supported by this browser.’);
  41.                 return;
  42.             }
  43.             Chat.socket.onopen = function () {
  44.                 Console.log(‘Info: WebSocket connection opened.’);
  45.                 document.getElementById(‘chat’).onkeydown = function(event) {
  46.                     if (event.keyCode == 13) {
  47.                         Chat.sendMessage();
  48.                     }
  49.                 };
  50.             };
  51.             Chat.socket.onclose = function () {
  52.                 document.getElementById(‘chat’).onkeydown = null;
  53.                 Console.log(‘Info: WebSocket closed.’);
  54.             };
  55.             Chat.socket.onmessage = function (message) {
  56.                 Console.log(message.data);
  57.             };
  58.         });
  59.         Chat.initialize = function() {
  60.             if (window.location.protocol == ’http:’) {
  61.                 Chat.connect(‘ws://’ + window.location.host + ’/socket2/websocket/chat’);
  62.             } else {
  63.                 Chat.connect(‘wss://’ + window.location.host + ’/socket2/websocket/chat’);
  64.             }
  65.         };
  66.         Chat.sendMessage = (function() {
  67.             var message = document.getElementById(‘chat’).value;
  68.             if (message != ”) {
  69.                 Chat.socket.send(message);
  70.                 document.getElementById(‘chat’).value = ”;
  71.             }
  72.         });
  73.         var Console = {};
  74.         Console.log = (function(message) {
  75.             var console = document.getElementById(‘console’);
  76.             var p = document.createElement(‘p’);
  77.             p.style.wordWrap = ’break-word’;
  78.             p.innerHTML = message;
  79.             console.appendChild(p);
  80.             while (console.childNodes.length > 25) {
  81.                 console.removeChild(console.firstChild);
  82.             }
  83.             console.scrollTop = console.scrollHeight;
  84.         });
  85.         Chat.initialize();
  86.         document.addEventListener(“DOMContentLoaded”, function() {
  87.             // Remove elements with ”noscript” class - <noscript> is not allowed in XHTML
  88.             var noscripts = document.getElementsByClassName(“noscript”);
  89.             for (var i = 0; i < noscripts.length; i++) {
  90.                 noscripts[i].parentNode.removeChild(noscripts[i]);
  91.             }
  92.         }, false);
  93.    </script>
  94. </head>
  95. <body>
  96. <div class=”noscript”><h2 style=”color: #ff0000″>Seems your browser doesn’t support Javascript! Websockets rely on Javascript being enabled. Please enable
  97.     Javascript and reload this page!</h2></div>
  98. <div>
  99.     <p>
  100.         <input type=”text” placeholder=”请输入内容” id=”chat” />
  101.     </p>
  102.     <div id=”console-container”>
  103.         <div id=”console”/>
  104.     </div>
  105. </div>
  106. </body>
  107. </html>

可指定发送给某个用户,也可全部发送,详情见ChatAnnotation类的broadcast方法。

程序发布时记得删除tomcat-coyote.jar、tomcat-juli.jar、websocket-api.jar这三个jar包在启动Tomcat。

程序截图,Guest0用户发送信息的信息,在后台进行了判断只发送给自己:

Guest1:

Guest2: