spring集成webscoket

1.后端代码

消息编码类

public class EquipEncoder implements javax.websocket.Encoder.Text<Object> {

    @Override
    public void destroy() {
        // TODO Auto-generated method stub

    }

    @Override
    public void init(EndpointConfig arg0) {
        // TODO Auto-generated method stub

    }



    @Override
    public String encode(Object o) throws EncodeException {
        return JSON.toJSONString(o);
    }
}

消息解码类

public class EquipEncoder implements javax.websocket.Encoder.Text<Object> {

    @Override
    public void destroy() {
        // TODO Auto-generated method stub

    }

    @Override
    public void init(EndpointConfig arg0) {
        // TODO Auto-generated method stub

    }



    @Override
    public String encode(Object o) throws EncodeException {
        return JSON.toJSONString(o);
    }
}

上面两个类测试下来好像没什么用处
websocket配置类

@Component
public class WebSocketConfig {
    @Bean
    public ServerEndpointExporter serverEndpointExporter(){
        return new ServerEndpointExporter();
    }
}

核心代码,onMessage接收前端发来的消息,sendToOne发送消息给前端,wid为前后端websocket连接的唯一标识(每个连接标识都必须唯一,可采取前端生成时间戳的方式,相同的会被后面的顶掉)

@Slf4j
@Component
@ServerEndpoint(value = "/websocket/{wid}", encoders = {EquipEncoder.class}, decoders = {EquipDecoder.class})
public class WebSocket {


    private Session session;

    /**
     * 用来记录当前在线连接数
     */
    private static AtomicInteger onlineCnt = new AtomicInteger();

    //定义 ConcurrentHashMap 存储用户编号和用户会话
    private static ConcurrentHashMap<String, Session> sessionPools = new ConcurrentHashMap<String, Session>();


    /**
     * 连接建立成功调用的方法
     *
     * @param session
     */
    @OnOpen
    public void onOpen(Session session, @PathParam(value = "wid") String wid) {
        log.info("有新的连接,wid={},session:{}", wid, session);
        if (sessionPools.containsKey(wid)) {
            sessionPools.remove(wid);
            sessionPools.put(wid, session);
        } else {
            sessionPools.put(wid, session);
            addOnlineCount();
        }
        log.info("总连接数:{}", onlineCnt);
    }

    /**
     * 连接断开调用的方法
     */
    @OnClose
    public void onClose(@PathParam(value = "wid") String wid) {
        if (sessionPools.containsKey(wid)) {
            sessionPools.remove(wid);
            subOnlineCount();
        }
        log.info("有新的断开:{}", wid);
        log.info("总连接数:{}", onlineCnt);
    }


    /**
     * 收到客户端消息后调用的方法
     *
     * @param message
     * @param wid
     */
    @OnMessage
    public void onMessage(String message, @PathParam(value = "wid") String wid) {
        log.info("收到客户端={},消息:{}", wid, message);
        JSONObject jsonObject = JSONObject.parseObject(message);
        //如果有flag说明是心跳检测机制
        if (jsonObject.containsKey("heart")) {
            sendToOne(message, wid);
        } else {//没有说明是前端给后端发消息
            System.out.println("收到前端发送过来的消息:" + message);
        }
    }

    /**
     * 发送字符串
     *
     * @param message
     */
    public void sendToOne(String message, @PathParam(value = "wid") String wid) {
        Session session = sessionPools.get(wid);
        if (StringUtils.isNotNull(session)) {
            try {
                session.getBasicRemote().sendText(message);
                log.info("message:{},wid:{}", message, wid);
            } catch (IOException e) {
                log.error("sendToOne error,wid:{},message:{}", wid, message, e);
            }
        }
    }

    /**
     * 全部发送
     *
     * @param message
     */
    public void sendAll(String message) {
        for (Session session : sessionPools.values()) {
            try {
                sendMessage(session, message);
                log.info("session:{},message:{}", session, message);
            } catch (Exception e) {
                log.error("sendAll error");
                continue;
            }
        }
    }

    /**
     * 发送消息方法
     *
     * @param session 客户端与socket建立的会话
     * @param message 消息
     * @throws IOException
     */
    public void sendMessage(Session session, String message) throws IOException {
        if (StringUtils.isNotNull(session)) {
            session.getBasicRemote().sendText(message);
        }
    }


    /**
     * 发送对象
     *
     * @param obj
     */
    public void send(Object obj, @PathParam(value = "wid") String wid) {
        Session session = sessionPools.get(wid);
        if (StringUtils.isNotNull(session)) {
            try {
                session.getBasicRemote().sendObject(obj);
            } catch (IOException e) {
                log.error("sendToOne error,wid:{},message:{}", wid, obj.toString(), e);
            } catch (EncodeException e) {
                log.error("sendToOne error,wid:{},message:{}", wid, obj.toString(), e);
            }

        }

    }

    /**
     * 增加在线数量
     */
    private static void addOnlineCount() {
        onlineCnt.incrementAndGet();
    }

    /**
     * 减少在线数量
     */
    private static void subOnlineCount() {
        onlineCnt.decrementAndGet();
    }
}

测试类

@Slf4j
@Api(tags = "websocket相关")
@RestController
@RequestMapping("/manage/websocket")
public class WebsocketTestController {

    @Autowired
    private WebSocket webSocket;

    @ApiOperation(value = "发送给指定连接", notes = "发送给指定连接")
    @PostMapping("/sendToOne/{wid}")
    public void sendToOne(@RequestBody JSONObject message, @PathVariable(value = "wid") String wid) {
        webSocket.sendToOne(message.toString(), wid);
    }
}

2.前端代码

<template>
  <div class="login">
    {{ value }}
  </div>
</template>

<script>
const heartCheck = {
  timeout: 60 * 1000,
  timer: null,
  serverTimer: null,
  reset() {
    this.timer && clearTimeout(this.timer);
    this.serverTimer && clearTimeout(this.serverTimer);
  },
  start(ws) {
    this.reset();
    this.timer = setTimeout(() => {
      // onmessage拿到返回的心跳就说明连接正常
      ws.send(JSON.stringify({ heart: 1 }));
      this.serverTimer = setTimeout(() => {
        // 如果超过一定时间还没响应(响应后触发重置),说明后端断开了
        ws.close();
      }, this.timeout);
    }, this.timeout);
  },
};
export default {
  name: "Login",
  data() {
    return {
      value: null,
    };
  },

  created() {
    this.initWebSocket();
  },
  methods: {
    //******************websocket相关*****************************//

    reconnect() {
      if (this.lockReconnect || this.maxReconnect <= 0) {
        return;
      }
      setTimeout(() => {
        // this.maxReconnect-- // 不做限制 连不上一直重连
        console.log("首页ws尝试重连");
        this.initWebSocket();
      }, 15 * 1000);
    },
    initWebSocket() {
      try {
        if ("WebSocket" in window) {
          let SESSION_FLAG = "currentTimestamp";
          let currentTimestamp = this.$cache.session.get(SESSION_FLAG);
          if (!currentTimestamp) {
            //
            this.$cache.session.set(SESSION_FLAG, new Date().getTime());
            currentTimestamp = sessionStorage.getItem(SESSION_FLAG);
            console.log(
              "===初次登陆为ws创建全局事件戳,用于当前ws===",
              currentTimestamp
            );
          }
          var wsUrl =
            "ws://localhost:8080/websocket/wjAlarm123" + currentTimestamp;
          console.log("wsUrl==>" + wsUrl);
          this.socket = new WebSocket(wsUrl);
        } else {
          console.log("您的浏览器不支持websocket");
        }
        this.socket.onopen = this.websocketonopen;
        this.socket.onerror = this.websocketonerror;
        this.socket.onmessage = this.websocketonmessage;
        this.socket.onclose = this.websocketclose;
      } catch (e) {
        this.reconnect();
        console.log("首页WebSocket发生错误", e);
      }
    },
    websocketonopen() {
      console.log("首页WebSocket连接成功", this.socket.readyState);
      heartCheck.start(this.socket);
      // this.socket.send('发送数据')
      this.websocketsend();
    },
    websocketonerror(e) {
      console.log("首页WebSocket连接发生错误", e);
      // this.reconnect()
    },
    //方法接收后台发过来的数据
    websocketonmessage(e) {
      var msgData = JSON.parse(e.data);
      if (msgData) {//msgData不为null的意思
        // 消息获取成功,重置心跳
        heartCheck.start(this.socket);
      }
      console.log("接收到消息");
      //如果不是心跳检测包
      if (!msgData.heart) {
        console.log("websocketonmessage==msgData==", msgData);
        this.value = msgData;
      }
    },
    websocketclose(e) {
      console.log("首页connection closed (" + e.code + ")");
      this.reconnect();
    },
    //前台给后台发送数据
    websocketsend() {
      let data = { heart: 1 };
      this.socket.send(JSON.stringify(data));
    },
    destroyed() {
      heartCheck.reset();
      this.socket.close();
    },
  },
};
</script>

<style rel="stylesheet/scss" lang="scss">
</style>

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值