1.简介

在工作遇到一个功能开发,应用场景是:后端(springboot项目)通过消息队列机制接收事件,并通过websocket实时推向前端(vue项目),从而实现前后端数据实时推送。

接下来介绍一下如何在前后端代码中实现websocket功能

2.后端

2.1 引入websocket jar包

在springboot项目的pom文件中加入websocket依赖,导入对应的jar包以及依赖

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
        </dependency>

2.2 添加WebSocketConfig配置类

使用@ServerEndpoint创立websocket endpoint。首先要注入ServerEndpointExporter,这个bean会自动注册使用了@ServerEndpoint注解声明的Websocket endpoint。要注意,如果使用独立的servlet容器,而不是直接使用springboot的内置容器,就不要注入ServerEndpointExporter,因为它将由容器自己提供和管理

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;

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

2.3 WebSocketUtils具体实现类

WebSocketUtils类是websocket的具体实现类,直接上代码:

package com.example.demo.websocket;

import org.springframework.stereotype.Component;
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.ArrayList;

@ServerEndpoint("/websocket")
@Component
public class WebSocketUtils {
    private Session session;
    private static ArrayList<WebSocketUtils> webSocketUtils = new ArrayList<>();

    @OnMessage
    public void onMessage(String message,Session session){
        System.out.println("Received:" + message);
    }

    @OnOpen
    public void onOpen(Session session){
        webSocketUtils.add(this);
        this.session = session;
        System.out.println("client connected");
    }

    @OnClose
    public void onClose(){
        webSocketUtils.remove(this);
        System.out.println("Client close");
    }

    @OnError
    public void onError(Throwable t){
        System.out.println("no client");
    }

    public static void sendMessage(String eventMessage){
        for (WebSocketUtils item:webSocketUtils){
            try {
                item.session.getBasicRemote().sendText(eventMessage);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

2.4 消息队列消费者函数中推送数据

onMessage函数是消费者类中的事件处理函数,在该函数中通过websocketUtils工具类的sendMessage方法发送事件信息。

public void onMessage(Message message) {
        String receiveMessage;
        try {
            receiveMessage = new String(message.getBody(), "utf-8");
        } catch (Exception e) {
            e.printStackTrace();
            return;
        }
        //解析数据
        JSONObject jsonObject = JSONObject.fromObject(receiveMessage);
        //通过websocket发送数据
  		webSocketUtils.sendMessage(jsonObject.toString());
}

3.前端代码

前端vue页面需要通过websocket从后端接收消息的代码实现如下:

<template>
  <el-row>
    <el-col class="col" v-for="(k, index) in faceArray" :key=index>
      <el-card class="box-card">
          <span">
            <img :src="k.smallpicURL" class="card-img"/>
          </span>
        <div class="card_text">
          <p>时间:{{k.pictime}}</p>
          <p>监控点:{{k.picdestination}}</p>
        </div>
      </el-card>
    </el-col>
  </el-row>
</template>

<script>
export default {
  data () {
    return {
      websock: null,
      faceArray: [],
      pictime: '',
      picdest: ''
    }
  },
  methods: {
    threadPoxi () {
      const agentData = 'mymessage'
      if (this.websock.readyState === this.websock.OPEN) {
        this.websocketsend(agentData)
      } else if (this.websock.readyState === this.websock.CONNECTING) {
        let that = this
        setTimeout(function () {
          that.websocketsend(agentData)
        }, 300)
      } else {
        this.initWebSocket()
        let that = this
        setTimeout(function () {
          that.websocketsend(agentData)
        }, 500)
      }
    },
    initWebSocket () {
      const wsuri = 'ws://localhost:8090/websocket'
      this.websock = new WebSocket(wsuri)
      this.websock.onmessage = this.websocketonmessage
      this.websock.onclose = this.websocketclose
    },
    websocketonmessage (e) {
      console.log(e.data)
      if (this.faceArray.length > 20) {
        this.faceArray.shift()
      }
      this.faceArray.push(JSON.parse(e.data))
      console.log(this.faceArray)
    },
    websocketsend (agentData) {
      this.websock.send(agentData)
    },
    websocketclose (e) {
      console.log('connection closed (' + e.code + ')')
    },
    toFaceSearch: function (realfaceImg) {
      this.$router.push({
        path: '/facesearch',
        query: {
          faceImg: realfaceImg
        }
      })
    }
  },
  created () {
    this.initWebSocket()
  }
}
</script>

<!-- Add 'scoped' attribute to limit CSS to this component only -->
<style scoped>

  .col {
    width: 250px;
  }
</style>

其中initWebSocket()接口中wsuri则指定了后端websocket的请求地址,必须保证正确。
当后端项目运行起来后,每当消息队列接收到事件,那么消费者程序就会去处理事件,并通过websocket发送数据,而前端运行之后就可以通过websocketonmessage()接口获取后端发送的数据

4.总结

本文简单总结了一下前后端分离项目(springboot项目+vue项目)下通过websocket实现事件消息通信的简单实现。关于websocket的知识了解的有限,后续需要继续学习。

Logo

前往低代码交流专区

更多推荐