Spring Boot WebFlux-08——WebFlux 中 WebSocket 實現通訊

第08課:WebFlux 中 WebSocket 實現通訊

前言

WebFlux 該模塊中包含了對反應式 HTTP、服務器推送事件和 WebSocket 的客戶端和服務器端的支持。這裏咱們簡單實踐下 WebFlux 中 WebSocket 實現通訊。javascript

什麼是 WebSocket

WebSocket 是一種通訊協議,類比下 HTTP 協議,HTTP 協議只能有客戶端發起請求,而後獲得響應。 通常經過 HTTP 的輪詢方式,實現 WebSocket 相似功能。css

由於輪詢,每次新建鏈接,請求響應,浪費資源。WebSocket 就出現了,它支持客戶端和服務端雙向通信。相似 http 和 https,WebSocket 的標識符爲 ws 和 wss,案例地址爲:html

ws://localhost:8080/echo 

結構

回到這個工程,新建一個工程編寫 WebSocket 實現通訊案例。工程如圖:java

file

目錄核心以下:react

  • EchoHandler websocket 處理類(相似 HTTP Servlet 處理)
  • WebSocketConfiguration websocket 配置類
  • websocket-client.html HTML 客戶端實現
  • WSClient java 客戶端實現

單擊這裏查看源代碼git

EchoHandler 處理類

代碼以下:github

import org.springframework.stereotype.Component; import org.springframework.web.reactive.socket.WebSocketHandler; import org.springframework.web.reactive.socket.WebSocketSession; import reactor.core.publisher.Mono; @Component public class EchoHandler implements WebSocketHandler { @Override public Mono<Void> handle(final WebSocketSession session) { return session.send( session.receive() .map(msg -> session.textMessage( "服務端返回:小明, -> " + msg.getPayloadAsText()))); } } 

代碼詳解:web

  • WebSocketHandler 接口,實現該接口來處理 WebSokcet 消息。
  • handle(WebSocketSession session) 方法,接收 WebSocketSession 對象,即獲取客戶端信息、發送消息和接收消息的操做對象。
  • receive() 方法,接收消息,使用 map 操做獲取的 Flux 中包含的消息持續處理,並拼接出返回消息 Flux 對象。
  • send() 方法,發送消息。消息爲「服務端返回:小明, -> 」開頭的。

WebSocketConfiguration 配置類

代碼以下:spring

@Configuration public class WebSocketConfiguration { @Autowired @Bean public HandlerMapping webSocketMapping(final EchoHandler echoHandler) { final Map<String, WebSocketHandler> map = new HashMap<>(); map.put("/echo", echoHandler); final SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping(); mapping.setOrder(Ordered.HIGHEST_PRECEDENCE); mapping.setUrlMap(map); return mapping; } @Bean public WebSocketHandlerAdapter handlerAdapter() { return new WebSocketHandlerAdapter(); } } 

代碼詳解:sql

  • WebSocketHandlerAdapter 負責將 EchoHandler 處理類適配到 WebFlux 容器中;
  • SimpleUrlHandlerMapping 指定了 WebSocket 的路由配置;
  • 使用 map 指定 WebSocket 協議的路由,路由爲 ws://localhost:8080/echo。

運行工程

一個操做 Redis 工程就開發完畢了,下面運行工程驗證下。使用 IDEA 右側工具欄,點擊 Maven Project Tab,點擊使用下 Maven 插件的 install 命令。或者使用命令行的形式,在工程根目錄下,執行 Maven 清理和安裝工程的指令:

cd springboot-webflux-8-websocket mvn clean install 

在控制檯中看到成功的輸出:

... 省略
[INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 01:30 min [INFO] Finished at: 2018-10-15T10:00:54+08:00 [INFO] Final Memory: 31M/174M [INFO] ------------------------------------------------------------------------ 

在 IDEA 中執行 Application 類啓動,任意正常模式或者 Debug 模式,能夠在控制檯看到成功運行的輸出:

... 省略
2018-04-10 08:43:39.932 INFO 2052 --- [ctor-http-nio-1] r.ipc.netty.tcp.BlockingNettyContext : Started HttpServer on /0:0:0:0:0:0:0:0:8080 2018-04-10 08:43:39.935 INFO 2052 --- [ main] o.s.b.web.embedded.netty.NettyWebServer : Netty started on port(s): 8080 2018-04-10 08:43:39.960 INFO 2052 --- [ main] org.spring.springboot.Application : Started Application in 6.547 seconds (JVM running for 9.851) 

打開 https://www.websocket.org/echo.html網頁,大多數瀏覽器是支持 WebSokcet 協議的。

Location - 輸入通訊地址、點擊 Conect 會出現 CONNECTED。

而後發送消息,能夠看到服務端返回對應的消息。若是此時關閉了服務端,那麼會出現 DISCONNECTED:

file

websocket-client.html HTML 客戶端實現

實現 HTML 客戶端:

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Client WebSocket</title> </head> <body> <div class="chat"></div> <script> var clientWebSocket = new WebSocket("ws://localhost:8080/echo"); clientWebSocket.onopen = function () { console.log("clientWebSocket.onopen", clientWebSocket); console.log("clientWebSocket.readyState", "websocketstatus"); clientWebSocket.send("你好!"); } clientWebSocket.onclose = function (error) { console.log("clientWebSocket.onclose", clientWebSocket, error); events("聊天會話關閉!"); } function events(responseEvent) { document.querySelector(".chat").innerHTML += responseEvent + "<br>"; } </script> </body> </html> 

大多數瀏覽器是支持 WebSocket,代碼詳解以下:

  • 網頁打開是,會調用 onopen 方法,併發送消息給服務端「你好!」;
  • 若是服務端關閉,會調用 onclose 方法,頁面會出現「聊天會話關閉!」信息。

WSClient Java 客戶端實現

相似,HTTPClient 調用 HTTP,WebSocket 客戶端去調用 WebSokcet 協議,並實現服務。代碼以下:

public class WSClient { public static void main(final String[] args) { final WebSocketClient client = new ReactorNettyWebSocketClient(); client.execute(URI.create("ws://localhost:8080/echo"), session -> session.send(Flux.just(session.textMessage("你好"))) .thenMany(session.receive().take(1).map(WebSocketMessage::getPayloadAsText)) .doOnNext(System.out::println) .then()) .block(Duration.ofMillis(5000)); } } 

代碼詳解:

  • ReactorNettyWebSocketClient 是 WebFlux 默認 Reactor Netty 庫提供的 WebSocketClient 實現。
  • execute 方法,與 ws://localhost:8080/echo 創建 WebSokcet 協議鏈接。
  • execute 須要傳入 WebSocketHandler 的對象,用來處理消息,這裏的實現和前面的 EchoHandler 相似。
  • 經過 WebSocketSession 的 send 方法來發送字符串「你好」到服務器端,而後經過 receive 方法來等待服務器端的響應並輸出。

總結

這一篇內容主要一塊兒實踐了簡單的 WebSocket 的應用操做,以及 WebSocket 客戶端小例子。

工程:springboot-webflux-8-websocket

單擊這裏查看源代碼

相關文章
相關標籤/搜索