# spring-boot-demo-websocket-socketio
> 此 demo 主要演示了 Spring Boot 如何使用 `netty-socketio` 集成 WebSocket,实现一个简单的聊天室。
## 1. 代码
### 1.1. pom.xml
```xml
* websocket服务器配置 *
* * @author yangkai.shen * @date Created in 2018-12-18 16:42 */ @Configuration @EnableConfigurationProperties({WsConfig.class}) public class ServerConfig { @Bean public SocketIOServer server(WsConfig wsConfig) { com.corundumstudio.socketio.Configuration config = new com.corundumstudio.socketio.Configuration(); config.setHostname(wsConfig.getHost()); config.setPort(wsConfig.getPort()); //这个listener可以用来进行身份验证 config.setAuthorizationListener(data -> { // http://localhost:8081?token=xxxxxxx // 例如果使用上面的链接进行connect,可以使用如下代码获取用户密码信息,本文不做身份验证 String token = data.getSingleUrlParam("token"); // 校验token的合法性,实际业务需要校验token是否过期等等,参考 spring-boot-demo-rbac-security 里的 JwtUtil // 如果认证不通过会返回一个 Socket.EVENT_CONNECT_ERROR 事件 return StrUtil.isNotBlank(token); }); return new SocketIOServer(config); } /** * Spring 扫描自定义注解 */ @Bean public SpringAnnotationScanner springAnnotationScanner(SocketIOServer server) { return new SpringAnnotationScanner(server); } } ``` ### 1.3. MessageEventHandler.java > 核心事件处理类,主要处理客户端发起的消息事件,以及主动往客户端发起事件 ```java /** ** 消息事件处理 *
* * @author yangkai.shen * @date Created in 2018-12-18 18:57 */ @Component @Slf4j public class MessageEventHandler { @Autowired private SocketIOServer server; @Autowired private DbTemplate dbTemplate; /** * 添加connect事件,当客户端发起连接时调用 * * @param client 客户端对象 */ @OnConnect public void onConnect(SocketIOClient client) { if (client != null) { String token = client.getHandshakeData().getSingleUrlParam("token"); // 模拟用户id 和token一致 String userId = client.getHandshakeData().getSingleUrlParam("token"); UUID sessionId = client.getSessionId(); dbTemplate.save(userId, sessionId); log.info("连接成功,【token】= {},【sessionId】= {}", token, sessionId); } else { log.error("客户端为空"); } } /** * 添加disconnect事件,客户端断开连接时调用,刷新客户端信息 * * @param client 客户端对象 */ @OnDisconnect public void onDisconnect(SocketIOClient client) { if (client != null) { String token = client.getHandshakeData().getSingleUrlParam("token"); // 模拟用户id 和token一致 String userId = client.getHandshakeData().getSingleUrlParam("token"); UUID sessionId = client.getSessionId(); dbTemplate.deleteByUserId(userId); log.info("客户端断开连接,【token】= {},【sessionId】= {}", token, sessionId); client.disconnect(); } else { log.error("客户端为空"); } } /** * 加入群聊 * * @param client 客户端 * @param request 请求 * @param data 群聊 */ @OnEvent(value = Event.JOIN) public void onJoinEvent(SocketIOClient client, AckRequest request, JoinRequest data) { log.info("用户:{} 已加入群聊:{}", data.getUserId(), data.getGroupId()); client.joinRoom(data.getGroupId()); server.getRoomOperations(data.getGroupId()).sendEvent(Event.JOIN, data); } @OnEvent(value = Event.CHAT) public void onChatEvent(SocketIOClient client, AckRequest request, SingleMessageRequest data) { Optional* websocket服务器启动 *
* * @author yangkai.shen * @date Created in 2018-12-18 17:07 */ @Component @Slf4j public class ServerRunner implements CommandLineRunner { @Autowired private SocketIOServer server; @Override public void run(String... args) { server.start(); log.info("websocket 服务器启动成功。。。"); } } ``` ## 2. 运行方式 1. 启动 `SpringBootDemoWebsocketSocketioApplication.java` 2. 使用不同的浏览器,访问 http://localhost:8080/demo/index.html ## 3. 运行效果 **浏览器1:** **浏览器2:** ## 4. 参考 ### 4.1. 后端 1. Netty-socketio 官方仓库:https://github.com/mrniko/netty-socketio 2. SpringBoot系列 - 集成SocketIO实时通信:https://www.xncoding.com/2017/07/16/spring/sb-socketio.html 3. Spring Boot 集成 socket.io 后端实现消息实时通信:http://alexpdh.com/2017/09/03/springboot-socketio/ 4. Spring Boot实战之netty-socketio实现简单聊天室:http://blog.csdn.net/sun_t89/article/details/52060946 ### 4.2. 前端 1. socket.io 官网:https://socket.io/ 2. axios.js 用法:https://github.com/axios/axios#example