vue 前端
https://www.cnblogs.com/xuwenjin/p/12664650.html
import {websocket_path,S_200,E_700} from '@/utils/constants'; import {getToken} from '@/utils/oauth'; import { Notification } from 'element-ui'; import store from '@/store'; import {genUUID} from '@/utils/stringUtils' let socket; const socketUrl = "/ws/msgWebSocket" function initWebSocket(){ if(typeof(WebSocket) === "undefined"){ Notification({ title: '系统信息', message: "您的浏览器不支持socket,请联系管理员", type: 'error' }) console.error("您的浏览器不支持socket,请联系管理员") return null; }else{ // 实例化socket socket = new WebSocket(websocket_path+socketUrl+"?token="+getToken()); // 监听socket连接 socket.onopen = handlerOpen; // 监听socket错误信息 socket.onerror = handlerError; // 监听socket消息 socket.onmessage = getMessage; return socket; } } let handlerOpen = function(){ } let handlerError = function(err){ console.error("websocket 连接错误",err); } /*接收消息*/ let getMessage = function(msg){ let msgObj = JSON.parse(msg.data); if(msgObj.code == E_700){ //token校验失败 socket.close(); console.error(msgObj) Notification({ title: '系统信息', message: "token验证失败,socket无法连接", type: 'error' }) return; } if(msgObj.code == S_200){ //socket连接成功 console.log("websocket 连接成功",msgObj) //判断是否是服务器推送的消息 if(JSON.stringify(msgObj.info) != "{}" ){ Notification({ title: '新消息', message: `<span>发送人: ${msgObj.info.senderUser.name_}</span><br/> <span>标题: ${msgObj.info.title_}</span><br/>`, type: 'success', dangerouslyUseHTMLString:true }) //触发消息标记 store.commit('commonData/SET_MSGUPDATEFLAG',genUUID()); } } return msg; } /*发送消息*/ let send = function(msg){ socket.send(msg) } /*关闭连接*/ let close = function () { socket.close(); } export default initWebSocket;
后台配置
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
import java.io.IOException; import java.util.Date; import java.util.List; import java.util.concurrent.CopyOnWriteArraySet; import javax.websocket.OnClose; import javax.websocket.OnError; import javax.websocket.OnMessage; import javax.websocket.OnOpen; import javax.websocket.Session; import javax.websocket.server.ServerEndpoint; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import com.alibaba.fastjson.JSONObject; import com.sun.star.uno.RuntimeException; import com.ylkj.common.constants.ErrorEnum; import com.ylkj.common.constants.SuccessEnum; import com.ylkj.common.oauth.jwt.JwtUtils; import com.ylkj.common.utils.DateUtils; import com.ylkj.common.utils.Result; import com.ylkj.common.utils.StringUtils; @Component @ServerEndpoint(value = "/ws/msgWebSocket") public class WebSocketServer { private static Logger log = LoggerFactory.getLogger(WebSocketServer.class); //用来存放每个客户端对应的WebSocketServer对象。 private static CopyOnWriteArraySet<WebSocketServer> WebSocketServers = new CopyOnWriteArraySet<WebSocketServer>(); //与某个客户端的连接会话,需要通过它来给客户端发送数据 private Session session; //每个连接客户的账号 private String account; @OnOpen public void onOpen(Session session) { this.session = session; WebSocketServers.add(this); String token= session.getQueryString().substring(session.getQueryString().indexOf("=")+1); //token为空 if(StringUtils.isEmpty(token)){ JSONObject param = new JSONObject(); param.put("msg", "对于半开放资源和受限资源,token不可为空"); try { this.session.getBasicRemote().sendText(Result.error(ErrorEnum.E_700,param).toJSONString()); } catch (IOException e) { throw new RuntimeException(e.getMessage()); } finally{ WebSocketServers.remove(this); } return; } //token校验失败 if(StringUtils.isEmpty(JwtUtils.getAccount(token))){ JSONObject param = new JSONObject(); param.put("msg", "token校验失败,已过期或伪造"); try { this.session.getBasicRemote().sendText(Result.error(ErrorEnum.E_700,param).toJSONString()); } catch (IOException e) { throw new RuntimeException(e.getMessage()); } finally{ WebSocketServers.remove(this); } return; } this.account = JwtUtils.getAccount(token); log.info("用户连接成功("+DateUtils.formatDate(new Date(), "yyyy-MM-dd HH:mm:ss")+"):"+JwtUtils.getAccount(token)); try { this.session.getBasicRemote().sendText(Result.success(SuccessEnum.S_200).toJSONString()); } catch (IOException e) { throw new RuntimeException(e.getMessage()); } } /** * @Title: onClose * @Description: 当客户端退出时触发,当服务端关闭时触发 * 客户端退出: 客户端游览器直接关闭,前端调用socket方法关闭 * @param session * void * @throws */ @OnClose public void onClose(Session session) { WebSocketServers.remove(this); log.info("用户断开连接("+DateUtils.formatDate(new Date(), "yyyy-MM-dd HH:mm:ss")+"):"+account); } @OnError public void onError(Session session, Throwable error) { log.info("连接错误"); } /** * @Title: onMessage * @Description: 接收客户端的消息 * @param message * void * @throws */ @OnMessage public void onMessage(String message) { log.info("["+this.account+"]发来消息("+DateUtils.formatDate(new Date(), "yyyy-MM-dd HH:mm:ss")+"):"+message); } /** * @Title: sendMessageAll * @Description: 服务器主动推送(所有在线用户都将收到) * @param msg * void * @throws */ public static synchronized void sendMessageAll(JSONObject msg) { for (WebSocketServer webSocketServer : WebSocketServers) { try { webSocketServer.session.getBasicRemote().sendText(Result.success(SuccessEnum.S_200, msg).toJSONString()); } catch (IOException e) { throw new RuntimeException(e.getMessage()); } } } /** * @Title: sendMessage * @Description: 服务器主动推送(指定账号可以收到) * @param msg * @param accounts * void * @throws */ public static synchronized void sendMessage(JSONObject msg,List<String> accounts) { //遍历所有用户 for (String account : accounts) { //遍历每一个当前session集合 for (WebSocketServer webSocketServer : WebSocketServers) { if(account.equals(webSocketServer.account)){ try { webSocketServer.session.getBasicRemote().sendText(Result.success(SuccessEnum.S_200, msg).toJSONString()); } catch (IOException e) { throw new RuntimeException(e.getMessage()); } } } } } }
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.socket.server.standard.ServerEndpointExporter; @Configuration public class WebSocketConfig { /** * ServerEndpointExporter 作用 * * 这个Bean会自动注册使用@ServerEndpoint注解声明的websocket endpoint * * @return */ @Bean public ServerEndpointExporter serverEndpointExporter() { return new ServerEndpointExporter(); } @Bean public MySpringConfigurator mySpringConfigurator() { return new MySpringConfigurator(); } }
import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanFactory; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import javax.websocket.server.ServerEndpointConfig; public class MySpringConfigurator extends ServerEndpointConfig.Configurator implements ApplicationContextAware { private static volatile BeanFactory context; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { MySpringConfigurator.context = applicationContext; } @Override public <T> T getEndpointInstance(Class<T> clazz) throws InstantiationException { return context.getBean(clazz); } }