本案例将session的id模拟为用户id,将session保存到ConcurrentHashMap中,用来获取到指定人的session,并向其发送消息。
一、引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
二、添加ServerEndpointExporter配置bean
@Configuration
public class WebSocketConfig {
/**
* 注入一个serverEndPointExporter,该Bean会自动注册使用@serverEndpoint注解声明的websocket endpoint
* @return
*/
@Bean
public ServerEndpointExporter serverEndpointExporter(){
return new ServerEndpointExporter();
}
}
三、建立连接、收发消息
@ServerEndpoint("/clientToClient")
@Component
public class ClientToClient {
//用来存储所有连接到服务的客户端信息
//ConcurrentHashMap使用了synchronized,是线程安全的
private static ConcurrentHashMap<String, Session> clients = new ConcurrentHashMap();
//线程安全的
private static AtomicInteger onlineClient = new AtomicInteger(0);
@OnOpen
public void OnOpen(Session session){
//在线人数加1
onlineClient.incrementAndGet();
System.out.println("有新连接["+session.getId()+"]加入,当前在线总人数为:"+onlineClient+"个");
clients.put(session.getId(),session);
}
@OnClose
public void OnClose(Session session){
onlineClient.decrementAndGet();
clients.remove(session.getId());
System.out.println(session.getId()+"离线...");
}
public void sendMessageToClent(ClientMessage message){
try {
if(clients.get(message.getUserid())!=null) {
clients.get(message.getUserid()).getBasicRemote().sendText(message.getMessage());
}else{
System.out.println("指定的用户已离线,数据存入数据库,当他上线时再行通知!");
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
四、前端向后端发送请求,后端处理后再发消息出去
@RestController
@RequestMapping("/chat")
public class SendMessageController {
@Autowired
ClientToClient clientToClient;
@RequestMapping("/sendMsg")
public void sendMessage(@RequestBody Map map){
clientToClient.sendMessageToClent(new ClientMessage(map.get("userId").toString(),map.get("message").toString()));
}
}
五、前端代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>WebSocket聊天室</title>
<script src="jquery-3-6-0.js"></script>
</head>
<body>
<h6>WebSocket聊天室</h6>
<input id="userId" type="text" placeholder="模拟用户登录后有userId">
<input id="text" type="text">
<button onclick="sendMessage()">发送</button>
<button onclick="closeConnect()">断开</button>
<div id="message"></div>
<script type="text/javascript">
//连接服务器
var webSocket = new WebSocket("ws://localhost:8080/clientToClient");
//连接成功时的回调方法
webSocket.onopen = function (event) {
document.getElementById('message').innerHTML += '连接服务器成功!<br/>';
}
//接收到服务器返回消息的回调方法
webSocket.onmessage = function (event) {
document.getElementById('message').innerHTML += event.data+'<br/>';
}
//向服务器发送消息
function sendMessage() {
var msg = document.getElementById('text').value;
var userId = document.getElementById('userId').value;
var data = {
"userId":userId,
"message":msg
};
$.ajax({
contentType:"application/json",
type: "POST",
url: "/chat/sendMsg",
dataType:"json",
data: JSON.stringify(data)
});
}
//关闭与服务器的连接
function closeConnect(){
webSocket.close();
}
</script>
</body>
</html>
六、运行效果