springboot vue webSocket 集成

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);
    }
}