一人分饰多角(bushi)
添加 WebSocketConfig 配置org.springframework.boot spring-boot-starter-websocket
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
实体bean接收客户端发过来的信息
@Data
public class SocketMsg {
private int type;
private String sendOutUser;
private String receiveUser;
private String msg;
}
WebSocketUtil
import cn.hutool.json.JSONUtil;
import org.springframework.stereotype.Component;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;
@Component
@ServerEndpoint("/web-socket/{userName}")
public class WebSocketUtil {
private String userName;
private Session session;
private static final String USER_NAME_PREFIX = "user_name_";
private static CopyOnWriteArraySet webSocketSet = new CopyOnWriteArraySet<>();
private static ConcurrentHashMap sessionMap = new ConcurrentHashMap<>();
public synchronized static void privateMessage(SocketMsg socketMsg) {
//接收消息的用户
Session receiveUser = sessionMap.get(USER_NAME_PREFIX + socketMsg.getReceiveUser());
//发送给接收者
if(receiveUser != null){
//发送给接收者
System.out.println(socketMsg.getSendOutUser()+" 向 "+socketMsg.getReceiveUser()+" 发送了一条消息:"+socketMsg.getMsg());
receiveUser.getAsyncRemote().sendText(socketMsg.getSendOutUser()+":"+socketMsg.getMsg());
}else{
//发送消息的用户
System.out.println(socketMsg.getSendOutUser()+" 私聊的用户 "+socketMsg.getReceiveUser()+" 不在线或者输入的用户名不对");
Session sendOutUser = sessionMap.get(USER_NAME_PREFIX + socketMsg.getSendOutUser());
//将系统提示推送给发送者
sendOutUser.getAsyncRemote().sendText("系统消息:对方不在线或者您输入的用户名不对");
}
}
public synchronized static void publicMessage(String userName,String message,boolean flag) {
for (WebSocketUtil item : webSocketSet) {
Session session = item.session;
if (flag){
session.getAsyncRemote().sendText(message);
}else {
//获取发送这条消息的用户
Session currentUser = sessionMap.get(USER_NAME_PREFIX + userName);
//消息不用推送到发送者的客户端
if (!session.getId().equals(currentUser.getId())){
session.getAsyncRemote().sendText(message);
}
}
}
System.out.println("公共频道接收了一条消息:"+message);
}
@OnOpen
public void onOpen(Session session, @PathParam("userName") String userName) {
this.userName = userName;
this.session = session;
sessionMap.put(USER_NAME_PREFIX + userName, session);
webSocketSet.add(this);
//在线数加1
String tips = userName+" 加入聊天室。当前聊天室人数为" + webSocketSet.size();
System.out.println(tips);
publicMessage(userName,tips,true);
}
@OnMessage
public void onMessage(String message) {
if (JSONUtil.isTypeJSONObject(message)) {
SocketMsg socketMsg = JSONUtil.toBean(message, SocketMsg.class);
if(socketMsg.getType() == 1){
//单聊,需要找到发送者和接受者
privateMessage(socketMsg);
}else{
//群发消息
publicMessage(socketMsg.getSendOutUser(),socketMsg.getSendOutUser()+": "+socketMsg.getMsg(),false);
}
}
}
@OnClose
public void onClose() {
if (sessionMap.containsKey(USER_NAME_PREFIX + userName)) {
//连接关闭后,将此websocket从set中删除
sessionMap.remove(USER_NAME_PREFIX + userName);
webSocketSet.remove(this);
}
String tips = userName+" 退出聊天室。当前聊天室人数为" + webSocketSet.size();
System.out.println(tips);
publicMessage(userName,tips,true);
}
@OnError
public void onError(Throwable error) {
System.out.println("userName为:" + userName + ",发生错误:" + error.getMessage());
error.printStackTrace();
}
}
前端代码
聊天室
聊天室



