关于websocket自定义通信,聊天工具--博客园老牛大讲堂
声明: 我的文章会不断更新的,或许你今天看完后,我第二天就更新了。关注:博客园老牛大讲堂
关于websocket通信,我也没做过,我也是参考别人的才成功的!今天把文章给补全。参考地址(我也忘了,有空补上)。
首先jdk1.7和tomact7以上,才能用websocket. 并且需要jar包:websocket-api.jar
1、什么是websocket通信?
通信一般应用就是常见的聊天等软件。例如qq,微信等。
2、websocket有什么作用?
其实说白了,就是为了进行聊天的,或者实现群聊。如果你能把这一块儿做全了,那么你也可以推出一个聊天工具了。
3、常见的通信有哪几种?
通信分类:
1、现在网上出了很多第三方的通信。个人推荐这种。(毕竟人家的东西已经成熟),用着方便。(第三方通信)
2、另一种就是andorid原生开发了。应该也是借用第三方的通信(个人表示不清楚)(android通信)
3、如果你是一个H5用户,又不想借用第三方通信,那么就可以往下面看了。(例如:websocket)。(自定义消息通信)
补充:
1、对于android来说,一般用第三方通信:例如极光,融云等平台。
2、对于H5用户来说,一般也用第三方通信,也可以用websocket。
4、自定义消息通信怎样实现?(其他两种我就不介绍了)
接下来我介绍一种推送,它不借助与第三方工具是第三种情况。
1、MyWebSocket代码:
package Tools; import java.io.IOException import java.util.concurrent.CopyOnWriteArraySet; import javax.websocket.OnClose; import javax.websocket.OnError; import javax.websocket.OnMessage; import javax.websocket.OnOpen; import javax.websocket.Session; import javax.websocket.server.ServerEndpoint; //该注解用来指定一个URI,客户端可以通过这个URI来连接到WebSocket。类似Servlet的注解mapping。无需在web.xml中配置。---博客园老牛大讲堂 @ServerEndpoint("/chat")//这里的注释相当于web.xml了,所以可以不用配置web.xml了,当然配置了也不算错 public class MyWebSocket { //静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。---博客园老牛大讲堂 private static int onlineCount = 0; //concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。若要实现服务端与单一客户端通信的话,可以使用Map来存放,其中Key可以为用户标识 private static CopyOnWriteArraySet<MyWebSocket> webSocketSet = new CopyOnWriteArraySet<MyWebSocket>(); //与某个客户端的连接会话,需要通过它来给客户端发送数据---博客园老牛大讲堂 private Session session; /** * 连接建立成功调用的方法 * @param session 可选的参数。session为与某个客户端的连接会话,需要通过它来给客户端发送数据---博客园老牛大讲堂 */ @OnOpen public void onOpen(Session session){ this.session = session; webSocketSet.add(this); //加入set中 addOnlineCount(); //在线数加1 System.out.println("有新连接加入!当前在线人数为" + getOnlineCount()); // this.session.getBasicRemote().sendText(HttpServletRequest.getRemoteAddr());---博客园老牛大讲堂 } /** * 连接关闭调用的方法 */ @OnClose public void onClose(){ webSocketSet.remove(this); //从set中删除 subOnlineCount(); //在线数减1 System.out.println("有一连接关闭!当前在线人数为" + getOnlineCount()); } /** * 收到客户端消息后调用的方法 * @param message 客户端发送过来的消息 * @param session 可选的参数--博客园老牛大讲堂 */ @OnMessage public void onMessage(String message, Session session) { System.out.println("来自客户端的消息:" + message); //群发消息 for(MyWebSocket item: webSocketSet){ try { item.sendMessage(message); } catch (IOException e) { e.printStackTrace(); continue; } } } /** * 发生错误时调用 * @param session * @param error */ @OnError public void onError(Session session, Throwable error){ System.out.println("发生错误"); error.printStackTrace(); } /** * 这个方法与上面几个方法不一样。没有用注解,是根据自己需要添加的方法。--博客园老牛大讲堂 * @param message * @throws IOException */ public void sendMessage(String message) throws IOException{ this.session.getBasicRemote().sendText(message); //this.session.getAsyncRemote().sendText(message); } public static synchronized int getOnlineCount() { return onlineCount; } public static synchronized void addOnlineCount() { MyWebSocket.onlineCount++; } public static synchronized void subOnlineCount() { MyWebSocket.onlineCount--; } }
2、前端页面
index.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML> <html> <head> <script type="text/javascript" src="js/jquery.min.js"></script> <base href="<%=basePath%>"> <title>My WebSocket</title> </head> <body> Welcome<br/> <input id="text" type="text" /><button onclick="send()">Send</button> <button onclick="closeWebSocket()">Close</button> <div id="message"> </div> </body> <script type="text/JavaScript"> var websocket = null; //判断当前浏览器是否支持WebSocket if('WebSocket' in window){ websocket = new WebSocket("ws://localhost:8080/MyWebSocket/chat");//这里没有走web.xml,直接到了MyWebSocket } else{ alert('Not support websocket'); } //连接发生错误的回调方法 websocket.onerror = function(){ setMessageInnerHTML("error"); }; //连接成功建立的回调方法 websocket.onopen = function(event){ setMessageInnerHTML("open"); }; //接收到消息的回调方法 websocket.onmessage = function(){ setMessageInnerHTML(event.data); }; //连接关闭的回调方法 websocket.onclose = function(){ setMessageInnerHTML("close"); }; //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。 window.onbeforeunload = function(){ websocket.close(); }; //将消息显示在网页上 function setMessageInnerHTML(innerHTML){ document.getElementById('message').innerHTML += innerHTML + '<br/>'; } //关闭连接 function closeWebSocket(){ websocket.close(); } //发送消息 function send(){ var message = document.getElementById('text').value; websocket.send(message); } </script> <body>sds</body> </html>
3、web.xml可以不配置的(我的没有配置并且成功了)
注释:如果不成功,给我留言。(稍后我会上传我自己写的一个网页版的群聊软件)
5、webSocek群聊天工具(改进版)--博客园老牛大讲堂。
思路:用户都通过键值对的方式进行传递数据和内容。(这样就可以传递不同数据)
其中 ,是我自己在里面封装的方法,你们可以自己写的。
这个例子,重要的是一个思路。
后端代码不变!前端页面部分:--博客园老牛大讲堂
<!doctype html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimum-scale=1.0, maximum-scale=1.0"><meta name="format-detection" content="telephone=no"> <title>chat</title> <link rel="stylesheet" href="../../css/seedsui.min.css">//引入的第三方的css <script src="../../js/seedsui.min.js"></script>//引入的第三方的js <script type="text/javascript" src="../../js/swiperJs/jquery.min.js" ></script> <script type="text/javascript" src="../../js/myJs/check.js" ></script>//自己定义的方法-博客园老牛大讲堂。 <script type="text/javascript" src="../../js/myJs/jsoup.js" ></script>//自己定义的方法 <style> .niu-pandding-left-30{ padding-left: 30px; } .niu-user-font{ font-size: 14px; text-align: center; margin: 15px 40px 15px 0px; float: right; } .niu-huanying{ font-size: 14px; text-align: center; margin: 15px 40px 15px 0px; } .niu-button{ padding-left: 10px; } </style> </head> //博客园老牛大讲堂 <body ontouchstart=""> <header> <div class="titlebar niu-pandding-left-30"> <h1>内部讨论组</h1> </div> </header> <article style="padding-bottom:47px;"> <p class="niu-user-font" >时间:<span id="shijian">2017-04-24 9:40:26</span></p> <br /> <ul class="chat" id="niuChat"> <li> <div class="chat-photo"> <img src="../../img/photo.png" alt="male"> </div> <div class="chat-content-box"> <div class="chat-content"> <b>用户ID:<span>sadf</span></b> <p>啥?你说滴是啥?那啥啥啥东西啊?咋看不懂啊,你说滴到底是个啥?</p> </div> </div> </li> <li class="even"> <div class="chat-photo"> <img src="../../img/photo.png" alt="Female"> </div> <div class="chat-content-box"> <div class="chat-content"> <p>啥?你说滴是啥?那啥啥啥东西啊?咋看不懂啊,你说滴到底是个啥?</p> </div> </div> </li> </ul> </article> <footer> <div class="inputbox bordered margin8"> <a class="button niu-button">请输入内容:</a> <input type="text" class="input-text" id="NiuContent"/> <a class="button lrpadding8" onclick="send()">检验</a> </div> </footer> <script> var name="老师"; //时间初始化模块 clearUI(); function clearUI(){ $("#niuChat").empty();//清空内容 setInterval(function(){ $("#shijian").html("2016-05-04 14:12:12"));//主要实现显示时间,你也可以自己写个方法,动态的得到时间 }, 1000) } var websocket = null; //判断当前浏览器是否支持WebSocket if('WebSocket' in window){ websocket = new WebSocket("ws://localhost:8080/SecondWeb/chat");//这个是你后台写的webSocket. }else{ alert('你的浏览器不支持通信'); } //连接成功建立的回调方法 websocket.onopen = function(event){ setTimeout(function(){ websocket.send("name:"+name);//发送一句话,key值是name,把用户的名字发送给后台,这样大家都能看到你是谁了。 },4000); }; //接收到消息的回调方法--博客园老牛大讲堂。 websocket.onmessage = function(){ var value=fenge(event.data);//当服务器有返回值则,自动调用这个方法,event.data是服务器的数据。--博客园老牛大讲堂 //每当我发送消息,成功的话,服务器端就会返回信息,那么我就可以根据key值不同,得到不同的内容了。---- 博客园老牛大讲堂 if(value[0]=="name"){ var str=' <p class="niu-huanying">欢迎老师:《<span>'+value[1]+'</span>》进入房间</p><br/>'; $("#niuChat").append(str);//当这个人进入房间,动态添加数据 }else if(value[0]=="close"){ var str=' <p class="niu-huanying">《<span>'+value[1]+'</span>》老师已经离开了房间</p><br>'; $("#niuChat").append(str);//当老师退出房间,进行提示离开房间 } else if(value[0]=="closeAll"){ // console.log(value[0]+value[1]); } else if(value[0]=="content"){ var str=' <li><div class="chat-photo"><img src="../../img/photo.png" alt="male"></div>'+ '<div class="chat-content-box"><div class="chat-content"><span><'+name+'老师></span></b>'+ '<p>'+value[1]+'</p></div></div></li>'; $("#niuChat").append(str);//当某个用户发送内容,那么本页面进行信息的显示。 } }; //连接关闭的回调方法--博客园老牛大讲堂 websocket.onclose = function(){ websocket.send("close:"+name); }; //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。 window.onbeforeunload = function(){ websocket.send("close:"+name)//关闭连接,发送key值是close的内容。 websocket.close(); }; //关闭连接--博客园老牛大讲堂 function closeWebSocket(){ websocket.send("close:"+name) websocket.close(); } $(document).keydown(function(event){ if(event.keyCode == 13){ send();//当我敲击键盘空格键,那么进行发消息的内容。 } }); //发送消息--博客园老牛大讲堂 function send(){ var str=$("#NiuContent").val()+"";//进行输入框清空操作。 if(str!=""){ $("#NiuContent").val(""); websocket.send("content:"+str);//向服务器发送内容。 }else{ $("#NiuContent").attr("placeholder","内容不能为空"); } }
//对key值和value值根据:号进行数据的分割。---博客园老牛大讲堂 function fenge(str){ return str.split(":"); } </script> </body> </html>