WebSocket协议主要用来实现后台服务端主动向客户端推送消息,当然,协议本身支持双向通信。
在Spring项目中集成WebSocket还是比较简单的,但是WebSocket的Session和HttpSession并不相通,如果想获取HttpSession中的登录用户就要稍费工夫,因此,记录成篇。
一、集成WebSocket
-
项目添加依赖包:
<!-- SpringBoot Websocket --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency>
-
增加WebSocketConfig配置类:
/** * websocket 配置 * * @author xhp */ @Configuration public class WebSocketConfig { @Bean public ServerEndpointExporter serverEndpointExporter() { return new ServerEndpointExporter(); } }
-
编写WebSocketSever类:
@Component @ServerEndpoint(value = "/ws/message") public class WebSocketServer { /** * 连接建立成功调用的方法 */ @OnOpen public void onOpen(Session session) throws Exception { } /** * 连接关闭时处理 */ @OnClose public void onClose(Session session) { } /** * 抛出异常时处理 */ @OnError public void onError(Session session, Throwable exception) throws Exception { if (session.isOpen()) { // 关闭连接 session.close(); } } /** * 服务器接收到客户端消息时调用的方法 */ @OnMessage public void onMessage(String message, Session session) { } }
-
编写html页面,测试连接:
<script type="text/javascript"> $(document).ready(function(){ // WebSocket var wsBaseUrl = /*[[${"ws://" + #httpServletRequest.getServerName() + ":" + #httpServletRequest.getServerPort() + #httpServletRequest.getContextPath()}]]*/''; var ws = new WebSocket(wsBaseUrl + '/ws/message'); ws.onopen = function (event) { console.log('WS已打开连接'); } ws.onmessage = function (event) { // TODO 接收消息 console.log(event.data); } ws.onclose = function (event) { console.log('WS已关闭连接'); } // 发送消息 $('#btn_send').click(function() { var message = $('#message').val(); if (ws) { ws.send(message); } else { alert("未连接到服务器"); } }); //断开 $('#btn_exit').click(function() { if (ws) { ws.close(); ws = null; } }); }) </script>
二、WebSocket会话获得登录用户
-
场景说明:
- 项目中常见场景,需要给某个用户或者某类用户推送消息;
- 我们需要在全部的WebSocket连接会话里根据登录用户匹配有效的发送会话;
- 因为WebSocket的Session和HttpSession是相互独立的,本身没用对应关系,那么,我们只能想办法把需要的信息放到Session里。
-
修改WebSocketConfig配置类,重写其继承类的方法,将用户信息放入,示例如下:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.socket.server.standard.ServerEndpointExporter; import javax.websocket.HandshakeResponse; import javax.websocket.server.HandshakeRequest; import javax.websocket.server.ServerEndpointConfig; /** * websocket 配置 * * @author xhp */ @Configuration public class WebSocketConfig extends ServerEndpointConfig.Configurator { @Bean public ServerEndpointExporter serverEndpointExporter() { return new ServerEndpointExporter(); } @Override public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response) { // 将用户信息存储到socket的配置里 sec.getUserProperties().put("sysUser", ShiroUtils.getSysUser()); super.modifyHandshake(sec, request, response); } }
-
修改WebSocketServer类,读取用户信息,示例如下:
/** * websocket 消息处理 * * @author xhp */ @Component @ServerEndpoint(value = "/ws/message", configurator = WebSocketConfig.class) public class WebSocketServer { /** * 连接建立成功调用的方法 */ @OnOpen public void onOpen(Session session) throws Exception { // 读取用户信息 SysUser sysUser= (SysUser)session.getUserProperties().get("sysUser"); } }
三、注意事项
- 本示例项目是Springboot,如果项目是Spring而非Springboot,那么第一步的依赖包有所不同,后面的步骤是一致的;
-
WebSocketServer
类的类注解需要增加对配置文件的引入
configurator = WebSocketConfig.class
,否则配置文件的重写方法是不生效的;
版权声明:本文为xhp312098226原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。