Java WebSocket的简单使用
此案例主要使用WebSocket实现代理系统发布公告时,App端可以实时显示出来
代码:
前台
- App端
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<h1>App手机客户端</h1>
<div id="">
<ul id="notice">
</ul>
</div>
<script type="text/javascript" src="js/jquery-1.9.1.min.js"></script>
<script type="text/javascript">
//向公告内容里面插入新公告
function addNotice(content) {
//向ul>li插入公告
var ul = $('#notice').append('<li>' + content + '</li>')
}
//初始化WebSocket连接
//判断当前浏览器是否支持WebSocket
if('WebSocket' in window) {
console.log('浏览器支持WebSocket')
websocket = new WebSocket("ws://192.168.0.118:8085/myssh/websocket/server/app");
} else {
alert('当前浏览器不支持 websocket')
}
//连接发生错误的回调方法
websocket.onerror = function() {
console.log("WebSocket连接发生错误");
};
//连接成功建立的回调方法
websocket.onopen = function() {
websocket.send('APP客户端连接成功');
}
//接收到消息的回调方法
websocket.onmessage = function(event) {
addNotice(event.data);
}
//连接关闭的回调方法
websocket.onclose = function() {
console.log("WebSocket连接关闭");
}
//监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
window.onbeforeunload = function() {
closeWebSocket();
}
//关闭WebSocket连接
function closeWebSocket() {
websocket.close();
}
</script>
</body>
</html>
- 代理
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
<h1>后台管理系统</h1>
<span id="">
此案例主要使用WebSocket实现后台管理系统发布公告时,App端可以实时显示出来
</span>
<hr />
<input id="msg" placeholder="公告内容"/>
<input type="button" value="发送" id="send"/>
<script type="text/javascript" src="js/jquery-1.9.1.min.js" ></script>
<script type="text/javascript">
//判断当前浏览器是否支持WebSocket
if('WebSocket' in window) {
console.log('浏览器支持WebSocket')
websocket = new WebSocket("ws://192.168.0.118:8085/myssh/websocket/server/代理");
} else {
alert('当前浏览器不支持 websocket')
}
//连接发生错误的回调方法
websocket.onerror = function() {
console.log("WebSocket连接发生错误");
};
//连接成功建立的回调方法
websocket.onopen = function() {
websocket.send('代理端连接成功');
}
//接收到消息的回调方法
websocket.onmessage = function(event) {
console.log(event.data)
}
//连接关闭的回调方法
websocket.onclose = function() {
console.log("WebSocket连接关闭");
}
//监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
window.onbeforeunload = function() {
closeWebSocket();
}
//关闭WebSocket连接
function closeWebSocket() {
websocket.close();
}
/**
* 发布公告
*/
$('#send').click(()=>{
//alert(1)
//获取公告内容
websocket.send($('#msg').val());
})
</script>
</body>
</html>
后台[就只有一个类,使用的是tomcat的websocket实现,文章结尾会介绍其他方法]
package com.ssh.socket;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
/**
* 后台管理系统发布公告
* @author asus
*
*/
/**
* @ServerEndpoint和springMVC @RequestMapping有点像,就是一个用来处理http/https请求的,一个是用来处理ws/wss请求的
* "/websocket/server/{username}"这个也是对应的前端的请求地址:"ws://192.168.0.118:8085/myssh/websocket/server/代理"
* 前端请求webSocket就不是使用http了,而是ws
* {username}对应的就是“代理”了,这种写法是为了获取前端请求路径上面的参数,这里必须要写,否则下面的@PathParam("username")获取不到参数
*/
@ServerEndpoint("/websocket/server/{username}")
public class WebSocketServer {
//用于存放所有连接进来的客户端
private static Map<String, WebSocketServer> clients = new ConcurrentHashMap<String, WebSocketServer>();
private Session session;
private String username;
@OnOpen
public void onOpen(@PathParam("username") String username, Session session) {
session.getAsyncRemote().sendText("服务器接收到了客户端的连接请求!");
this.username = username;
this.session = session;
clients.put(username, this);
}
@OnClose
public void onClose() {
System.out.println("后台管理系统已关闭连接");
}
@OnMessage
public void onMessage(@PathParam("username") String username, String message) {
System.err.println("接收到客户端的消息:" + message);
/**
* 通知所有人[包括代理和用户]
*/
for (WebSocketServer item : clients.values()) {
item.session.getAsyncRemote().sendText(this.username + " : " + message);
}
}
@OnError
public void onError(Session session, Throwable error) {
error.printStackTrace();
}
}
讲解
实际上是两个前端都连接至后台,然后后台将两个客户端都存入Map集合中,当然也可以自己定义一个类来存放用户和代理的信息,可以用来区分连接进来的是代理还是用户,此案例中没有进行代理和用户之间的区分,只是单纯的实现代理实时向用户[客户端]发送消息,发送消息就是通过循环去发送[因为之前已经把所有用户都存入Map],相当于每个连接进来的用户都是一个独立的连接,如果自己添加什么东西进行区分代理和用户,也可以在此基础上实现只给用户发送消息。