SpringBoot整合WebSocket的实现方式

2022-08-24 11:46:34

前言

以下代码,复制粘贴

实现

pom.xml中加入依赖

<!-- WebSocket依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId></dependency>

java实现类

在这里插入图片描述
配置类

packagecom.modules.websocket;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.web.socket.server.standard.ServerEndpointExporter;@ConfigurationpublicclassWebSocketConfig{/**
     * ServerEndpointExporter 作用
     *
     * 这个Bean会自动注册使用@ServerEndpoint注解声明的websocket endpoint
     *
     * @return
     */@BeanpublicServerEndpointExporterserverEndpointExporter(){returnnewServerEndpointExporter();}}

具体实现类

packagecom.modules.websocket;importjava.io.IOException;importjava.util.ArrayList;importjava.util.List;importjava.util.Map;importjava.util.concurrent.ConcurrentHashMap;importjavax.websocket.OnClose;importjavax.websocket.OnError;importjavax.websocket.OnMessage;importjavax.websocket.OnOpen;importjavax.websocket.Session;importjavax.websocket.server.PathParam;importjavax.websocket.server.ServerEndpoint;importorg.springframework.stereotype.Component;importcn.hutool.json.JSONObject;@Component@ServerEndpoint("/webSocket/{type}/{uuid}")publicclassWebSocket{privatestaticint onlineCount=0;// 统计在线人数的privatestaticMap<String,WebSocket> loginMap=newConcurrentHashMap<String,WebSocket>();// 饿汉式privatestaticList<Map<String,WebSocket>> clients=null;// 懒汉式publicSession session;publicString userName;publicString uuid;publicstaticlong timeCount=0;/**
    * 打开连接
    * @param type
    * @param session
    * @throws IOException
    */@OnOpenpublicvoidonOpen(@PathParam("type")String type,@PathParam("uuid")String uuid,Session session)throwsIOException{this.userName= type;this.uuid= uuid;this.session= session;if(type!=null){if(type.equals("login")){// 登录
        		 loginMap.put(uuid,this);}else{if(clients==null){// 大数据synchronized(WebSocket.class){if(clients==null){
      						clients=newArrayList<Map<String,WebSocket>>();}}}Map<String,WebSocket> clien=newConcurrentHashMap<String,WebSocket>(); 
  	             clien.put(uuid,this);
  	             clients.add(clien);}}//addOnlineCount();//本来用统计在线人数的}/**
    * 删除
    * @throws IOException
    */@OnClosepublicvoidonClose()throwsIOException{if(userName!=null&& userName.equals("login")){// 登录if(loginMap!=null){
        		loginMap.remove(uuid);}}else{if(clients!=null){for(int i=0; i< clients.size(); i++){// 大数据Map<String,WebSocket> clien= clients.get(i);for(WebSocket item: clien.values()){if(item.session.equals(session))
                			clients.remove(i);}}}}//subOnlineCount(); //本来用统计在线人数的}/**
     * 错误信息
     */@OnErrorpublicvoidonError(Session session,Throwable error){
         error.printStackTrace();}/**
     * 接收数据
     * @throws IOException
     */@OnMessagepublicstaticvoidonMessage(String message)throwsIOException{JSONObject jsonTo=newJSONObject(message);String mes=(String) jsonTo.get("message");String type=(String) jsonTo.get("type");Stringto=(String) jsonTo.get("To");if(type!=null){if(type.equals("login")){// 登录sendMessageLoginTo(mes,to);}elseif(type.equals("data")){// 大数据sendMessageAll(mes);}}}/**
	  * 发给指定-登录
	  * @param message
	  * @param To
	  * @throws IOException
	*/publicstaticvoidsendMessageLoginTo(String message,StringTo)throwsIOException{//session.getBasicRemote().sendText(message); // 同步//session.getAsyncRemote().sendText(message); // 异步if(loginMap!=null){for(WebSocket item: loginMap.values()){if(item.uuid.equals(To))
    				item.session.getAsyncRemote().sendText(message);}}}/**
    * 发给指定-大数据2
    * @param message
    * @throws IOException
    */publicstaticvoidsendMessageTo(String message,Stringto)throwsIOException{if(clients!=null){// 大数据for(int i=0; i< clients.size(); i++){Map<String,WebSocket> clien= clients.get(i);for(WebSocket item: clien.values()){if(item.uuid.equals(to))
    					item.session.getAsyncRemote().sendText(message);}}}}/**
     * 发给全部 -大数据
     * @param message
     * @throws IOException
     */publicstaticvoidsendMessageAll(String message)throwsIOException{for(int i=0; i< clients.size(); i++){Map<String,WebSocket> clien= clients.get(i);for(WebSocket item: clien.values()){ 
                item.session.getAsyncRemote().sendText(message);}}}publicstaticsynchronizedintgetOnlineCount(){return onlineCount;}publicstaticsynchronizedvoidaddOnlineCount(){WebSocket.onlineCount++;}publicstaticsynchronizedvoidsubOnlineCount(){WebSocket.onlineCount--;}publicstaticsynchronizedMap<String,WebSocket>getLoginMap(){return loginMap;}publicstaticsynchronizedList<Map<String,WebSocket>>getClients(){return clients;}}

JS连接实现

var websocket=null;var host= document.location.host;var judgeTemp=0;functiongetUuid(){return(S4()+S4()+"-"+S4()+"-"+S4()+"-"+S4()+"-"+S4()+S4()+S4());}functionS4(){return(((1+Math.random())*0x10000)|0).toString(16).substring(1);}// 创建连接functioncreateWebSorket(){try{//判断当前浏览器是否支持WebSocketif('WebSocket'in window){
			websocket=newWebSocket('ws://'+ host+'/Layui-SB/webSocket/data/'+temp_uuid);initEventHandle();}else{alert('当前浏览器无法使用');}}catch(err){
		loadTemp++;if(loadTemp==5){// 重连5 次不行就重新刷新浏览器
			window.location.reload();}
		console.log(err)
		console.log(err.message);setTimeout(function(){createWebSorket();// 由于网络问题可能无法连接(两秒后重新连接)},2000)}}functioninitEventHandle(){//连接发生错误的回调方法
	websocket.onerror=function(){
		judgeTemp=1;
		console.log('连接失败');};//连接成功建立的回调方法
	websocket.onopen=function(){
		console.log('连接成功');}//接收到消息的回调方法
	websocket.onmessage=function(event){//console.log('回馈消息');setMessageInnerHTML(event.data);}//连接关闭的回调方法
	websocket.onclose=function(){
		console.log('连接关闭');if(judgeTemp!=1){createWebSorket();}}//监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
	window.onbeforeunload=function(){
		judgeTemp=1;closeWebSocket();}}//关闭WebSocket连接functioncloseWebSocket(){
	websocket.close();}// 初始化UUID连接var temp_uuid=getUuid();createWebSorket();/**-----------------------------------消息处理---------------------------------------
 * 接收消息
 */functionsetMessageInnerHTML(data){}

发布后Nginx代理报错问题解决:

websocket连接错误Error during WebSocket handshake Unexpected response code 404

 location/ProjectName{
       proxy_pass http://temp_project;
       proxy_redirectdefault;
       proxy_connect_timeout5s;   #默认值60s, nginx连接到后端服务器的连接超时时间
       proxy_set_headerHost $host:80;
       proxy_set_headerX-Forward-For $remote_addr;
       proxy_http_version1.1;
       proxy_set_headerUpgrade $http_upgrade;
       proxy_set_headerConnection"upgrade";
       proxy_read_timeout3600s;}

主要关键行,使用如下的即可

	   proxy_http_version1.1;
       proxy_set_headerUpgrade $http_upgrade;
       proxy_set_headerConnection"upgrade";
       proxy_read_timeout3600s;
  • 作者:慕云枫
  • 原文链接:https://blog.csdn.net/weixin_43992507/article/details/125625680
    更新时间:2022-08-24 11:46:34