最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot集成WebSocket長連接實際應用詳解

 更新時間:2020年06月11日 09:59:54   作者:有追求的程序狗  
這篇文章主要介紹了SpringBoot集成WebSocket長連接實際應用詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

前言:

一、WebSocket之初出茅驢

官方定義:WebSocket是一種在單個TCP連接上進行全雙工通信的協(xié)議。WebSocket使得客戶端和服務器之間的數(shù)據(jù)交換變得更加簡單,允許服務端主動向客戶端推送數(shù)據(jù)。在WebSocket API中,瀏覽器和服務器只需要完成一次握手,兩者之間就直接可以創(chuàng)建持久性的連接,并進行雙向數(shù)據(jù)傳輸。是真正的雙向平等對話,屬于服務器推送技術的一種。

太官方啦,還是博主過來翻譯一下吧 :WebSocket技術只需要service和client建立一次連接,就能實現(xiàn)服務器和客戶端雙方相互頻繁的發(fā)送請求和通信?。ê唵渭哟直┑姆g有木有,哈哈?。?/p>

WebSocket經(jīng)典的使用場景:網(wǎng)站在線聊天系統(tǒng)、彈幕系統(tǒng)…

臣附議:webSocket技術無法做到向下兼容,不兼容低版本的IE,因此依賴于瀏覽器版本,這也正是webSocket非常顯著的缺陷。

二、WebSocket的出現(xiàn)到底為我們解決了什么實際問題?

在傳統(tǒng)的b/s架構中,要實現(xiàn)服務器向client進行實時消息推送功能,市場上常用的解決方案大致分為三類:

定時輪詢 客戶端以一定的時間間隔向服務端發(fā)出請求
長輪詢 如果服務器沒有可以立即返回給客戶端的數(shù)據(jù),則不會立刻返回一個空結(jié)果
流技術 客戶端隱藏的窗口向服務端發(fā)出一個長輪詢的請求

長輪詢機制:

綜合這幾種方案,您會發(fā)現(xiàn)這些目前我們所使用的所謂的實時技術并不是真正的實時技術,它們只是在用 Ajax 方式來模擬實時的效果,定時輪詢需要實時獲取取服務端信息的應用時, client需要頻繁輪詢server,為了拿到最新信息, client一直這樣循環(huán)下去server如果一直沒有新的消息, client的大多請求都是屬于無效請求, 導致會帶來很多無謂的網(wǎng)絡傳輸,所以這是一種非常低效的實時方案。長輪詢對服務器造成的壓力非常大,并且如果服務端的數(shù)據(jù)變更非常頻繁的話,這種方式無異于定時輪詢。所以為了解決傳統(tǒng)http請求的實際問題,WebSocket技術應運而生!下面博主給張圖讓大家生動的理解傳統(tǒng)HTTP和WebSocket的差異化:

三、博主使用WebSocket的場景

博主最進在公司調(diào)用第三方影像采集系統(tǒng),由于影像狀態(tài)是異步返回給業(yè)務系統(tǒng)的,導致當業(yè)務系統(tǒng)收到第三方回調(diào)后,對于前臺用戶體驗來說是無感知的,因此前臺必須刷新頁面才能獲取到影像最新狀態(tài)。這時候由service主動向client實時發(fā)送影像采集狀態(tài)的通知是最好不過的方案!在上述提到的常用解決方案,像輪詢這種比較low的實現(xiàn),博主作為技術宅,肯定是不會作為技術選型的,哈哈…

四、不多bb,上代碼!

本項目是基于SpringBoot環(huán)境開發(fā)

1、導入websocket坐標

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

2、封裝WebSocketUtil工具類,用于提供對session鏈接、斷開連接、推送消息的簡單控制。

 public class WebsocketUtil {
  /**
   * 記錄當前在線的Session
   */
  private static final Map<String, Session> ONLINE_SESSION = new ConcurrentHashMap<> ();

  /**
   * 添加session
   * @param userId
   * @param session
   */
  public static void addSession(String userId, Session session){
    // 此處只允許一個用戶的session鏈接。一個用戶的多個連接,我們視為無效。
    ONLINE_SESSION.putIfAbsent ( userId, session );
  }

  /**
   * 關閉session
   * @param userId
   */
  public static void removeSession(String userId){
    ONLINE_SESSION.remove ( userId );
  }

  /**
   * 給單個用戶推送消息
   * @param session
   * @param message
   */
  public static void sendMessage(Session session, String message){
    if(session == null){
      return;
    }

    // 同步
    RemoteEndpoint.Async async = session.getAsyncRemote ();
    async.sendText ( message );
  }

  /**
   * 向所有在線人發(fā)送消息
   * @param message
   */
  public static void sendMessageForAll(String message) {
    //jdk8 新方法
    ONLINE_SESSION.forEach((sessionId, session) -> sendMessage(session, message));
  }
}

3、 WebSocketController

如上,已經(jīng)創(chuàng)建好了簡單的session管理和消息管理,接下來要使用注解的方式,使用SpringBoot的websocket包提供的方法,實現(xiàn)OnOpen、OnClose、OnMessage三個方法,再實現(xiàn)一個OnError方法來應對異常。代碼段如下:

/**
 * websocket接口處理類
 */
@Component
@ServerEndpoint ( value = "/chat/{userid}" )
public class WebsocketController {

  /**
   * 連接事件,加入注解
   * @param userId
   * @param session
   */
  @OnOpen
  public void onOpen( @PathParam ( value = "userid" ) String userId, Session session ) {
    String message ="[" + userId + "]加入聊天室??!";

    // 添加到session的映射關系中
    WebsocketUtil.addSession ( userId, session );
    // 廣播通知,某用戶上線了
    WebsocketUtil.sendMessageForAll ( message );
  }

  /**
   * 連接事件,加入注解
   * 用戶斷開鏈接
   * @param userId
   * @param session
   */
  @OnClose
  public void onClose(@PathParam ( value = "userId" ) String userId, Session session ) {
    String message ="[" + userId + "]退出了聊天室...";

    // 刪除映射關系
    WebsocketUtil.removeSession ( userId );
    // 廣播通知,用戶下線了
    WebsocketUtil.sendMessageForAll ( message );
  }

  /**
   * 當接收到用戶上傳的消息
   * @param userId
   * @param session
   */
  @OnMessage
  public void onMessage(@PathParam ( value = "userId" ) String userId, Session session ,String message) {
    String msg ="[" + userId + "]:"+message;

    // 直接廣播
    WebsocketUtil.sendMessageForAll ( msg );
  }

  /**
   * 處理用戶活連接異常
   * @param session
   * @param throwable
   */
  @OnError
  public void onError(Session session, Throwable throwable) {
    try {
      session.close();
    } catch (IOException e) {
      e.printStackTrace();
    }
    throwable.printStackTrace();
  }
}

4、添加 ServerEndpointExporter 啟動Bean

public class DemoApplication {

  public static void main(String[] args) {
    SpringApplication.run(DemoApplication.class, args);
  }

  /**
   * 會自動注冊使用了@ServerEndpoint注解聲明的Websocket endpoint
   * 要注意,如果使用獨立的servlet容器,
   * 而不是直接使用springboot的內(nèi)置容器,
   * 就不要注入ServerEndpointExporter,因為它將由容器自己提供和管理。
   */
  @Bean
  public ServerEndpointExporter serverEndpointExporter() {
    return new ServerEndpointExporter();
  }
}

那些年踩過的坑:
注意:在websocketEndpoint中,使用@Autowired一些列注解注入Bean時候,一直無法注入,報空指針。原因在于spring管理的都是單例(singleton),和 websocket (多對象)相沖突。
解決辦法:通過上下文獲取bean實例:從Spring上下文獲取bean實例的方法

到此這篇關于SpringBoot集成WebSocket長連接實際應用詳解的文章就介紹到這了,更多相關SpringBoot WebSocket長連接內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Java報錯:Error:java:?程序包org.springframework.boot不存在解決辦法

    Java報錯:Error:java:?程序包org.springframework.boot不存在解決辦法

    建完springboot項目時,點擊啟動,有可能會報錯,下面這篇文章主要給大家介紹了關于Java報錯:Error:java:?程序包org.springframework.boot不存在的解決辦法,需要的朋友可以參考下
    2024-02-02
  • 在MyBatis中使用接口映射的步驟詳解

    在MyBatis中使用接口映射的步驟詳解

    在MyBatis中使用接口映射是一種基于Java接口而非XML映射文件的方式來綁定SQL查詢和操作,這種方法使用注解來指定SQL語句,并將其直接關聯(lián)到接口方法上,本文給大家介紹了在MyBatis中使用接口映射的步驟,需要的朋友可以參考下
    2024-06-06
  • Java中的Unsafe在安全領域的使用總結(jié)和復現(xiàn)(實例詳解)

    Java中的Unsafe在安全領域的使用總結(jié)和復現(xiàn)(實例詳解)

    unsafe里面有很多好用的方法,比如allocateInstance可以直接創(chuàng)建實例對象,defineAnonymousClass可以創(chuàng)建一個VM匿名類(VM?Anonymous?Class),以及直接從內(nèi)存級別修改對象的值。這篇文章主要介紹了Java中的Unsafe在安全領域的一些應用總結(jié)和復現(xiàn),需要的朋友可以參考下
    2022-03-03
  • springCloud config本地配置操作

    springCloud config本地配置操作

    這篇文章主要介紹了springCloud config本地配置操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-10-10
  • MybatisPlus特殊查詢的實現(xiàn)介紹

    MybatisPlus特殊查詢的實現(xiàn)介紹

    這篇文章主要介紹了MybatisPlus查詢投影、聚合查詢、分組查詢、等值查詢、范圍查詢、模糊查詢、排序查詢,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習吧
    2022-10-10
  • Spring中bean的生命周期之getSingleton方法

    Spring中bean的生命周期之getSingleton方法

    今天給大家?guī)淼氖顷P于Spring的相關知識,文章圍繞著Spring中bean的生命周期之getSingleton方法展開,文中有非常詳細的介紹及代碼示例,需要的朋友可以參考下
    2021-06-06
  • Java使用synchronized實現(xiàn)互斥鎖功能示例

    Java使用synchronized實現(xiàn)互斥鎖功能示例

    這篇文章主要介紹了Java使用synchronized實現(xiàn)互斥鎖功能,結(jié)合實例形式分析了Java使用synchronized互斥鎖功能簡單實現(xiàn)方法與操作技巧,需要的朋友可以參考下
    2020-05-05
  • java開源區(qū)塊鏈jdchain入門

    java開源區(qū)塊鏈jdchain入門

    這篇文章主要介紹了java開源區(qū)塊鏈jdchain入門,文中為大家講解了關于部署及組件遇到的一些問題,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步
    2022-02-02
  • java8中l(wèi)amba表達式的使用

    java8中l(wèi)amba表達式的使用

    這篇文章主要介紹了java8中l(wèi)amba表達式的使用,非常不錯,具有參考借鑒價值,需要的朋友可以參考下
    2017-02-02
  • springboot restTemplate連接池整合方式

    springboot restTemplate連接池整合方式

    這篇文章主要介紹了springboot restTemplate連接池整合方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-10-10

最新評論

庄浪县| 桑日县| 九江县| 舒城县| 郧西县| 公主岭市| 苍梧县| 桐乡市| 逊克县| 湘潭市| 浙江省| 烟台市| 遂昌县| 丰都县| 曲水县| 郸城县| 贡觉县| 微博| 尤溪县| 洪湖市| 木里| 定南县| 东光县| 贡嘎县| 乌兰察布市| 手游| 静乐县| 惠安县| 新河县| 广汉市| 襄汾县| 家居| 六安市| 衡水市| 华坪县| 绥滨县| 聂拉木县| 栖霞市| 青河县| 钟山县| 侯马市|