欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

SpringBoot集成WebSocket【基于純H5】進(jìn)行點對點[一對一]和廣播[一對多]實時推送

 更新時間:2018年08月15日 09:58:54   作者:Ouyzc  
這篇文章主要介紹了SpringBoot集成WebSocket【基于純H5】進(jìn)行點對點[一對一]和廣播[一對多]實時推送,具有一定的參考價值,感興趣的小伙伴們可以參考一下

之前實現(xiàn)WebSocket基于STOMP的,覺得SpringBoot封裝的太高,不怎么靈活,現(xiàn)在實現(xiàn)一個純H5的,也大概了解webSocket在內(nèi)部是怎么傳輸?shù)摹?/p>

1.環(huán)境搭建

因為在上一篇基于STOMP協(xié)議實現(xiàn)的WebSocket里已經(jīng)有大概介紹過Web的基本情況了,所以在這篇就不多說了,我們直接進(jìn)入正題吧,在SpringBoot中,我們還是需要導(dǎo)入WebSocket的包。

在pox.xml加上對springBoot對WebSocket的支持:

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

這里大概說一下自己的一點小見解:客戶端與服務(wù)器建立WebSocket連接,實際上是創(chuàng)建了一個Socket,這個Socket是共享與客戶端和服務(wù)器的。兩者只要往對應(yīng)的Socket里操作,就可以實現(xiàn)雙方實時通訊了

2.編碼實現(xiàn)

一、在SpringBoot中,添加WebSocket的配置

package com.cloud.sbjm.configure;
 
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
import com.cloud.sbjm.security.WebSocketInterceptor;
import com.cloud.sbjm.service.Imp.MyHandler;
 
 
//實現(xiàn)接口來配置Websocket請求的路徑和攔截器。
@Configuration
@EnableWebSocket
public class WebSocketH5Config implements WebSocketConfigurer{
 
	@Override
	public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
		
	  //handler是webSocket的核心,配置入口
	  registry.addHandler(new MyHandler(), "/myHandler/{ID}").setAllowedOrigins("*").addInterceptors(new WebSocketInterceptor());
		
	}
 
	
}

1.@Configuration:注解標(biāo)識該類為Spring的配置類

2.@EnableWebSocket:開啟注解接收和發(fā)送消息

3.實現(xiàn)WebSocketConfigurer接口,重寫registerWebSocketHandlers方法,這是一個核心實現(xiàn)方法,配置websocket入口,允許訪問的域、注冊Handler、定義攔截器??蛻舳送ㄟ^“/myHandler/{ID}”直接訪問Handler核心類,進(jìn)行socket的連接、接收、發(fā)送等操作,這里由于還加了個攔截器,所以建立新的socket訪問時,都先進(jìn)來攔截器再進(jìn)去Handler類,“new WebSocketInterceptor()”是我實現(xiàn)的攔截器,“new MyHandler()”是我實現(xiàn)的一個Handler類。

二、WebSocketInterceptor攔截器的實現(xiàn):

package com.cloud.sbjm.security;
 
import java.util.Map;
 
import javax.servlet.http.HttpSession;
 
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.HandshakeInterceptor;
 
public class WebSocketInterceptor implements HandshakeInterceptor {
 
  //進(jìn)入hander之前的攔截
  @Override
  public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Map<String, Object> map) throws Exception {
    if (request instanceof ServletServerHttpRequest) {
      String ID = request.getURI().toString().split("ID=")[1];
      System.out.println("當(dāng)前session的ID="+ID);
      ServletServerHttpRequest serverHttpRequest = (ServletServerHttpRequest) request;
      HttpSession session = serverHttpRequest.getServletRequest().getSession();
      map.put("WEBSOCKET_USERID",ID);
    }
    return true;
  }
 
  @Override
  public void afterHandshake(ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Exception e) {
  	System.out.println("進(jìn)來webSocket的afterHandshake攔截器!");
  }
}

1.實現(xiàn)了HandshakeInterceptor 接口,并實現(xiàn)了beforeHandshake該方法,該方法是在進(jìn)入Handler核心類之前進(jìn)行攔截。

這里主要實現(xiàn)的邏輯是:

截取客戶端建立webSocket連接時發(fā)送的URL地址字符串,并通過對該字符串進(jìn)行特殊標(biāo)識截取操作,獲取客戶端發(fā)送的唯一標(biāo)識(由自己定義的,一般是系統(tǒng)用戶ID唯一標(biāo)識,用以標(biāo)識該用戶),并把它以鍵值對的形式放到Session里,這樣后期可以通過該session獲取它對應(yīng)的用戶ID了。【一個session對應(yīng)著一個webSocketSession】

三、MyHandler核心類的實現(xiàn)

package com.cloud.sbjm.service.Imp;
 
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import net.sf.json.JSONObject;
import org.springframework.stereotype.Service;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.WebSocketMessage;
import org.springframework.web.socket.WebSocketSession;
 
 
@Service
public class MyHandler implements WebSocketHandler {
	
  //在線用戶列表
  private static final Map<String, WebSocketSession> users;
 
  
  static {
    users = new HashMap<>();
  }
  //新增socket
  @Override
  public void afterConnectionEstablished(WebSocketSession session) throws Exception {
  	 System.out.println("成功建立連接");
  	 String ID = session.getUri().toString().split("ID=")[1];
     System.out.println(ID);
     if (ID != null) {
       users.put(ID, session);
       session.sendMessage(new TextMessage("成功建立socket連接"));
       System.out.println(ID);
       System.out.println(session);
     }
     System.out.println("當(dāng)前在線人數(shù):"+users.size());
  }
 
  //接收socket信息
  @Override
	public void handleMessage(WebSocketSession webSocketSession, WebSocketMessage<?> webSocketMessage) throws Exception {
  	try{
	  	JSONObject jsonobject = JSONObject.fromObject(webSocketMessage.getPayload());  	
	  	System.out.println(jsonobject.get("id"));
	  	System.out.println(jsonobject.get("message")+":來自"+(String)webSocketSession.getAttributes().get("WEBSOCKET_USERID")+"的消息");
	  	sendMessageToUser(jsonobject.get("id")+"",new TextMessage("服務(wù)器收到了,hello!"));
  	 }catch(Exception e){
   	  e.printStackTrace();
     }
		
	}
 
  /**
   * 發(fā)送信息給指定用戶
   * @param clientId
   * @param message
   * @return
   */
  public boolean sendMessageToUser(String clientId, TextMessage message) {
    if (users.get(clientId) == null) return false;
    WebSocketSession session = users.get(clientId);
    System.out.println("sendMessage:" + session);
    if (!session.isOpen()) return false;
    try {
      session.sendMessage(message);
    } catch (IOException e) {
      e.printStackTrace();
      return false;
    }
    return true;
  }
 
  /**
   * 廣播信息
   * @param message
   * @return
   */
  public boolean sendMessageToAllUsers(TextMessage message) {
    boolean allSendSuccess = true;
    Set<String> clientIds = users.keySet();
    WebSocketSession session = null;
    for (String clientId : clientIds) {
      try {
        session = users.get(clientId);
        if (session.isOpen()) {
          session.sendMessage(message);
        }
      } catch (IOException e) {
        e.printStackTrace();
        allSendSuccess = false;
      }
    }
 
    return allSendSuccess;
  }
 
 
  @Override
  public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
    if (session.isOpen()) {
      session.close();
    }
    System.out.println("連接出錯");
    users.remove(getClientId(session));
  }
 
  @Override
  public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
    System.out.println("連接已關(guān)閉:" + status);
    users.remove(getClientId(session));
  }
 
  @Override
  public boolean supportsPartialMessages() {
    return false;
  }
 
  /**
   * 獲取用戶標(biāo)識
   * @param session
   * @return
   */
  private Integer getClientId(WebSocketSession session) {
    try {
      Integer clientId = (Integer) session.getAttributes().get("WEBSOCKET_USERID");
      return clientId;
    } catch (Exception e) {
      return null;
    }
  }
}

1.實現(xiàn)了WebSocketHandler接口,并實現(xiàn)了關(guān)鍵的幾個方法。

① afterConnectionEstablished(接口提供的):建立新的socket連接后回調(diào)的方法。主要邏輯是:將成功建立連接的webSocketSssion放到定義好的常量[private static final Map<String, WebSocketSession> users;]中去。這里也截取客戶端訪問的URL的字符串,拿到標(biāo)識,以鍵值對的形式講每一個webSocketSession存到users里,以記錄每個Socket。

② handleMessage(接口提供的):接收客戶端發(fā)送的Socket。主要邏輯是:獲取客戶端發(fā)送的信息。這里之所以可以獲取本次Socket的ID,是因為客戶端在第一次進(jìn)行連接時,攔截器進(jìn)行攔截后,設(shè)置好ID,這樣也說明,雙方在相互通訊的時候,只是對第一次建立好的socket持續(xù)進(jìn)行操作。

③ sendMessageToUser(自己定義的):發(fā)送給指定用戶信息。主要邏輯是:根據(jù)用戶ID從常量users(記錄每一個Socket)中,獲取Socket,往該Socket里發(fā)送消息,只要客戶端還在線,就能收到該消息。

④sendMessageToAllUsers (自己定義的):這個廣播消息,發(fā)送信息給所有socket。主要邏輯是:跟③類型,只不過是遍歷整個users獲取每一個socket,給每一個socket發(fā)送消息即可完廣播發(fā)送

⑤handleTransportError(接口提供的):連接出錯時,回調(diào)的方法。主要邏輯是:一旦有連接出錯的Socket,就從users里進(jìn)行移除,有提供該Socket的參數(shù),可直接獲取ID,進(jìn)行移除。這個在客戶端沒有正常關(guān)閉連接時,會進(jìn)來,所以在開發(fā)客戶端時,記得關(guān)閉連接

⑥afterConnectionClosed(接口提供的):連接關(guān)閉時,回調(diào)的方法。主要邏輯:一旦客戶端/服務(wù)器主動關(guān)閉連接時,將個socket從users里移除,有提供該Socket的參數(shù),可直接獲取ID,進(jìn)行移除。

后臺的開發(fā)就開發(fā)完了,大家有沒有發(fā)現(xiàn)比基于STOMP協(xié)議實現(xiàn)要靈活得多?

四、客戶端頁面的實現(xiàn)【基于H5】

不需要加入任何的JS包

<!DOCTYPE html>
<html>
 <head>
  <title>socket.html</title>
	
  <meta name="keywords" content="keyword1,keyword2,keyword3">
  <meta name="description" content="this is my page">
  <meta name="content-type" content="text/html" charset="UTF-8">
  <!--<link rel="stylesheet" type="text/css" href="./styles.css" rel="external nofollow" >-->
 
 </head>
 
 <body>
	
	Welcome<br/>
<input id="text" type="text" /><button onclick="send()">Send</button>  <button onclick="closeWebSocket()">Close</button>
<div id="message">
</div>
  <!-- 公共JS -->
  <script type="text/javascript" src="../webSocket/jquery.min.js"></script>
 
	
<script type="text/javascript">
var userID="888";
var websocket=null;
 $(function() {
 
 //創(chuàng)建WebSocket
 connectWebSocket();
 })
 
  //強制關(guān)閉瀏覽器 調(diào)用websocket.close(),進(jìn)行正常關(guān)閉
 window.onunload = function() {
  	 
  //關(guān)閉連接  
  closeWebSocket();  
  }
 
 //建立WebSocket連接
 function connectWebSocket(){
 	
	console.log("開始...");
   
   //建立webSocket連接
    websocket = new WebSocket("ws://127.0.0.1:9091/cloud-sbjm/myHandler/ID="+userID);
   
   //打開webSokcet連接時,回調(diào)該函數(shù)
    websocket.onopen = function () {   
    console.log("onpen"); 
    }
    
    //關(guān)閉webSocket連接時,回調(diào)該函數(shù)
    websocket.onclose = function () {
    //關(guān)閉連接  
    console.log("onclose");
    }
	
	  //接收信息
    websocket.onmessage = function (msg) {
    console.log(msg.data);
    }
 }
 
 //發(fā)送消息
 function send(){
   var postValue={};
   postValue.id=userID;
   postValue.message=$("#text").val(); 	 	
   websocket.send(JSON.stringify(postValue));
 }
 //關(guān)閉連接
 function closeWebSocket(){
 	 if(websocket != null) {
      websocket.close();
    }
 }
 
</script>
 </body>
</html>

頁面比較簡單,簡單解釋一下:

1.new WebSocket("ws://127.0.0.1:9091/cloud-sbjm/myHandler/ID="+userID),與服務(wù)器建立webSocket連接,后面的ID="+userID,是動態(tài)參數(shù),跟服務(wù)器配置Handler的訪問地址時對應(yīng)"/myHandler/{ID}"。

2.H5也提供多個回調(diào)函數(shù)

onopen:打開webSokcet連接時,回調(diào)該函數(shù)

onclose:關(guān)閉webSocket連接時,回調(diào)該函數(shù)

onmessage:服務(wù)器給該socket發(fā)送消息時,回調(diào)該函數(shù),獲取消息

websocket.send(JSON.stringify(postValue));:給Socket發(fā)送消息,服務(wù)器獲取

websocket.close();客戶端主要關(guān)閉連接,會觸發(fā)客戶端的onclose方法和服務(wù)器的afterConnectionClosed方法

到此服務(wù)端的開發(fā)也完成了,下面執(zhí)行一下程序效果圖:

一、建立連接

客戶端:

服務(wù)器:

二、發(fā)送消息

客戶端:

服務(wù)器:

三、服務(wù)器主動推送消息

服務(wù)器代碼:

到此已經(jīng)完成了,各位可以根據(jù)自己需求進(jìn)行修改,這會靈活多了!

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

相關(guān)文章

  • Springboot整合策略模式詳解

    Springboot整合策略模式詳解

    這篇文章主要介紹了Springboot整合策略模式詳解的相關(guān)資料,需要的朋友可以參考下
    2023-01-01
  • java實現(xiàn)通用分頁(后端)

    java實現(xiàn)通用分頁(后端)

    這篇文章主要介紹了java實現(xiàn)通用分頁(后端)方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-12-12
  • macbook中springboot的jmeter壓測示例

    macbook中springboot的jmeter壓測示例

    這篇文章主要介紹了macbook中springboot的jmeter壓測示例詳解,本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-11-11
  • Java final 修飾符知識點總結(jié)(必看篇)

    Java final 修飾符知識點總結(jié)(必看篇)

    下面小編就為大家?guī)硪黄狫ava final 修飾符知識點總結(jié)(必看篇)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-09-09
  • Java 圖片壓縮實現(xiàn)思路及代碼

    Java 圖片壓縮實現(xiàn)思路及代碼

    本文為大家詳細(xì)介紹下圖片壓縮的具體實現(xiàn)思路及java代碼,想學(xué)習(xí)的各位可以參考下哈,希望對大家有所幫助
    2013-07-07
  • SSM+微信小程序?qū)崿F(xiàn)物業(yè)管理系統(tǒng)及實例代碼

    SSM+微信小程序?qū)崿F(xiàn)物業(yè)管理系統(tǒng)及實例代碼

    這篇文章主要介紹了SSM+微信小程序?qū)崿F(xiàn)物業(yè)管理系統(tǒng),ssm微信小程序物業(yè)管理系統(tǒng),有網(wǎng)站后臺管理系統(tǒng),本文通過實例代碼給大家展示系統(tǒng)的功能,需要的朋友可以參考下
    2022-02-02
  • SpringBoot+MinIO實現(xiàn)文件上傳、讀取、下載、刪除的使用示例

    SpringBoot+MinIO實現(xiàn)文件上傳、讀取、下載、刪除的使用示例

    本文主要介紹了SpringBoot+MinIO實現(xiàn)文件上傳、讀取、下載、刪除的使用示例,詳細(xì)介紹每個功能實現(xiàn)的步驟和代碼示例,具有一定的參考價值,感興趣的可以了解一下
    2023-10-10
  • Java中的WeakHashMap詳解

    Java中的WeakHashMap詳解

    這篇文章主要介紹了Java中的WeakHashMap詳解,WeakHashMap可能平時使用的頻率并不高,但是你可能聽過WeakHashMap會進(jìn)行自動回收吧,下面就對其原理進(jìn)行分析,需要的朋友可以參考下
    2023-09-09
  • Java編程之雙重循環(huán)打印圖形

    Java編程之雙重循環(huán)打印圖形

    這篇文章主要介紹了Java編程之雙重循環(huán)打印圖形,屬于Java編程基礎(chǔ)練習(xí)部分,具有一定參考價值,需要的朋友可以了解下。
    2017-11-11
  • Java優(yōu)雅的處理金錢問題(BigDecimal)

    Java優(yōu)雅的處理金錢問題(BigDecimal)

    本文主要介紹了Java優(yōu)雅的處理金錢問題(BigDecimal),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-06-06

最新評論