02.25 SpringBoot2.0整合WebSocket,實現後端數據實時推送

之前公司的某個系統為了實現推送技術,所用的技術都是Ajax輪詢,這種方式瀏覽器需要不斷的向服務器發出請求,顯然這樣會浪費很多的帶寬等資源,所以研究了下WebSocket,本文將詳細介紹下。

一、什麼是WebSocket?

WebSocket是HTML5開始提供的一種在單個TCP連接上進行全雙工通訊的協議,能更好的節省服務器資源和帶寬,並且能夠更實時地進行通訊。

WebSocket 使得客戶端和服務器之間的數據交換變得更加簡單,允許服務端主動向客戶端推送數據,在WebSocket API中,瀏覽器和服務器只需要完成一次握手,兩者之間就直接可以創建持久性的連接,並進行雙向數據傳輸。

二、SpringBoot整合WebSocket

新建一個spring boot項目spring-boot-websocket,按照下面步驟操作。

  1. pom.xml引入jar包
<code><dependency>
<groupid>org.springframework.boot/<groupid>
<artifactid>spring-boot-starter-websocket/<artifactid>
/<dependency>
/<code>
  1. 新建WebSocket的配置類

這個配置類檢測帶註解@ServerEndpoint的bean並註冊它們,配置類代碼如下:

<code>@Configuration
public class WebSocketConfig {
/**

* 給spring容器注入這個ServerEndpointExporter對象
* 相當於xml:
* <beans>
* <bean>
* /<beans>
*


* 檢測所有帶有@serverEndpoint註解的bean並註冊他們。
*
* @return
*/
@Bean
public ServerEndpointExporter serverEndpointExporter() {
System.out.println("我被注入了");
return new ServerEndpointExporter();
}
}

/<code>
  1. 新建WebSocket的處理類

這個處理類需要使用@ServerEndpoint,這個類裡監聽連接的建立關閉、消息的接收等,具體代碼如下:

<code>
@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包的線程安全Set,用來存放每個客戶端對應的Session對象。
private static CopyOnWriteArraySet<session> SessionSet = new CopyOnWriteArraySet<session>();


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

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

/**
* 收到客戶端消息後調用的方法
*
* @param message
* 客戶端發送過來的消息
*/
@OnMessage
public void onMessage(String message, Session session) {
log.info("來自客戶端的消息:{}",message);
SendMessage(session, "收到消息,消息內容:"+message);

}

/**
* 出現錯誤
* @param session
* @param error
*/

@OnError
public void onError(Session session, Throwable error) {
log.error("發生錯誤:{},Session ID: {}",error.getMessage(),session.getId());
error.printStackTrace();
}

/**
* 發送消息,實踐表明,每次瀏覽器刷新,session會發生變化。
* @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("發送消息出錯:{}", e.getMessage());
e.printStackTrace();
}
}

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

/**
* 指定Session發送消息
* @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("沒有找到你指定ID的會話:{}",sessionId);
}
}
}
/<session>/<session>/<code>
  1. 新建一個html

目前大部分瀏覽器支持WebSocket,比如Chrome, Mozilla,Opera和Safari,在html頁面進行websocket的連接建立、收消息的監聽,頁面代碼如下:

<code>


<title>websocket測試/<title>

<style><br> h3,h4{<br> text-align:center;<br> }<br> /<style>



WebSocket測試,客戶端接收到的消息如下:



<textarea>

/<textarea>





/<code>

三、查看運行效果

啟動SpringBoot項目

  1. 打開首頁

本地瀏覽器打開首頁http://localhost:8080/,出現WebSocket測試頁面,同時後臺打印連接的日誌。

<code>有連接加入,當前連接數為:1,sessionId=0
/<code>
  1. 往客戶端發送消息

通過上面日誌可以看到客戶端連接連接的sessionId,我測試時候sessionId是0,然後瀏覽器訪問下面接口即可往客戶端發送消息。

<code>//參數說明: id:sessionID 
//參數說明: message:消息內容
http://localhost:8080/api/ws/sendOne?id=0&message=你好Java碎碎念
/<code>
SpringBoot2.0整合WebSocket,實現後端數據實時推送

發送消息動圖

到此SpringBoot整合WebSocket的功能已經全部實現,有問題歡迎留言溝通哦!

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


分享到:


相關文章: