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

SpringBoot2.0整合WebSocket代碼實(shí)例

 更新時(shí)間:2019年11月26日 16:52:16   作者:Java碎碎念  
這篇文章主要介紹了SpringBoot2.0整合WebSocket代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下

這篇文章主要介紹了SpringBoot2.0整合WebSocket代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下

之前公司的某個(gè)系統(tǒng)為了實(shí)現(xiàn)推送技術(shù),所用的技術(shù)都是Ajax輪詢(xún),這種方式瀏覽器需要不斷的向服務(wù)器發(fā)出請(qǐng)求,顯然這樣會(huì)浪費(fèi)很多的帶寬等資源,所以研究了下WebSocket,本文將詳細(xì)介紹下。

一、什么是WebSocket?

WebSocket是HTML5開(kāi)始提供的一種在單個(gè)TCP連接上進(jìn)行全雙工通訊的協(xié)議,能更好的節(jié)省服務(wù)器資源和帶寬,并且能夠更實(shí)時(shí)地進(jìn)行通訊。

WebSocket 使得客戶(hù)端和服務(wù)器之間的數(shù)據(jù)交換變得更加簡(jiǎn)單,允許服務(wù)端主動(dòng)向客戶(hù)端推送數(shù)據(jù),在WebSocket API中,瀏覽器和服務(wù)器只需要完成一次握手,兩者之間就直接可以創(chuàng)建持久性的連接,并進(jìn)行雙向數(shù)據(jù)傳輸。

二、SpringBoot整合WebSocket

新建一個(gè)spring boot項(xiàng)目spring-boot-websocket,按照下面步驟操作。

pom.xml引入jar包

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

新建WebSocket的配置類(lèi)

這個(gè)配置類(lèi)檢測(cè)帶注解@ServerEndpoint的bean并注冊(cè)它們,配置類(lèi)代碼如下:

@Configuration
public class WebSocketConfig {
  /**
   * 給spring容器注入這個(gè)ServerEndpointExporter對(duì)象
   * 相當(dāng)于xml:
   * <beans>
   * <bean id="serverEndpointExporter" class="org.springframework.web.socket.server.standard.ServerEndpointExporter"/>
   * </beans>
   * <p>
   * 檢測(cè)所有帶有@serverEndpoint注解的bean并注冊(cè)他們。
   *
   * @return
   */
  @Bean
  public ServerEndpointExporter serverEndpointExporter() {
    System.out.println("我被注入了");
    return new ServerEndpointExporter();
  }
}

新建WebSocket的處理類(lèi)

這個(gè)處理類(lèi)需要使用@ServerEndpoint,這個(gè)類(lèi)里監(jiān)聽(tīng)連接的建立關(guān)閉、消息的接收等,具體代碼如下:

@ServerEndpoint(value = "/ws/asset")
@Component
public class WebSocketServer {

  @PostConstruct
  public void init() {
    System.out.println("websocket 加載");
  }
  private static Logger log = LoggerFactory.getLogger(WebSocketServer.class);
  private static final AtomicInteger OnlineCount = new AtomicInteger(0);
  // concurrent包的線(xiàn)程安全Set,用來(lái)存放每個(gè)客戶(hù)端對(duì)應(yīng)的Session對(duì)象。
  private static CopyOnWriteArraySet<Session> SessionSet = new CopyOnWriteArraySet<Session>();


  /**
   * 連接建立成功調(diào)用的方法
   */
  @OnOpen
  public void onOpen(Session session) {
    SessionSet.add(session);
    int cnt = OnlineCount.incrementAndGet(); // 在線(xiàn)數(shù)加1
    log.info("有連接加入,當(dāng)前連接數(shù)為:{}", cnt);
    SendMessage(session, "連接成功");
  }

  /**
   * 連接關(guān)閉調(diào)用的方法
   */
  @OnClose
  public void onClose(Session session) {
    SessionSet.remove(session);
    int cnt = OnlineCount.decrementAndGet();
    log.info("有連接關(guān)閉,當(dāng)前連接數(shù)為:{}", cnt);
  }

  /**
   * 收到客戶(hù)端消息后調(diào)用的方法
   *
   * @param message
   *      客戶(hù)端發(fā)送過(guò)來(lái)的消息
   */
  @OnMessage
  public void onMessage(String message, Session session) {
    log.info("來(lái)自客戶(hù)端的消息:{}",message);
    SendMessage(session, "收到消息,消息內(nèi)容:"+message);

  }

  /**
   * 出現(xiàn)錯(cuò)誤
   * @param session
   * @param error
   */
  @OnError
  public void onError(Session session, Throwable error) {
    log.error("發(fā)生錯(cuò)誤:{},Session ID: {}",error.getMessage(),session.getId());
    error.printStackTrace();
  }

  /**
   * 發(fā)送消息,實(shí)踐表明,每次瀏覽器刷新,session會(huì)發(fā)生變化。
   * @param session
   * @param message
   */
  public static void SendMessage(Session session, String message) {
    try {
//      session.getBasicRemote().sendText(String.format("%s (From Server,Session ID=%s)",message,session.getId()));
      session.getBasicRemote().sendText(message);
    } catch (IOException e) {
      log.error("發(fā)送消息出錯(cuò):{}", e.getMessage());
      e.printStackTrace();
    }
  }

  /**
   * 群發(fā)消息
   * @param message
   * @throws IOException
   */
  public static void BroadCastInfo(String message) throws IOException {
    for (Session session : SessionSet) {
      if(session.isOpen()){
        SendMessage(session, message);
      }
    }
  }

  /**
   * 指定Session發(fā)送消息
   * @param sessionId
   * @param message
   * @throws IOException
   */
  public static void SendMessage(String message,String sessionId) throws IOException {
    Session session = null;
    for (Session s : SessionSet) {
      if(s.getId().equals(sessionId)){
        session = s;
        break;
      }
    }
    if(session!=null){
      SendMessage(session, message);
    }
    else{
      log.warn("沒(méi)有找到你指定ID的會(huì)話(huà):{}",sessionId);
    }
  }
}

新建一個(gè)html

目前大部分瀏覽器支持WebSocket,比如Chrome, Mozilla,Opera和Safari,在html頁(yè)面進(jìn)行websocket的連接建立、收消息的監(jiān)聽(tīng),頁(yè)面代碼如下:

<html>
<head>
  <meta charset="UTF-8">
  <title>websocket測(cè)試</title>
  <script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
  <style type="text/css">
    h3,h4{
      text-align:center;
    }
  </style>
</head>
<body>

<h3>WebSocket測(cè)試,客戶(hù)端接收到的消息如下:</h3>

<textarea id = "messageId" readonly="readonly" cols="150" rows="30" >

</textarea>


<script type="text/javascript">
  var socket;
  if (typeof (WebSocket) == "undefined") {
    console.log("遺憾:您的瀏覽器不支持WebSocket");
  } else {
    console.log("恭喜:您的瀏覽器支持WebSocket");
    //實(shí)現(xiàn)化WebSocket對(duì)象
    //指定要連接的服務(wù)器地址與端口建立連接
    //注意ws、wss使用不同的端口。我使用自簽名的證書(shū)測(cè)試,
    //無(wú)法使用wss,瀏覽器打開(kāi)WebSocket時(shí)報(bào)錯(cuò)
    //ws對(duì)應(yīng)http、wss對(duì)應(yīng)https。
    socket = new WebSocket("ws://localhost:8080/ws/asset");
    //連接打開(kāi)事件
    socket.onopen = function() {
      console.log("Socket 已打開(kāi)");
      socket.send("消息發(fā)送測(cè)試(From Client)");
    };
    //收到消息事件
    socket.onmessage = function(msg) {
      $("#messageId").append(msg.data+ "\n");
      console.log(msg.data );
    };
    //連接關(guān)閉事件
    socket.onclose = function() {
      console.log("Socket已關(guān)閉");
    };
    //發(fā)生了錯(cuò)誤事件
    socket.onerror = function() {
      alert("Socket發(fā)生了錯(cuò)誤");
    }
    //窗口關(guān)閉時(shí),關(guān)閉連接
    window.unload=function() {
      socket.close();
    };
  }
</script>

</body>
</html>

三、查看運(yùn)行效果

啟動(dòng)SpringBoot項(xiàng)目

打開(kāi)首頁(yè)

本地瀏覽器打開(kāi)首頁(yè)http://localhost:8080/,出現(xiàn)WebSocket測(cè)試頁(yè)面,同時(shí)后臺(tái)打印連接的日志。

有連接加入,當(dāng)前連接數(shù)為:1,sessionId=0

往客戶(hù)端發(fā)送消息

通過(guò)上面日志可以看到客戶(hù)端連接連接的sessionId,我測(cè)試時(shí)候sessionId是0,然后瀏覽器訪(fǎng)問(wèn)下面接口即可往客戶(hù)端發(fā)送消息。

//參數(shù)說(shuō)明: id:sessionID 
//參數(shù)說(shuō)明: message:消息內(nèi)容
http://localhost:8080/api/ws/sendOne?id=0&message=你好Java碎碎念

發(fā)送消息動(dòng)圖

到此SpringBoot整合WebSocket的功能已經(jīng)全部實(shí)現(xiàn),有問(wèn)題歡迎留言溝通哦!

完整源碼地址:  https://github.com/suisui2019/springboot-study

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Spring覆蓋容器中Bean的注解如何實(shí)現(xiàn)@OverrideBean

    Spring覆蓋容器中Bean的注解如何實(shí)現(xiàn)@OverrideBean

    文章介紹了在項(xiàng)目開(kāi)發(fā)中如何通過(guò)偷梁換柱的方式重寫(xiě)Spring容器中的內(nèi)置Bean,并指出了需要注意的兩點(diǎn):1. 對(duì)應(yīng)的Bean應(yīng)基于接口注入;2. 如果不是基于接口注入,可以使用同包名同類(lèi)名的方式重寫(xiě)(可能存在潛在問(wèn)題,不推薦),文章還強(qiáng)調(diào)了“基于接口編程”的好處
    2025-01-01
  • Java中ResponseBodyEmitter的實(shí)現(xiàn)

    Java中ResponseBodyEmitter的實(shí)現(xiàn)

    這篇文章主要介紹了Java中ResponseBodyEmitter的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03
  • SpringBoot前后端分離實(shí)現(xiàn)個(gè)人博客系統(tǒng)

    SpringBoot前后端分離實(shí)現(xiàn)個(gè)人博客系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了使用springboot+mybatis+前端vue,使用前后端分離架構(gòu)實(shí)現(xiàn)的個(gè)人博客系統(tǒng),感興趣的小伙伴可以動(dòng)手嘗試一下
    2022-06-06
  • SpringBoot集成Mybatis-Plus多租戶(hù)架構(gòu)實(shí)現(xiàn)

    SpringBoot集成Mybatis-Plus多租戶(hù)架構(gòu)實(shí)現(xiàn)

    本文主要介紹了SpringBoot集成Mybatis-Plus多租戶(hù)架構(gòu)實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-09-09
  • Java在Map轉(zhuǎn)Json字符串時(shí)出現(xiàn)"\"轉(zhuǎn)義字符的解決辦法

    Java在Map轉(zhuǎn)Json字符串時(shí)出現(xiàn)"\"轉(zhuǎn)義字符的解決辦法

    當(dāng)一個(gè)Map被轉(zhuǎn)成Json字符串后,被添加到另一個(gè)Map中,會(huì)出現(xiàn)被加上“\”轉(zhuǎn)義字符的情況,這個(gè)時(shí)候該如何解決呢,下面就來(lái)和小編一起了解一下
    2023-07-07
  • 使用Java實(shí)現(xiàn)在PDF插入頁(yè)眉頁(yè)腳

    使用Java實(shí)現(xiàn)在PDF插入頁(yè)眉頁(yè)腳

    在處理PDF文檔時(shí),有時(shí)需要為文檔中的每一頁(yè)添加頁(yè)眉和頁(yè)腳,這篇文章主要為大家詳細(xì)介紹了如何使用Java為PDF文件添加頁(yè)眉、頁(yè)腳,感興趣的可以了解下
    2024-03-03
  • MyBatis-Plus 插件擴(kuò)展的實(shí)現(xiàn)

    MyBatis-Plus 插件擴(kuò)展的實(shí)現(xiàn)

    MyBatis-Plus通過(guò)插件擴(kuò)展機(jī)制增強(qiáng)功能,基于MyBatis Interceptor攔截器,包括分頁(yè)插件、邏輯刪除、SQL性能分析和樂(lè)觀(guān)鎖等,開(kāi)發(fā)者可自定義插件以適應(yīng)特定需求,有效地增強(qiáng)SQL執(zhí)行過(guò)程的控制和優(yōu)化,同時(shí)注意插件使用的性能影響和執(zhí)行順序
    2024-09-09
  • IDEA關(guān)閉SpringBoot程序后仍然占用端口的排查與解決方法

    IDEA關(guān)閉SpringBoot程序后仍然占用端口的排查與解決方法

    在使用 IntelliJ IDEA 開(kāi)發(fā) Spring Boot 應(yīng)用時(shí),有時(shí)即使關(guān)閉了應(yīng)用,程序仍然占用端口,這會(huì)導(dǎo)致重新啟動(dòng)應(yīng)用時(shí)出現(xiàn)端口被占用的錯(cuò)誤,所以本文給大家介紹了IDEA關(guān)閉SpringBoot程序后仍然占用端口的排查與解決方法,需要的朋友可以參考下
    2025-02-02
  • Maven 的配置文件路徑讀取方法

    Maven 的配置文件路徑讀取方法

    這篇文章主要介紹了Maven 的配置文件路徑讀取方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-06-06
  • 詳解Java中的延時(shí)隊(duì)列 DelayQueue

    詳解Java中的延時(shí)隊(duì)列 DelayQueue

    這篇文章主要介紹了Java中延時(shí)隊(duì)列 DelayQueue的相關(guān)資料,幫助大家更好的理解和使用Java,感興趣的朋友可以了解下
    2020-12-12

最新評(píng)論

旌德县| 鹿邑县| 沧源| 淮南市| 安西县| 泸溪县| 三明市| 海晏县| 沙湾县| 平果县| 张家川| 浙江省| 天等县| 金门县| 东兰县| 确山县| 汕尾市| 阿拉善左旗| 金门县| 文水县| 锦州市| 双鸭山市| 武定县| 喀什市| 济源市| 炎陵县| 文山县| 辽中县| 麻城市| 宝丰县| 盐亭县| 墨玉县| 志丹县| 长海县| 美姑县| 麻城市| 鹿泉市| 南木林县| 蓝田县| 东乡县| 吕梁市|