1. 程式人生 > 其它 >websocket+sockjs公告通知【基於STOMP協議】

websocket+sockjs公告通知【基於STOMP協議】

技術標籤:javawebsocket公告通知

前言:
訊息推送技術,之前你可能用過 Ajax 輪詢。輪詢是在特定的的時間間隔(如每1秒),由瀏覽器對伺服器發出HTTP請求,然後由伺服器返回最新的資料給客戶端的瀏覽器。這種傳統的模式帶來很明顯的缺點,即瀏覽器需要不斷的向伺服器發出請求,然而HTTP請求可能包含較長的頭部,其中真正有效的資料可能只是很小的一部分,顯然這樣會浪費很多的頻寬等資源。有了長連線的websocket,能更好的節省伺服器資源和頻寬,並且能夠更實時地進行通訊。
WebSocket 是 HTML5 開始提供的一種在單個 TCP 連線上進行全雙工通訊的協議。
WebSocket 使得客戶端和伺服器之間的資料交換變得更加簡單,允許服務端主動向客戶端推送資料。在 WebSocket API 中,瀏覽器和伺服器只需要完成一次握手,兩者之間就直接可以建立永續性的連線,並進行雙向資料傳輸。

依賴

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

webSocket的配置檔案

@Configuration
/**
 * 註解開啟使用STOMP協議來傳輸基於代理(message broker)的訊息
 */
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

    /*@Resource
    private GetHeaderParamInterceptor getHeaderParamInterceptor;*/
    /**
     * 註冊stomp的端點
     */
    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        // 允許使用socketJs方式訪問,允許跨域
        // 在網頁上我們就可以通過這個連結
        // http://localhost:8080//ws/endpointChat
        // 來和伺服器的WebSocket連線
        registry.addEndpoint("/ws/endpointChat")
                .setAllowedOrigins("*")
                .withSockJS();
    }
    @Override
    /**
     * 配置訊息代理
     */
    public void configureMessageBroker(MessageBrokerRegistry registry) {
        //點對點queue,廣播式topic
        registry.enableSimpleBroker("/queue","/topic");
        //registry.setUserDestinationPrefix("/user");
    }

    /**
    * @Description  採用自定義攔截器   獲取connect時候傳遞的引數
    * @Author  mk
    * @Date   2020/12/17 9:47
    * @Param
    * @Return
    *
    */
   /* @Override
    public void configureClientInboundChannel(ChannelRegistration registration) {
        registration.interceptors(getHeaderParamInterceptor);
    }*/

}

websocket處理類controller

@Controller
public class WsController {
    @MessageMapping("/ws/nf")
    @SendTo("/topic/nf")
    public String handleNF() {
        return "公告通知";
    }
}

前端程式碼

const actions = {
  connect(context){
    context.state.stomp = Stomp.over(new SockJS("http://39.104.74.107:9090/ws/endpointChat"));
    context.state.stomp.connect({}, frame=> {
      
      //公告
      context.state.stomp.subscribe("/topic/nf", message=> {
        context.commit('toggleNFDot', true);
      });

    }, failedMsg=> {

    });
  }
}

const mutations = {
  toggleNFDot(state, newValue){
    state.nfDot = newValue;
  },
}

使用者傳送系統通知,在系統通知儲存到資料庫後,傳送websocket訊息

 sendNFMsg(){
        this.dialogLoading = true;
        var _this = this;
        SendMsg({message: this.message, title: this.title}).then(resp=> {
          _this.dialogLoading = false;
          if (resp && resp.status == 200) {
            var data = resp.data;
            _this.$message({type: "success", message: resp.data.msg});
            if (resp.data.code == 2000000) {
             _this.$store.state.stomp.send("/ws/nf", {}, '');
              _this.initSysMsgs();
              _this.cancelSend();
            }
          }
        })
      },

使用者進入home頁面,發起後端請求,看是否有未讀訊息,來控制鬧鐘小紅點的顯示

initSysMsgs(){
        var _this = this;
        getMsg().then(resp=> {
          _this.sysmsgs=resp.data.data;
          var isDot = false;
          resp.data.data.forEach(msg=> {
            if (msg.state == 0) {
              isDot = true;
            }
          })
          _this.$store.commit('toggleNFDot', isDot);
        })
      }

效果圖:
在這裡插入圖片描述

參考自“江南一點雨”大神的vhr專案