1.需求:通过websocket实现在线聊天室
2.流程分析
3.消息格式
- 客户端 --> 服务端
{"toName":"张三","message":"你好"}
- 服务端 --> 客户端
- 系统消息格式:
{"system":true,"fromName":null,"message":["李四","王五"]}
- 推送给某一个用户的消息格式:
{"system":false,"fromName":"张三","message":"你好"}
4.代码实现
4.1.引入坐标
在pom.xml
中引入依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId></dependency>
4.2.编写配置类,扫描添加有@ServerEndpoint注解的 Bean
package com.itheima.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;/*** @version v1.0* @ClassName: WebsocketConfig* @Description: TODO(一句话描述该类的功能)* @Author:*/
@Configuration
public class WebsocketConfig {@Beanpublic ServerEndpointExporter serverEndpointExporter() {return new ServerEndpointExporter();}
}
4.3.编写配置类,用于获取 HttpSession 对象
package com.itheima.config;import javax.servlet.http.HttpSession;
import javax.websocket.HandshakeResponse;
import javax.websocket.server.HandshakeRequest;
import javax.websocket.server.ServerEndpointConfig;/*** @version v1.0* @ClassName: GetHttpSessionConfig* @Description: TODO(一句话描述该类的功能)* @Author: */
public class GetHttpSessionConfig extends ServerEndpointConfig.Configurator {@Overridepublic void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response) {//获取HttpSession对象HttpSession httpSession = (HttpSession) request.getHttpSession();//将httpSession对象保存起来sec.getUserProperties().put(HttpSession.class.getName(),httpSession);}
}
4.4.编写ChatEndpoint类 在 @ServerEndpoint 注解中引入配置器
package com.itheima.ws;import com.alibaba.fastjson.JSON;
import com.itheima.config.GetHttpSessionConfig;
import com.itheima.utils.MessageUtils;
import com.itheima.ws.pojo.Message;
import org.springframework.stereotype.Component;import javax.servlet.http.HttpSession;
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;/*** @version v1.0* @ClassName: ChatEndpoint* @Description: TODO(一句话描述该类的功能)* @Author:*/
@ServerEndpoint(value = "/chat",configurator = GetHttpSessionConfig.class)
@Component
public class ChatEndpoint {private static final Map<String,Session> onlineUsers = new ConcurrentHashMap<>();private HttpSession httpSession;/*** 建立websocket连接后,被调用* @param session*/@OnOpenpublic void onOpen(Session session, EndpointConfig config) {//1,将session进行保存this.httpSession = (HttpSession) config.getUserProperties().get(HttpSession.class.getName());String user = (String) this.httpSession.getAttribute("user");onlineUsers.put(user,session);//2,广播消息。需要将登陆的所有的用户推送给所有的用户String message = MessageUtils.getMessage(true,null,getFriends());broadcastAllUsers(message);}public Set getFriends() {Set<String> set = onlineUsers.keySet();return set;}private void broadcastAllUsers(String message) {try {//遍历map集合Set<Map.Entry<String, Session>> entries = onlineUsers.entrySet();for (Map.Entry<String, Session> entry : entries) {//获取到所有用户对应的session对象Session session = entry.getValue();//发送消息session.getBasicRemote().sendText(message);}} catch (Exception e) {//记录日志}}/*** 浏览器发送消息到服务端,该方法被调用** 张三 --> 李四* @param message*/@OnMessagepublic void onMessage(String message) {try {//将消息推送给指定的用户Message msg = JSON.parseObject(message, Message.class);//获取 消息接收方的用户名String toName = msg.getToName();String mess = msg.getMessage();//获取消息接收方用户对象的session对象Session session = onlineUsers.get(toName);String user = (String) this.httpSession.getAttribute("user");String msg1 = MessageUtils.getMessage(false, user, mess);session.getBasicRemote().sendText(msg1);} catch (Exception e) {//记录日志}}/*** 断开 websocket 连接时被调用* @param session*/@OnClosepublic void onClose(Session session) {//1,从onlineUsers中剔除当前用户的session对象String user = (String) this.httpSession.getAttribute("user");if (user != null) {onlineUsers.remove(user);//2,通知其他所有的用户,当前用户下线了String message = MessageUtils.getMessage(true, null, getFriends());broadcastAllUsers(message);} else {// 处理 user 为空的情况,可以记录日志或者采取其他适当的措施}}
}
4.5.完整代码如下:
github:https://github.com/RanGuMo/itheima_chat.git