前言
以下代码,复制粘贴
实现
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;