websocket实现在线客服系统
1、后端
先实现一个端点服务。注意:在websocket中导入ChatService时候必须是static的,不然会是null。
@Slf4j
@Component
@ServerEndpoint("/stu/chat/{name}")
public class ChatController {
private static ChatService chatMsgService;
@Autowired
public void setChatService(ChatService chatService) {
ChatController.chatMsgService = chatService;
}
private static final Map<String, Session> clients = new ConcurrentHashMap<>();
@OnOpen
public void onOpen(@PathParam("name") String name, Session session) {
log.info("有新的连接:{}", name);
add(name, session);
log.info("当前在线用户数:{}", clients.size());
}
/**
* 发送消息,前端将消息转成json字符串,后端转成对象
*/
@OnMessage
public void onMessage(String message, Session session) {
ObjectMapper mapper = new ObjectMapper();
try {
ChatMsg msg = mapper.readValue(message, ChatMsg.class);
if ("1".equals(msg.getSendType())) {
// 广播
sendMessageAll(msg.getMsg(), msg.getSendUser());
} else if ("2".equals(msg.getSendType())) {
// 群聊
sendMessageGroup(msg.getMsg(), msg.getMsg());
} else if ("3".equals(msg.getSendType())) {
Session se = clients.get(msg.getAcceptUser());
if (se != null) {
sendMessage(se, msg);
} else {
msg.setIsRead("0");
}
new Thread(() -> {
if (chatMsgService == null) {
log.error("保存聊天消息出错:chatMsgService为null");
return;
}
chatMsgService.addMsg(msg);
}).start();
}
} catch (JsonProcessingException e) {
log.info("发送消息出错");
e.printStackTrace();
}
}
@OnClose
public void onClose(@PathParam("name") String name, Session session) {
log.info("{}:退出聊天", name);
remove(name);
log.info("当前在线用户数:{}", clients.size());
}
@OnError
public void onError(Session session, Throwable throwable) {
try {
session.close();
} catch (IOException e) {
log.error("退出发生异常: {}", e.getMessage());
}
log.info("连接出现异常: {}", throwable.getMessage());
}
/**
* 新增一个连接
*/
public static void add(String name, Session session) {
if (!name.isEmpty() && session != null) {
clients.put(name, session);
}
}
/**
* 删除一个连接
*/
public static void remove(String name) {
if (!name.isEmpty()) {
clients.remove(name);
}
}
/**
* 获取在线人数
*/
public static int count() {
return clients.size();
}
/**
* 广播
*
* @param message 发送的消息
* @param username 发送人
*/
public static void sendMessageAll(String message, String username) {
log.info("广播消息:{}", message);
clients.forEach((key, session) -> {
if (!username.equals(key)) {
RemoteEndpoint.Async remote = session.getAsyncRemote();
if (remote == null) {
return;
}
remote.sendText(message);
}
});
}
/**
* 群聊
*
* @param message 发送的消息
* @param username 发送人
*/
public static void sendMessageGroup(String message, String username) {
log.info("群发消息");
clients.forEach((key, session) -> {
if (!username.equals(key)) {
RemoteEndpoint.Async remote = session.getAsyncRemote();
if (remote == null) {