java 开发 websocket 网页端聊天室

博客地址:https://ainyi.com/67

WebSocket协议是基于TCP的一种新的网络协议。它实现了浏览器与服务器全双工(full-duplex)通信——允许服务器主动发送信息给客户端。

需要导入一个jar包:javax.websocket-api-1.0-rc4.jar

注意点:

需要实现这几个方法:

 1 //注册事件
 2     ws.onopen = function(){
 3           openWs();
 4     };
 5     ws.onmessage = function(event){
 6            msgWs(event);
 7     };
 8     ws.onclose = function(){
 9           closeWs();
10     };
11     ws.onerror = function(){
12           errorWs();
13     };

后台代码:

 1 package com.krry.socket;
 2 import java.io.IOException;
 3 import java.util.concurrent.CopyOnWriteArraySet;
 4  
 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  
12 //该注解用来指定一个URI,客户端可以通过这个URI来连接到WebSocket。类似Servlet的注解mapping。无需在web.xml中配置。
13 @ServerEndpoint("/websocket")
14 public class MyWebSocket {
15     //静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
16     private static int onlineCount = 0;
17      
18     //concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。若要实现服务端与单一客户端通信的话,可以使用Map来存放,其中Key可以为用户标识
19     private static CopyOnWriteArraySet<MyWebSocket> webSocketSet = new CopyOnWriteArraySet<MyWebSocket>();
20      
21     //与某个客户端的连接会话,需要通过它来给客户端发送数据
22     private Session session;
23      
24     /**
25      * 连接建立成功调用的方法
26      * @param session  可选的参数。session为与某个客户端的连接会话,需要通过它来给客户端发送数据
27      */
28     @OnOpen
29     public void onOpen(Session session){
30         this.session = session;
31         webSocketSet.add(this);     //加入set中
32         addOnlineCount();           //在线数加1
33         System.out.println("有新连接加入!当前在线人数为" + getOnlineCount());
34     }
35      
36     /**
37      * 连接关闭调用的方法
38      */
39     @OnClose
40     public void onClose(){
41         webSocketSet.remove(this);  //从set中删除
42         subOnlineCount();           //在线数减1    
43         System.out.println("有一连接关闭!当前在线人数为" + getOnlineCount());
44     }
45      
46     /**
47      * 收到客户端消息后调用的方法
48      * @param message 客户端发送过来的消息
49      * @param session 可选的参数
50      */
51     @OnMessage
52     public void onMessage(String message, Session session) {
53         System.out.println("来自客户端的消息:" + message);
54          
55         //群发消息
56         for(MyWebSocket item: webSocketSet){             
57             try {
58                 item.sendMessage(message);
59             } catch (IOException e) {
60                 e.printStackTrace();
61                 continue;
62             }
63         }
64     }
65      
66     /**
67      * 发生错误时调用
68      * @param session
69      * @param error
70      */
71     @OnError
72     public void onError(Session session, Throwable error){
73         System.out.println("发生错误");
74         error.printStackTrace();
75     }
76      
77     /**
78      * 这个方法与上面几个方法不一样。没有用注解,是根据自己需要添加的方法。
79      * @param message
80      * @throws IOException
81      */
82     public void sendMessage(String message) throws IOException{
83         this.session.getBasicRemote().sendText(message);
84         //this.session.getAsyncRemote().sendText(message);
85     }
86  
87     public static synchronized int getOnlineCount() {
88         return onlineCount;
89     }
90  
91     public static synchronized void addOnlineCount() {
92         MyWebSocket.onlineCount++;
93     }
94      
95     public static synchronized void subOnlineCount() {
96         MyWebSocket.onlineCount--;
97     }
98 }

前端代码:

  1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
  2 <!doctype html>
  3 <html>
  4     <head>
  5         <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
  6         <meta name="keywords" content="">
  7         <meta name="description" content="">
  8         <title>基于Java服务器端的消息主动推送技术揭秘 --krry</title>
  9         <link rel="stylesheet" href="css/animate.css"/>
 10         <link rel="stylesheet" type="text/css" href="css/sg.css" />
 11         <style>
 12             *{margin:0;padding:0;}
 13             body{background:url("images/5.jpg");background-size:cover;}
 14             h1{margin-top:50px;text-align:center;color:#fff;text-shadow:1px 1px 1px #000;font-family:-webkit-body;font-size:24px;}
 15             .box{width:700px;margin:20px auto;}
 16             .box span{color:#f60;font-size:16px;font-family:"微软雅黑";}
 17             .box .shu{text-indent:1em;height:24px;font-family:"微软雅黑";border:0;outline:none;font-size:14px;}
 18             .box .add{width:300px;margin-right:24px;}
 19             .box .user{width:200px;}
 20             .box .btn{width:80px;height:34px;color:#fff;background:#6c0;border:0;outline:none;cursor:pointer;margin-top:20px;font-size:16px;font-family:"微软雅黑";}
 21             .box .area{line-height: 29px;height:280px;width:680px;padding:10px;overflow:auto;font-size:16px;font-family:"微软雅黑";margin:20px 0;outline:none;box-shadow:1px 2px 18px #000}
 22             .box .setex{text-indent:1em;height:28px;border:1px solid #6c0;width:618px;outline:none;float:left;font-family:"微软雅黑";}
 23             .box .send{font-size:14px;width:80px;height:30px;color:#fff;background:#6c0;border:0;outline:none;cursor:pointer;font-family:"微软雅黑";}
 24         </style>
 25     </head>
 26     <body>
 27         <h1>基于Java服务器端的消息主动推送技术揭秘 --krry</h1>
 28         <div class="box">
 29             <span>服务器地址:</span><input type="text" class="shu add" value="localhost/krry_NetChat/websocket" readonly/>
 30             <span>用户名:</span><input type="text" class="shu user" value="匿名"/>
 31             <input type="button" value="连接" class="btn" />
 32             <div class="area" id="boxx"></div>
 33             <div class="c_cen">
 34                 <input type="text" class="setex"/>
 35                 <input type="button" value="发送" class="send">
 36             </div>
 37         </div>
 38         <script src="js/jquery-1.11.1.min.js"></script>
 39         <script src="js/sg.js"></script>
 40         <script src="js/sgutil.js"></script>
 41         <script>
 42             var close = true;
 43             var ws;
 44             $(function(){
 45                 $(".c_cen").hide();
 46                 //首先判断浏览器是否支持webSocket,支持h5的浏览器才会支持
 47                 if(window.WebSocket){
 48                     printMsg("您的浏览器支持WebSocket,您可以尝试连接到聊天服务器!","OK");
 49                 }else{
 50                     printMsg("您的浏览器不支持WebSocket,请选择其他浏览器!","ERROR");
 51                     //设置按钮不可点击
 52                     $(".btn").attr("disabled","true");
 53                 }
 54             });
 55             //打印信息
 56             function printMsg(msg,msgType){
 57                 if(msgType == "OK"){
 58                     msg = "<span style='color:green'>"+msg+"</span>";
 59                 }
 60                 if(msgType == "ERROR"){
 61                     msg = "<span style='color:red'>"+msg+"</span>";
 62                 }
 63                 $(".area").append(msg+"<br/>");
 64                 var boxx = document.getElementById("boxx");
 65                 boxx.scrollTop = boxx.scrollHeight;//使滚动条一直在底部
 66             }
 67             
 68             //打开Socket
 69             function openWs(){
 70                 printMsg("链接已建立","OK");
 71                 ws.send(""+$(".user").val()+"】已进入聊天室");
 72                 $(".c_cen").show();
 73             }
 74             
 75             //接收消息的时候
 76             function msgWs(e){
 77                 printMsg(e.data);
 78             }
 79             //关闭连接
 80             function closeWs(){
 81                 $(".btn").val("连接");
 82                 $(".c_cen").hide();
 83             }
 84             //产生错误
 85             function errorWs(){
 86                 printMsg("您与服务器连接错误...","ERROR");
 87             }
 88 
 89             //点击发送按钮
 90             $(".send").click(function(){
 91                 var text = $(".setex").val();
 92                 if(text == null || text == "") return;
 93                 $(".setex").val("");
 94                 ws.send(""+$(".user").val()+"】:"+text);
 95             });
 96             
 97             //点击连接
 98             $(".btn").click(function(){
 99                 if($(".add").val() && $(".user").val()){
100                     if(close){
101                         printMsg("正在准备连接服务器,请稍等...");
102                         var url = "ws://"+$(".add").val();
103                         if("WebSocket" in window){
104                             ws = new WebSocket(url);
105                         }else if("MozWebSocket" in window){
106                             ws = new MozWebSocket(url);
107                         }
108                         //已连接
109                         $(".btn").val("断开");
110                         close = false;
111                         
112                         //注册事件
113                         ws.onopen = function(){
114                             openWs();
115                         };
116                         ws.onmessage = function(event){
117                             msgWs(event);
118                         };
119                         ws.onclose = function(){
120                             closeWs();
121                         };
122                         ws.onerror = function(){
123                             errorWs();
124                         };
125                         
126                         //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
127                         window.onbeforeunload = function(){
128                             ws.send(""+$(".user").val()+"】离开了聊天室");
129                             close = true;
130                             ws.close();
131                         };
132                         
133                     }else{
134                         ws.send(""+$(".user").val()+"】离开了聊天室");
135                         close = true;
136                         ws.close();
137                     }
138                 }else{
139                     $.tmDialog.alert({open:"left",content:"服务器地址和用户名不能为空哦...",title:"提示哦~~~"});
140                 }
141             });
142             
143             //回车键
144             $(".setex").keypress(function(event){
145                 if(event.keyCode == 13){
146                     $(".send").trigger("click");
147                 }
148             });
149         </script>
150     </body>
151 </html>

博客地址:https://ainyi.com/67

原文地址:https://www.cnblogs.com/ainyi/p/8592226.html