# Spring WebSocket(XML 配置方式) ## 一、项目说明 ### 1.1 项目结构 1. 项目模拟一个简单的群聊功能,为区分不同的聊天客户端,登录时候将临时用户名存储在 session 当中; 2. CustomHander 为自定义的消息处理器; 3. CustomHandershakerInterceptor 为自定义的 websocket 的握手拦截器; 4. 项目以 web 的方式构建。
### 1.2 基本依赖 除了基本的 Spring 依赖外,还需要导入 WebSocket 的相关依赖: ```xml org.springframework spring-websocket 5.1.3.RELEASE ``` ## 二、实现 WebSocket ### 2.1 消息处理器 继承自TextWebSocketHandler,创建消息处理类: ```java /** * @description : 自定义消息处理类 */ public class CustomHandler extends TextWebSocketHandler { private Map nameAndSession = new ConcurrentHashMap<>(); // 建立连接时候触发 @Override public void afterConnectionEstablished(WebSocketSession session) { String username = getNameFromSession(session); nameAndSession.putIfAbsent(username, session); } // 关闭连接时候触发 @Override public void afterConnectionClosed(WebSocketSession session, CloseStatus status) { String username = getNameFromSession(session); nameAndSession.remove(username); } // 处理消息 @Override protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { // 防止中文乱码 String msg = URLDecoder.decode(message.getPayload(), "utf-8"); String username = getNameFromSession(session); // 简单模拟群发消息 TextMessage reply = new TextMessage(username + " : " + msg); nameAndSession.forEach((s, webSocketSession) -> { try { webSocketSession.sendMessage(reply); } catch (IOException e) { e.printStackTrace(); } }); } private String getNameFromSession(WebSocketSession session) { Map attributes = session.getAttributes(); return (String) attributes.get(Constant.USER_NAME); } } ``` ### 2.2 握手拦截器 创建websocket 握手拦截器(如果没有权限拦截等需求,这一步不是必须的): ```java /** * @description : 可以按照需求实现权限拦截等功能 */ public class CustomHandshakeInterceptor extends HttpSessionHandshakeInterceptor { @Override public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map attributes) throws Exception { InetSocketAddress remoteAddress = request.getRemoteAddress(); InetAddress address = remoteAddress.getAddress(); System.out.println(address); /* * 最后需要要显示调用父类方法,父类的 beforeHandshake 方法 * 把 ServerHttpRequest 中 session 中对应的值拷贝到 WebSocketSession 中。 * 如果我们没有实现这个方法,我们在最后的 handler 处理中 是拿不到 session 中的值 * 作为测试 可以注释掉下面这一行 可以发现自定义处理器中 session 的 username 总是为空 */ return super.beforeHandshake(request, response, wsHandler, attributes); } } ``` ### 2.3 配置 WebSocket ```xml ``` ### 2.4 前端 WebSocket ```jsp <%@ page contentType="text/html;charset=UTF-8" language="java" %> ${sessionScope.get("username")}您好!欢迎进入群聊大厅!
``` ### 2.5 实现简单登录 ```JSP <%@ page contentType="text/html;charset=UTF-8" language="java" %> Title
``` ```java @Controller public class LoginController { @PostMapping("login") public String login(String username, HttpSession session){ session.setAttribute(Constant.USER_NAME,username); return "chat"; } } ```