博主最近做的项目有这样一个需求,需要将某监控系统的监控数据实时推送到web页面,以及集群之间的数据推送,这就可以使用Websocket来实现。
1.什么是Websocket?(以下说明copy来的)
WebSocket 协议在2008年诞生,2011年成为国际标准。现在所有浏览器都已经支持了。WebSocket 的最大特点就是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,实现真正的双向平等对话。
2.Websocket能做什么?
1.网页在线聊天
2.多人在线游戏
3.在线股票网站
4.在线新闻网站
5.应用集群之间的通信
6.远程系统/软件的状态和性能的实时监控
以上只是一部分,Websocket能做的远不止这些。
3.主要介绍Java WebSocket和javascript中的websocket的使用,js中websocket就是扮演一个客户端的角色,Java中的WebSocket分两种角色,一种是Java客户端终端的WebSocket(作用类似于JavaScript中的WebSocket),还有一种角色是Java服务器终端。
4.Websocket客户端
创建一个Websocket对象:
var webSocket = new WebSocket("ws://localhost:8001/socket");
在websocket中有几个常见方法:
webSocket.onopen=function (event) {
//连接成功时触发
}
webSocket.onclose=function (event) {
//连接关闭时触发
}
webSocket.onerror=function (event) {
event.data拿到错误信息
//连接出错时触发
}
webSocket.onmessage=function (event) {
event.data拿到消息
//收到消息时触发
}
//向服务端发送消息
webSocket.send(msg)
//关闭当前Websocket连接
webSocket.close()
websocket还定义了一个readyState属性,这个属性可以返回websocket所处的状态:
1、CONNECTING(0) websocket正尝试与服务器建立连接
2、OPEN(1) websocket与服务器已经建立连接
3、CLOSING(2) websocket正在关闭与服务器的连接
4、CLOSED(3) websocket已经关闭了与服务器的连接
if(webSocket.readyState==WebSocket.OPEN){/*do something*/}
5.Web页面测试代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<input type="button" value="连接" id="btnClick1"><br>
<input type="text" id="msg"><input type="button" value="发送" id="btnClick2">
</div>
<div id="resultDiv"></div>
<script src="js/jquery-1.12.4.js" type="text/javascript"></script>
<script>
var webSocket;
$("#btnClick2").click(function () {
var msg = $("#msg").val();
$("#resultDiv").append("<p>发送消息:" + msg+"</p>");
webSocket.send(msg)
});
$("#btnClick1").click(function () {
$("#resultDiv").append("<p>开始连接服务端!</p>");
webSocket = new WebSocket("ws://localhost:8001/socket");
webSocket.onerror = function (event) {
$("#resultDiv").append("<p>onerror:" + event.data + "</p>");
}
webSocket.onopen = function (event) {
$("#resultDiv").append("<p>连接成功!</p>");
}
webSocket.onmessage = function (event) {
$("#resultDiv").append("<p>onmessage:" + event.data + "</p>");
}
});
</script>
</body>
</html>
6.服务端配置
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
7.服务端逻辑代码
注意记得加上@Component,不加会出现握手失败404错误,注解@ServerEndpoint后跟的地址就是请求地址,且可以跟参数,如@ServerEndpoint(value = "/socket/{id}"),@ServerEndpoint(value = "/socket/{name}"),跟参数后,可在方法参数中使用注解@PathParam(value = "name")来获取。如跟用户绑定的参数,记得在服务端设置对应属性,如private String name,且在连接成功时赋值;
@ServerEndpoint(value = "/socket")
@Component
public class WebSocketServer {
//用来记录当前在线连接数,线程安全。
private static int onlineCount = 0;
//线程安全Set,存放每个客户端的MyWebSocket对象。
private static CopyOnWriteArraySet<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<WebSocketServer>();
//与某个客户端的连接会话
private Session session;
/**
* 连接建立成功调用的方法*/
@OnOpen
public void onOpen(Session session) {
System.out.println(session.getAsyncRemote());
this.session = session;
webSocketSet.add(this); //加入set中
addOnlineCount(); //在线数加1
sendMessage("有新连接加入!当前在线人数为" + getOnlineCount());
}
/**
* 连接关闭调用的方法
*/
@OnClose
public void onClose() {
webSocketSet.remove(this); //从set中删除
subOnlineCount(); //在线数减1
sendMessage("有用户退出!当前在线人数为" + getOnlineCount());
}
/**
* 收到客户端消息后调用的方法
*
* @param message 客户端发送过来的消息*/
@OnMessage
public void onMessage(String message, Session session){
System.out.println("来自客户端的消息:" + message);
//群发消息
sendInfo("服务端返回:"+session.getId()+"-"+message);
}
/**
* 发生错误时调用
* @OnError
**/
@OnError
public void onError(Session session, Throwable error) {
System.out.println("发生错误");
error.printStackTrace();
}
/**
* 向客户端发送消息
* @param message 消息内容
* */
private void sendMessage(String message) {
this.session.getAsyncRemote().sendText(message);
}
/**
* 群发自定义消息
* */
private static void sendInfo(String message){
for (WebSocketServer item : webSocketSet) {
item.sendMessage(message);
}
}
public static synchronized int getOnlineCount() {
return onlineCount;
}
public static synchronized void addOnlineCount() {
WebSocketServer.onlineCount++;
}
public static synchronized void subOnlineCount() {
WebSocketServer.onlineCount--;
}
}
8.测试结果如图: