目錄
傳統 Tomcat 開發 WebSocket 回顧
WebSocket 的出現是基於 Web 應用的實時性需要而產生的,在淘寶、京東等網頁客服、網頁賣家聊天等需求上應用廣泛。對於前端網頁可以使用 H5 開發 WebSocket 客戶端,也可以使用 SockJS 庫開發 WebSocket 客戶端。
對於Java 開發者而言,後臺 WebSocket 服務端開發通常有以下常用的選擇:
Tomcat8 如下所示,自身已經支持 WebSocket 服務端開發,它的 lib 目錄下有自己實現 WebSocket 協議的開發包,如果是傳統的 Java Web 項目,則只需要將 tomcat-websocket.jar、websocket-api.jar 導入應用中即可進行代碼開發。Tomcat 自身也提供了 WebSocket 開發的示例,在 webapps/exampls下,一共提供了 4 個示例,可以啟動 Tomcat 進行訪問測試以及學習:對於傳統 Java Web 導包式應用開發,這裡不再過多進行說明,它的基本流程是:
1)新建 Java Web 應用後,導入 Tomcat 伺服器 lib 目錄下的 websocket-api.jar 、tomcat-websocket.jar開發包,前者是瀏覽器 webSocket 規範的接口,後者是 Tomcat 對它的實現
2)創建後臺 webSocket 服務端類,標識 @ServerEndpoint( javax.websocket.server.ServerEndpoint)註解,表示當前類是 webSocket 服務終端,同時在裡面實現客戶端連接建立、發送消息、接收消息等通信業務。
3)自己實現 javax.websocket.server.ServerApplicationConfig 接口,掃描整個應用所有的 @ServerEndpoint 服務終端SpringBoot 整合 Tomcat WebSocket
本文的重點是 SpringBoot 項目如何使用 Tomcat 的 webSocket 服務端開發;本文環境:springboot 2.1.0 ,使用內置的 Tomcat 伺服器。<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId></dependency>@ServerEndpoint 創建 websocket 服務終端
1、創建後臺 webSocket 服務端類,標識 @ServerEndpoint( javax.websocket.server.ServerEndpoint)註解,表示當前類是 webSocket 服務終端,同時在裡面實現客戶端連接建立、發送消息、接收消息等通信業務。
2、這與傳統導包式開發 Tomcat WebSocket 服務端是一樣的,區別就是:傳統方式 @ServerEndpoint 類上不需要加 @Component 交由 Spring 管理,而現在需要加上 @Component 將此組件交由 spring 管理。
import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.stereotype.Component;import javax.websocket.*;import javax.websocket.server.ServerEndpoint;import java.io.IOException;import java.util.HashSet;import java.util.Set;@ServerEndpoint(value = "/websocket/yy.action")@Componentpublic class ServerEnpoint { private static Logger logger = LoggerFactory.getLogger(ServerEnpoint.class); private static Set<Session> sessionSet = new HashSet<>(); @OnOpen public void afterConnectionEstablished(Session session) { sessionSet.add(session); logger.info("新客戶端加入,session id=" + session.getId() + ",當前客戶端格個數為:" + sessionSet.size()); session.getAsyncRemote().sendText("我是伺服器,你連接成功!"); } @OnClose public void afterConnectionClosed(Session session) { sessionSet.remove(session); logger.info("客戶端斷開,session id=" + session.getId() + ",當前客戶端格個數為:" + sessionSet.size()); } @OnMessage public void handleMessage(Session session, String textMessage) { try { logger.info("接收到客戶端信息,session id=" + session.getId() + ":" + textMessage); session.getBasicRemote().sendText(textMessage); } catch (IOException e) { e.printStackTrace(); } } @OnError public void handleTransportError(Session session, Throwable throwable) { System.out.println("shake client And server handleTransportError,session.getId()=" + session.getId() + " -- " + throwable.getMessage()); logger.error("與客戶端 session id=" + session.getId() + " 通信錯誤..."); }}注入 ServerEndpointExporter
1、注入 org.springframework.web.socket.server.standard.ServerEndpointExporter,這個 bean 會自動註冊使用了@ServerEndpoint 註解聲明的 Websocket endpoint 。
2、如果使用獨立的 servlet 容器,而不是使用 spring boot 的內置容器,就不要注入ServerEndpointExporter,因為它將由 Tomcat 容器自己提供和管理。
3、因為傳統導包式 Tomcat websocket 開發時,是需要實現 javax.websocket.server.ServerApplicationConfig 接口的,然後由它去掃描整個應用中的 @ServerEndpoint,而現在這一步就由 springboot 的 ServerEndpointExporter 取代了。
import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.web.socket.server.standard.ServerEndpointExporter;@Configurationpublic class WebSocketConfig { @Bean public ServerEndpointExporter serverEndpointExporter() { return new ServerEndpointExporter(); }}前端 H5 webSocket 客戶端
為了方便,直接使用 H5 的 webSocket 方式,頁面的 html 與 css 樣式就不做提供了,直接提供客戶端 webSocket 的 js 代碼。
var ws = null;function webSocketBind() { if ("WebSocket" in window) { ws = new WebSocket("ws://192.168.1.20/yyServer/websocket/yy.action"); ws.onopen = function () { console.log("伺服器連接成功,並發送數據到後臺..."); }; ws.onmessage = function (evt) { var received_msg = evt.data; console.log("接收到伺服器數據:" + received_msg); showClientMessage(received_msg); }; ws.onerror = function (evt) { console.log("客戶端 與 伺服器 數據傳輸錯誤..."); }; ws.onclose = function () { console.log("web scoket 連接關閉..."); }; } else { alert("您的瀏覽器不支持 WebSocket!"); }} let showServerMessage = function (message) { if (message != undefined && message.trim() != "") { ws.send(message.trim()); let messageShow = "<div class='messageLine server'><div class='messageContent serverCon'>" + message + "</div><span>:我</span>"; $(".centerTop").append(messageShow + "<br>"); $(".messageArea").val(""); let scrollHeight = $(".centerTop")[0].scrollHeight; $(".centerTop").scrollTop(scrollHeight - $(".centerTop").height()); }}; let showClientMessage = function (message) { if (message != undefined && message.trim() != "") { let messageShow = "<div class='messageLine client'><span>伺服器:</span><div class='messageContent clientCon'>" + message + "</div>"; $(".centerTop").append(messageShow + "<br>"); $(".messageArea").val(""); let scrollHeight = $(".centerTop")[0].scrollHeight; $(".centerTop").scrollTop(scrollHeight - $(".centerTop").height()); }}; $(function () { $(".messageArea").val(""); $(".sendButton").click(function () { let message = $(".messageArea").val(); showServerMessage(message); }); $(window).keydown(function (event) { if (event.keyCode === 13) { let message = $(".messageArea").val(); showServerMessage(message); } }); webSocketBind();});websocket 通信測試
作者:蚩尤後裔
來源:https://blog.csdn.net/wangmx1993328/article/details/84582904