Eclipse 搭建一个简单的SpringBoot+WebSocket环境
WebSocket是一种在单个TCP连接上进行全双工通信的协议。
WebSocket通信协议于2011年被IETF定为标准RFC 6455,并由RFC7936补充规范。
WebSocket API也被W3C定为标准。
WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。
在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。
使用SpringBoot+WebSocket搭建一个多人聊天系统
1、新建Spring Starter Project
2、添加对WebSocket的支持
注入ServerEndpointExporter,这个bean会自动注册使用了@ServerEndpoint注解声明的Websocket endpoint。
1 package com.zzq.config; 2 3 import org.springframework.context.annotation.Bean; 4 import org.springframework.context.annotation.Configuration; 5 import org.springframework.web.socket.server.standard.ServerEndpointExporter; 6 7 /** 8 * 9 * @author ZZQ-PC 10 * 11 */ 12 @Configuration 13 public class AppConfiguration { 14 15 @Bean 16 public ServerEndpointExporter serverEndpointExporter(){ 17 return new ServerEndpointExporter(); 18 } 19 20 }
3、创建WebSocket的实现类
@ServerEndpoint("/webSocket/{page}")中的值就是需要访问的地址,和Controller中的@RequestMapping有点类似。然后实现@OnOpen(打开连接),@OnClose(关闭连接),@onMessage(收到消息),@Error(触发异常)。
1 package com.zzq.config; 2 3 import java.io.IOException; 4 import java.util.Map; 5 import java.util.Set; 6 import java.util.concurrent.ConcurrentHashMap; 7 import java.util.concurrent.CopyOnWriteArraySet; 8 import java.util.concurrent.atomic.AtomicInteger; 9 10 import javax.websocket.OnClose; 11 import javax.websocket.OnError; 12 import javax.websocket.OnMessage; 13 import javax.websocket.OnOpen; 14 import javax.websocket.Session; 15 import javax.websocket.server.PathParam; 16 import javax.websocket.server.ServerEndpoint; 17 18 import org.slf4j.Logger; 19 import org.slf4j.LoggerFactory; 20 import org.springframework.stereotype.Component; 21 22 /** 23 * 24 * @author ZZQ-PC 25 * 26 */ 27 @Component 28 @ServerEndpoint("/webSocket/{page}") 29 public class WebSocket { 30 private Logger log = LoggerFactory.getLogger(this.getClass()); 31 32 /** 33 * 用来记录房间的人数 34 */ 35 private static AtomicInteger onlinePersons = new AtomicInteger(0); 36 37 /** 38 * 用来记录房间及人数 39 */ 40 private static Map<String,Set> roomMap = new ConcurrentHashMap(8); 41 42 @OnOpen 43 public void open(@PathParam("page") String page, Session session) throws IOException { 44 Set set = roomMap.get(page); 45 // 如果是新的房间,则创建一个映射,如果房间已存在,则把用户放进去 46 if(set == null){ 47 set = new CopyOnWriteArraySet(); 48 set.add(session); 49 roomMap.put(page,set); 50 }else{ 51 set.add(session); 52 } 53 // 房间人数+1 54 onlinePersons.incrementAndGet(); 55 log.info("新用户{}进入聊天,房间人数:{}",session.getId(),onlinePersons); 56 } 57 58 @OnClose 59 public void close(@PathParam("page") String page, Session session){ 60 // 如果某个用户离开了,就移除相应的信息 61 if(roomMap.containsKey(page)){ 62 roomMap.get(page).remove(session); 63 } 64 // 房间人数-1 65 onlinePersons.decrementAndGet(); 66 log.info("用户{}退出聊天,房间人数:{}",session.getId(),onlinePersons); 67 } 68 69 @OnMessage 70 public void reveiveMessage(@PathParam("page") String page, Session session,String message) throws IOException { 71 log.info("接受到用户{}的数据:{}",session.getId(),message); 72 // 拼接一下用户信息 73 String msg = session.getId()+" : "+ message; 74 Set<Session> sessions = roomMap.get(page); 75 // 给房间内所有用户推送信息 76 for(Session s : sessions){ 77 s.getBasicRemote().sendText(msg); 78 } 79 } 80 81 @OnError 82 public void error(Throwable throwable){ 83 try { 84 throw throwable; 85 } catch (Throwable e) { 86 log.error("未知错误"); 87 } 88 } 89 }
4、在src/main/resources/static文件夹下新建index.html。
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8"></meta> 5 <title>springboot项目WebSocket测试demo</title> 6 </head> 7 <body> 8 <h3>springboot项目websocket测试demo</h3> 9 <h4>测试说明</h4> 10 <h5>文本框中数据数据,点击‘发送测试’,文本框中的数据会发送到后台websocket,后台接受到之后,会再推送数据到前端,展示在下方;点击关闭连接,可以关闭该websocket;可以跟踪代码,了解具体的流程;代码上有详细注解</h5> 11 <br /> 12 <input id="text" type="text" /> 13 <button onclick="send()">发送测试</button> 14 <hr /> 15 <button onclick="clos()">关闭连接</button> 16 <hr /> 17 <div id="message"></div> 18 <script> 19 var websocket = null; 20 if('WebSocket' in window){ 21 websocket = new WebSocket("ws://127.0.0.1:8080/webSocket/1"); 22 }else{ 23 alert("您的浏览器不支持websocket"); 24 } 25 websocket.onerror = function(){ 26 setMessageInHtml("send error!"); 27 } 28 websocket.onopen = function(){ 29 setMessageInHtml("连接成功!") 30 setTimeout(function(){setMessageInHtml("欢迎来到这里!") 31 },2000) 32 } 33 websocket.onmessage = e => setMessageInHtml(e.data) 34 websocket.onclose = function(){ 35 setMessageInHtml("连接断开!") 36 } 37 window.onbeforeunload = function(){ 38 clos(); 39 } 40 function setMessageInHtml(message){ 41 document.getElementById('message').innerHTML += message+"</br>"; 42 } 43 function clos(){ 44 websocket.close(3000,"强制关闭"); 45 } 46 function send(){ 47 var msg = document.getElementById('text').value; 48 websocket.send(msg); 49 } 50 </script> 51 </body> 52 </html>
5、启动Spring boot工程
至此,一个简单的SpringBoot+WebSocket项目搭建完毕。