1. 程式人生 > >spring websocket 基於編碼的方式手動進行推送

spring websocket 基於編碼的方式手動進行推送

spring websocket基於註解的@SendTo和@SendToUser雖然方便,但是有侷限性,例如我這樣子的需求,我想手動的把訊息推送給某個人,或者特定一組人,怎麼辦,@SendTo只能推送給所有人,@SendToUser只能推送給請求訊息的那個人,這時,我們可以利用SimpMessagingTemplate這個類

SimpMessagingTemplate有倆個推送的方法

convertAndSend(destination, payload); //將訊息廣播到特定訂閱路徑中,類似@SendTo
convertAndSendToUser(user, destination, payload);//將訊息推送到固定的使用者訂閱路徑中,類似@SendToUser

實現需求之前,我們來關注下websocket的一個ApplicationListener事件,SessionConnectedEvent,你可以訂閱它,然後websocket通道連結成功之後,就廣播這個事件

public class MySessionConnectedEvent implements ApplicationListener<SessionConnectedEvent> {

    @Override
    public void onApplicationEvent(SessionConnectedEvent event) {


    }
}

註冊下這個接收事件到spring容器中,這裡通過java config的方式註冊

@Configuration
public class AppConfig {

    @Bean
    public MySessionConnectedEvent mySessionConnectedEvent(){

        return new MySessionConnectedEvent();
    }

}

通過這個事件,我們可以把使用者的登入授權資訊儲存起來,放到ServletContext中,以便於我們在推送訊息的時候,拿到使用者資訊,當然,這裡你也可以把使用者的登入授權資訊儲存到其他的快取策略中。

public class MySessionConnectedEvent
implements ApplicationListener<SessionConnectedEvent> {
@SuppressWarnings("unchecked") @Override public void onApplicationEvent(SessionConnectedEvent event) { StompHeaderAccessor headers = StompHeaderAccessor.wrap(event.getMessage()); //獲取訊息頭 String name = headers.getUser().getName(); //獲取賬號名 ServletContext sc = SpringBeanUtil.getServletContext(); //SpringBeanUtil的作用就是獲取ServletContext Object obj = sc.getAttribute("users"); Map<String, Principal> users = (Map<String, Principal>) (obj == null ? new HashMap<String,Principal>() : obj); users.put(name, headers.getUser()); sc.setAttribute("users", users); //將使用者資訊已map格式放存放起來 } }

有了使用者資訊就可以使用SimpMessagingTemplate進行特定使用者推送了

@Controller
@RequestMapping("/webSocket")
public class WebSocketController {

    @Autowired private SimpMessagingTemplate template; 

}

SimpMessagingTemplate在配置spring websocket的時候就已經放到spring容器中了

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketMessageBrokerConfig implements WebSocketMessageBrokerConfigurer {

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {

        //portfolio-stomp就是websocket的端點,客戶端需要註冊這個端點進行連結,withSockJS允許客戶端利用sockjs進行瀏覽器相容性處理
        registry.addEndpoint("/portfolio-stomp")/*.setAllowedOrigins("http://localhost:8080")*/.withSockJS(); 

    }

    @Override
    public void configureMessageBroker(MessageBrokerRegistry registry) {
        registry.enableSimpleBroker("/topic");               //設定伺服器廣播訊息的基礎路徑
        registry.setApplicationDestinationPrefixes("/app");  //設定客戶端訂閱訊息的基礎路徑
        registry.setPathMatcher(new AntPathMatcher("."));    //可以已“.”來分割路徑,看看類級別的@messageMapping和方法級別的@messageMapping
    }

    @Override
    public boolean configureMessageConverters(List<MessageConverter> messageConverters) {

        return true;
    }

    @Override
    public void configureWebSocketTransport(WebSocketTransportRegistration registry) {
        // TODO Auto-generated method stub
        registry.addDecoratorFactory(new MyWebSocketHandlerDecoratorFactory());
    }

    @Override
    public void configureClientInboundChannel(ChannelRegistration registration) {
         registration.setInterceptors(new MyChannelInterceptor());
    }

    @Override
    public void configureClientOutboundChannel(ChannelRegistration registration) {
        // TODO Auto-generated method stub

    }

    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
        // TODO Auto-generated method stub

    }

    @Override
    public void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> returnValueHandlers) {
        // TODO Auto-generated method stub

    }

}

所以我們這裡我們可以直接通過@Autowired注入進來。接下來我們就利用進行推送了

@Controller
@RequestMapping("/webSocket")
public class WebSocketController {

    @Autowired private SimpMessagingTemplate template; 

    @SuppressWarnings("unchecked")
    @RequestMapping("/httpSendMsg")
    public void httpSendMsg(String msg){

        ServletContext sc = SpringBeanUtil.getServletContext();
        Map<String,Principal> users = sc.getAttribute("users") == null ? null : (Map<String,Principal>)sc.getAttribute("users");//獲取放在servletContext中的使用者資訊

        Set<String> set = users.keySet();
        Iterator<String> iterator = set.iterator();
        while(iterator.hasNext()){ //遍歷根據使用者進行推送
            String key = iterator.next();
            this.template.convertAndSendToUser(key, "/topic/greetings", msg);
        }

    }
}

在這裡我們就成功的將訊息推送到固定使用者中了,這裡有個想法,我們可以把spring websocket作為訊息匯流排伺服器獨立出來,專案中,如果需要廣播或者訂閱訊息就直接在訊息匯流排中進行處理,只需要把推送路徑和訂閱路徑做好就可以了,這裡,跨域的操作,可以用setAllowedOrigins,下次可以看看

相關推薦

spring websocket 基於編碼方式手動進行

spring websocket基於註解的@SendTo和@SendToUser雖然方便,但是有侷限性,例如我這樣子的需求,我想手動的把訊息推送給某個人,或者特定一組人,怎麼辦,@SendTo只能推送給所有人,@SendToUser只能推送給請求訊息的那個人,這

Java Spring WebSocket實現後端訊息主動

這篇文章將介紹如何構建一個簡單的WebSocket訊息推送Demo使用eclipse建立maven專案後引入相關的依賴jar包,如下:<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://m

Spring mvc基於註解方式實現簡單HelloWorld

實現spring MVC有兩種不同的方式:基於XML配置檔案和基於註解。 上篇部落格介紹了基於XML配置檔案的方式,這裡我們使用基於註解的方式來實現。 下面只重點介紹與XML配置檔案方式不同的兩個地方:Spring配置檔案(springmvc-servlet.xml)

C/C++ 基於 websocket 的前臺及後臺實時

實現步驟如下: 1. 獲取 GoEasy appkey. 在 goeasy 官網上註冊一個賬號,並新建一個 app. APP 建立好後系統會為該 app 自動生成兩個 key, 一個既可以用來接收又可以用來推送 (supper key),另一個只可以用來接收(subscr

基於netty-socketio的web服務

hub href 相關 發生 推送消息 數據 特定 使用 github   在WEB項目中,服務器向WEB頁面推送消息是一種常見的業務需求。PC端的推送技術可以使用socket建立一個長連接來實現。傳統的web服務都是客戶端發出請求,服務端給出響應。但是現在直觀的要求是允許

Android 基於Netty的消息方案之概念和工作原理(二)

img b2c 決定 watermark net nios 通道 感覺 art 上一篇文章中我講述了關於消息推送的方案以及一個基於Netty實現的一個簡單的Hello World。為了更好的理解Hello World中的代碼,今天我來解說一下關於Netty中一些概念和工

v-charts 和 websocket實現數據展示動態

lob each sock sent visual 基於 例子 repr har v-charts https://v-charts.js.org/#/ ELEMENT力作: 在使用 echarts 生成圖表時,經常需要做繁瑣的數據類型轉化、修改復雜的配置項,v-

基於Netty的百萬級服務設計要點

1. 背景 1.1. 話題來源 最近很多從事移動網際網路和物聯網開發的同學給我發郵件或者微博私信我,諮詢推送服務相關的問題。問題五花八門,在幫助大家答疑解惑的過程中,我也對問題進行了總結,大概可以歸納為如下幾類: 1,Netty是否可以做推送伺服器? 2,如果使用Netty開發推送服務,一個伺服器

WebSocket 教程,關於伺服器實時

原文出處: http://www.ruanyifeng.com/blog/2017/05/websocket.html WebSocket 是一種網路通訊協議,很多高階功能都需要它。 本文介紹 WebSocket 協議的使用方法。 一、為什麼需要 WebSocket?

利用WebSocket和EventSource實現服務端

可能有很多的同學有用 setInterval 控制 ajax 不斷向服務端請求最新資料的經歷(輪詢)看下面的程式碼: setInterval(function() { $.get('/get/data-list', function(data, status) { conso

webSocket-簡單的服務端定時以及重連

本文章是對webSocket的學習,在使用webSocket進行客戶端-服務端的互動。 參考文章: Java基於Socket的簡單推送,在文章在服務端 輸入後回車 ,可進行對客戶端的資訊傳送,同時進行回饋。 以下為自行改進:服務端定時推送資訊到客戶端,可根據自行需要進行調整。

WebSocket和kafka實現資料實時到前端

一. 需求背景 最近新接觸一個需求,需要將kafka中的資料實時推送到前端展示。最開始想到的是前端輪詢介面資料,但是無法保證輪詢的頻率和消費的頻率完全一致,或造成資料缺失等問題。最終確定用利用WebSocket實現資料的實時推送。 二. websocket簡介 網上已經有好

如何使用極光,java服務端向鐳射伺服器進行

第一種:使用官方的sdk直接使用 /** * <pre>專案名稱:bsa-admin-api * 檔名稱:Test.java * 包名:com.bsa.api.jiguang * 建立日期:2018年12月10日下午2:30:19 * Copyright (c

Android訊息(二)--基於MQTT協議實現的功能

前段時間公司需要android端的手機群推功能,我們就通過MQTT來實現了該功能。 MQTT的官網如下 http://mqtt.org/ 關於系統的主要架構就不詳述了。這關係的到職業道德問題,在這裡

Mac下使用git對GitHub進行,拉取等操作

不經常使用的話就會生疏,就只能多做筆記,多分享。今天是0606,記錄一下基本操作。 第一: 下載並安裝git https://git-scm.com/downloads 第二:對git進行全域性或單個應用配置    2.1 全域性配置 git config --glob

(服務端)極光根據別名和分組名進行

1、別名推送 public static void sendPush(List<String> list, Map<String, String> map,String taskName) { JPushClient jpushCl

基於sse的訊息單向機制

     訊息推送現在基本上是web應用的標配,在做一個社交類網站時,本人一開始由於對這方面的技術不夠熟練,想採用最新的websocket技術,卻一直失敗,最終採用了最傳統的輪詢方式,十分浪費資源。今天看了spring boot 實戰這本書,裡面介紹了一種我之前從未了解過的

python3 三行程式碼基於HTTP2完美實現APNS【詳解】

    第一次做蘋果APNS(Apple Push Notification service)推送,關於APNS推送原理以及證書的獲取方式網上已經有許多資料,在此不做過多贅述,需要注意的是證書分為測試證書和正式證書兩種,建議直接用通用版的正式證書 大家可以參考網上的這篇部落格:點選這裡檢視

SpringBoot整合WebSocket基於STOMP協議】進行點對點[一對一]和廣播[一對多]實時,內附簡易聊天室demo

最近專案來了新需求,需要做一個實時推送的功能,伺服器主動推送訊息給客戶端,在網上經過一輪搜查之後,確定使用WebSocket來進行開發。以前經常聽說WebSocket的神奇之處,如今終於可以嘗試使用它了。1.淺談WebSocketWebSocket是在HTML5基礎上單個TC

SpringBoot整合WebSocket基於純H5】進行點對點[一對一]和廣播[一對多]實時

之前實現WebSocket基於STOMP的,覺得SpringBoot封裝的太高,不怎麼靈活,現在實現一個純H5的,也大概瞭解webSocket在內部是怎麼傳輸的。1.環境搭建因為在上一篇基於STOMP協議實現的WebSocket裡已經有大概介紹過Web的基本情況了,所以在這篇