一开始是看着这篇博客写的《使用websocket简单实现多人聊天》,不过有bug(用户名使用的是在线人数作为用户名,当用户退出后,用户名是人数就会出现bug了,可以自己试试,最好是用动态参数)。
而且由于这是springboot启动的,需要额外写个配置类,具体原因可以看这篇文章https://blog.csdn.net/Xyouzi/article/details/113914558,如果使用独立的servlet容器则不需要
-
目录结构
-
引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
- 前端页面(index.html用于用户使用,admin.html用于发布广播)
index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>多人在线聊天</title>
</head>
<body>
<input id="text" type="text">
<button onclick="send()">发送消息</button>
<button onclick="closeWebSocket()">退出多人聊天</button>
<hr>
<div id="message"></div>
================================================================
<script type="text/javascript">
var websocket=null;
let name = "";
if('WebSocket' in window){
name = location.href.split('?')[1].split("=")[1];
websocket=new WebSocket("ws://localhost:8088/websocket/server/"+name);
}
else{
alert('当前浏览器不支持websocket')
}
//连接失败事件
websocket.onerror=function(){
setMessageInnerHTML("连接失败!");
}
//连接成功事件
websocket.onopen=function(){
setMessageInnerHTML("成功加入聊天室");
}
//有消息从服务器端发送过来
websocket.onmessage=function (event){
setMessageInnerHTML(event.data);
}
//关闭事件
websocket.onclose=function(){
setMessageInnerHTML('退出聊天室!')
}
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>
</html>
admin.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>多人在线聊天</title>
</head>
<body>
<input id="text" type="text">
<button onclick="send()">发送公告</button>
<hr>
<div id="message"></div>
================================================================
<script type="text/javascript">
var websocket=null;
let name = "";
if('WebSocket' in window){
name = location.href.split('?')[1].split("=")[1];
websocket=new WebSocket("ws://localhost:8088/websocket/server/"+name);
}
else{
alert('当前浏览器不支持websocket')
}
//连接失败事件
websocket.onerror=function(){
setMessageInnerHTML("连接失败!");
}
//连接成功事件
websocket.onopen=function(){
setMessageInnerHTML("可发布广播");
}
//有消息从服务器端发送过来
websocket.onmessage=function (event){
setMessageInnerHTML('已发送广播');
}
//关闭事件
websocket.onclose=function(){
setMessageInnerHTML('退出控制台!')
}
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>
</html>
4.后端代码
@Component
@ServerEndpoint("/websocket/server/{username}")
public class MySocket {
// 记录当前在线记录数
private static AtomicInteger onlineCount = new AtomicInteger();
// 存储每个客户端
private static CopyOnWriteArraySet<MySocket> socketSet = new CopyOnWriteArraySet<MySocket>();
private Session session;
private String name;
@OnOpen//连接成功
public void onOpen(Session session, @PathParam(value = "username") String userName) {
this.session = session;
socketSet.add(this);
addOnlineCount();
this.name = "用户" + userName;//简易用户名
try {
if ("用户all".equals(this.name)){
return;
} else {
this.sendMessage("系统:欢迎您!你是" + this.name + ",开始聊天吧!");
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("有新连接加入!当前在线人数为" + onlineCount);
}
@OnClose//关闭
public void onClose() {
subOnlineCount();
socketSet.remove(this);
System.out.println("一个用户离开了!当前在线人数" + onlineCount);
}
@OnError//连接出错
public void onError(Session session, Throwable error) {
System.out.println("连接发生错误");
error.printStackTrace();
}
@OnMessage//当客户端有消息传来时
public void onMessage(String message, Session session) {
System.out.println("来自客户端的消息,由" + this.name + "发出:" + message);
String mstemp;
for (MySocket mySocket : socketSet) {
System.out.println(this.name);
if ("用户all".equals(this.name)) {
System.out.println("--"+this.name+"--");
mstemp = "广播:" + message;
}
else if (this.name.equals(mySocket.name)) { //处理客户端消息
mstemp = "我" + ":" + message;
}
else {
mstemp = this.name + ":" + message;
}
try {
mySocket.sendMessage(mstemp);
} catch (IOException e) {
e.printStackTrace();
continue;
}
}
}
public void sendMessage(String message) throws IOException {
this.session.getBasicRemote().sendText(message);
}
public static synchronized void addOnlineCount() {
onlineCount.incrementAndGet();
}
public static synchronized void subOnlineCount() {
onlineCount.decrementAndGet();
}
}
还有记得在配置里改端口