- 准备
导入websocket相关依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
- 监听websocket类
package com.neo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RestController;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import static com.neo.utils.WebSocketUtils.ONLINE_USER_SESSIONS;
import static com.neo.utils.WebSocketUtils.sendMessageAll;
@RestController
@ServerEndpoint("/chat-room/{username}")
public class ChatRoomServerEndpoint {
private static final Logger logger = LoggerFactory.getLogger(ChatRoomServerEndpoint.class);
@OnOpen
public void openSession(@PathParam("username") String username, Session session) {
ONLINE_USER_SESSIONS.put(username, session);
String message = "欢迎用户[" + username + "] 来到聊天室!";
logger.info("用户登录:"+message);
sendMessageAll(message);
}
@OnMessage
public void onMessage(@PathParam("username") String username, String message) {
logger.info("发送消息:"+message);
sendMessageAll("用户[" + username + "] : " + message);
}
@OnClose
public void onClose(@PathParam("username") String username, Session session) {
//当前的Session 移除
ONLINE_USER_SESSIONS.remove(username);
//并且通知其他人当前用户已经离开聊天室了
sendMessageAll("用户[" + username + "] 已经离开聊天室了!");
try {
session.close();
} catch (IOException e) {
logger.error("onClose error",e);
}
}
@OnError
public void onError(Session session, Throwable throwable) {
try {
session.close();
} catch (IOException e) {
logger.error("onError excepiton",e);
}
logger.info("Throwable msg "+throwable.getMessage());
}
}
- 发送消息工具类
package com.neo.utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.websocket.RemoteEndpoint;
import javax.websocket.Session;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public final class WebSocketUtils {
private static final Logger logger = LoggerFactory.getLogger(WebSocketUtils.class);
// 存储 websocket session
public static final Map<String, Session> ONLINE_USER_SESSIONS = new ConcurrentHashMap<>();
/**
* @param session 用户 session
* @param message 发送内容
*/
public static void sendMessage(Session session, String message) {
if (session == null) {
return;
}
final RemoteEndpoint.Basic basic = session.getBasicRemote();
if (basic == null) {
return;
}
try {
basic.sendText(message);
} catch (IOException e) {
logger.error("sendMessage IOException ",e);
}
}
//群发消息
public static void sendMessageAll(String message) {
ONLINE_USER_SESSIONS.forEach((sessionId, session) -> sendMessage(session, message));
}
//发送给指定用户
public static void sendMessageToUser(String username,String message) {
//username 指定接收用户名称 (ONLINE_USER_SESSIONS的key)
Session toUser = ONLINE_USER_SESSIONS.get(username);
sendMessage(toUser,message);
}
}
- 前台页面及建立websocket脚本
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>chat room websocket</title>
<link rel="stylesheet" href="bootstrap.min.css">
<script src="jquery-3.2.1.min.js" ></script>
</head>
<body class="container" style="width: 60%">
<div class="form-group" ></br>
<h5>聊天室</h5>
<textarea id="message_content" class="form-control" readonly="readonly" cols="50" rows="10"></textarea>
</div>
<div class="form-group" >
<label for="in_user_name">用户姓名 </label>
<input id="in_user_name" value="" class="form-control" /></br>
<button id="user_join" class="btn btn-success" >加入聊天室</button>
<button id="user_exit" class="btn btn-warning" >离开聊天室</button>
</div>
<div class="form-group" >
<label for="in_room_msg" >群发消息 </label>
<input id="in_room_msg" value="" class="form-control" /></br>
<button id="user_send_all" class="btn btn-info" >发送消息</button>
</div>
</body>
<script type="text/javascript">
$(document).ready(function(){
var urlPrefix ='ws://localhost:8080/chat-room/';
var ws = null;
$('#user_join').click(function(){
var username = $('#in_user_name').val();
if(username==''){
alert("请输入用户名!");
return;
}
var url = urlPrefix + username;
ws = new WebSocket(url);
ws.onopen = function () {
console.log("建立 websocket 连接...");
};
ws.onmessage = function(event){
//服务端发送的消息
$('#message_content').append(event.data+'\n');
};
ws.onclose = function(){
$('#message_content').append('用户['+username+'] 已经离开聊天室!');
console.log("关闭 websocket 连接...");
}
});
//客户端发送消息到服务器
$('#user_send_all').click(function(){
var msg = $('#in_room_msg').val();
if(msg==''){
alert("请填写消息!");
return;
}
if(ws && msg!=''){
ws.send(msg);
}
});
// 退出聊天室
$('#user_exit').click(function(){
if(ws){
ws.close();
}
});
})
</script>
</html>
原理:
将各个用户存入ONLINE_USER_SESSIONS
群发:遍历这个Map里的所有的用户并发送消息。
点对点:根据Map获取指定的用户,发送消息。