springboot websocket的封裝js ,STOMP使用


參考地址:https://blog.csdn.net/m0_37542889/article/details/83750665

1、啟用STOMP功能

    STOMP 的消息根據前綴的不同分為三種。如下,以 /app 開頭的消息都會被路由到帶有@MessageMapping 或 @SubscribeMapping 注解的方法中;以/topic 或 /queue 開頭的消息都會發送到STOMP代理中,根據你所選擇的STOMP代理不同,目的地的可選前綴也會有所限制;以/user開頭的消息會將消息重路由到某個用戶獨有的目的地上。

 View Code

2、處理來自客戶端的STOMP消息

    服務端處理客戶端發來的STOMP消息,主要用的是 @MessageMapping 注解。如下:

 

  @MessageMapping("/marco")
  @SendTo("/topic/marco")
  public Shout stompHandle(Shout shout){
      LOGGER.info("接收到消息:" + shout.getMessage());
      Shout s = new Shout();
      s.setMessage("Polo!");
      return s;
  }

 

    2.1、@MessageMapping 指定目的地是“/app/marco”(“/app”前綴是隱含的,因為我們將其配置為應用的目的地前綴)。

    2.2、方法接收一個Shout參數,因為Spring的某一個消息轉換器會將STOMP消息的負載轉換為Shout對象。Spring 4.0提供了幾個消息轉換器,作為其消息API的一部分:

    2.3、尤其注意,這個處理器方法有一個返回值,這個返回值並不是返回給客戶端的,而是轉發給消息代理的,如果客戶端想要這個返回值的話,只能從消息代理訂閱。@SendTo 注解重寫了消息代理的目的地,如果不指定@SendTo,幀所發往的目的地會與觸發處理器方法的目的地相同,只不過會添加上“/topic”前綴。

    2.4、如果客戶端就是想要服務端直接返回消息呢?聽起來不就是HTTP做的事情!即使這樣,STOMP 仍然為這種一次性的響應提供了支持,用的是@SubscribeMapping注解,與HTTP不同的是,這種請求-響應模式是異步的...

 

   @SubscribeMapping("/getShout")
   public Shout getShout(){
       Shout shout = new Shout();
       shout.setMessage("Hello STOMP");
       return shout;
   }

 

3、發送消息到客戶端

3.1 在處理消息之后發送消息

    正如前面看到的那樣,使用 @MessageMapping 或者 @SubscribeMapping 注解可以處理客戶端發送過來的消息,並選擇方法是否有返回值。

    如果 @MessageMapping 注解的控制器方法有返回值的話,返回值會被發送到消息代理,只不過會添加上"/topic"前綴。可以使用@SendTo 重寫消息目的地;

    如果 @SubscribeMapping 注解的控制器方法有返回值的話,返回值會直接發送到客戶端,不經過代理。如果加上@SendTo 注解的話,則要經過消息代理。

3.2 在應用的任意地方發送消息

    spring-websocket 定義了一個 SimpMessageSendingOperations 接口(或者使用SimpMessagingTemplate ),可以實現自由的向任意目的地發送消息,並且訂閱此目的地的所有用戶都能收到消息。

 

  @Autowired
  private SimpMessageSendingOperations simpMessageSendingOperations;


  /**
  * 廣播消息,不指定用戶,所有訂閱此的用戶都能收到消息
  * @param shout
  */
  @MessageMapping("/broadcastShout")
  public void broadcast(Shout shout) {
      simpMessageSendingOperations.convertAndSend("/topic/shouts", shout);
  }

 

3.3 為指定用戶發送消息

    3.2介紹了如何廣播消息,訂閱目的地的所有用戶都能收到消息。如果消息只想發送給特定的用戶呢?spring-websocket 介紹了兩種方式來實現這種功能,一種是 基於@SendToUser注解和Principal參數,一種是SimpMessageSendingOperations 接口的convertAndSendToUser方法。

  • 基於@SendToUser注解和Principal參數

    @SendToUser 表示要將消息發送給指定的用戶,會自動在消息目的地前補上"/user"前綴。如下,最后消息會被發布在  /user/queue/notifications-username。但是問題來了,這個username是怎么來的呢?就是通過 principal 參數來獲得的。那么,principal 參數又是怎么來的呢?需要在spring-websocket 的配置類中重寫 configureClientInboundChannel 方法,添加上用戶的認證。

 spring-websocket 用戶認證

 

  @MessageMapping("/shout")
  @SendToUser("/queue/notifications")
  public Shout userStomp(Principal principal, Shout shout) {
        String name = principal.getName();
        String message = shout.getMessage();
        LOGGER.info("認證的名字是:{},收到的消息是:{}", name, message);
        return shout;
  }

 

  • convertAndSendToUser方法

    除了convertAndSend()以外,SimpMessageSendingOperations 還提供了convertAndSendToUser()方法。按照名字就可以判斷出來,convertAndSendToUser()方法能夠讓我們給特定用戶發送消息。

 

    @MessageMapping("/singleShout")
    public void singleUser(Shout shout, StompHeaderAccessor stompHeaderAccessor) {
        String message = shout.getMessage();
        LOGGER.info("接收到消息:" + message);
        Principal user = stompHeaderAccessor.getUser();
        simpMessageSendingOperations.convertAndSendToUser(user.getName(), "/queue/shouts", shout);
    }

 

    如上,這里雖然我還是用了認證的信息得到用戶名。但是,其實大可不必這樣,因為 convertAndSendToUser 方法可以指定要發送給哪個用戶。也就是說,完全可以把用戶名的當作一個參數傳遞給控制器方法,從而繞過身份認證!convertAndSendToUser 方法最終會把消息發送到 /user/sername/queue/shouts 目的地上。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM