声明: 我的文章会不断更新的,或许你今天看完后,我第二天就更新了。关注:博客园老牛大讲堂
关于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>