領先一步
VMware 提供培訓和認證,以加速您的進度。
了解更多歡迎來到另一期的 您可能不需要另一個函式庫 (YMNNALFT)!自 2016 年以來,我花了很多時間在 我的 Spring Tips 影片中,闡明(或試圖闡明!)Spring 生態系統中一些更巨大的機會。 然而,今天,我以不同的精神來到您身邊,希望專注於那些小而隱藏的寶石,它們能完成出色的事情,並且可以避免您額外依賴第三方函式庫及其隱含的複雜性。
開放網路長期以來一直為那些希望建立一個商品平台,以大規模建構和部署服務及應用程式的人們帶來希望。 我們知道,一旦改進了一些東西,網路就可以變得引人注目。 人們可以提供豐富的客戶端,這些客戶端可以透過重新整理瀏覽器頁面來升級。 他們可以提供以資料和多媒體為中心、身歷其境的體驗。 我們知道,如果他們有正確的範例來建構網站和服務,人們就可以做到這些事情。 但他們說,沒有酸就無法欣賞甜,因此社群開始尋找建構網站和服務的絕對最差的方法,而這就是我們如何獲得 PHP 的故事。
結束。...
好吧,所以還有一點點。 一開始,後端和客戶端都存在嚴重的限制。 然而,客戶端的問題持續的時間比後端的問題長得多。 到 2000 年代初期,每個重要的程式語言社群都可以建構 HTTP 服務,但客戶端的能力停滯不前。 (幾乎就像某種主要力量出於惡意阻止開放網路發展一樣。 但是為什麼? 誰? 這是一個謎,我想我們永遠無法解決......)
開放網路自行演變。 它使用 HTTP PATCH
修補了自己。 在 90 年代末,我們讓 PayPal 成為可能進行安全的商業交易。 在 2000 年代初期,我們獲得了對 HTTP 的約束,稱為 REST(代表 Really Easy Service Transactions,還是 REcent Software Trend? 不。 這不對。 Representational State Transfer! 聽起來是對的......)。 然後 "Ajax"(不,不是清潔產品)出現了,它允許客戶端就地向服務發出請求,而無需強制另一個 HTTP 往返服務以獲取新頁面。 很好。 然後我們花了令人痛苦的五年左右的時間,試圖尋找將資料從伺服器推送到客戶端的方法,而不是回應用戶端的請求將資料發送到客戶端。
我們確實嘗試了所有方法。 有很多拙劣的解決方案。 (這是一個有趣的事實:janky JavaScript 在 Node.js 到來之前就存在了!)最終,在 2011 年,我們獲得了一個所有 HTTP 瀏覽器供應商和 HTTP 伺服器供應商都可以始終如一地支援的標準,並且解決了我們 70% 的需求:WebSockets。 Websockets 太棒了! 它們是將非同步通訊引入基於瀏覽器的應用程式的最佳方式。 它們快速、輕量且易於實作。
雖然有很多框架可以用於實作 WebSocket 端點,但您不必再尋找 Spring,因為它開箱即用地支援反應式和非反應式服務。 讓我們看看使用 Spring Webflux(反應式 Web 運行時)的服務範例。
您將需要以下依賴項。
org.springframework.boot
: spring-boot-starter-webflux
這是我放入 application.properties
的內容
spring.main.web-application-type=reactive
這是程式碼
package bootiful.websockets.service;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.reactive.HandlerMapping;
import org.springframework.web.reactive.handler.SimpleUrlHandlerMapping;
import org.springframework.web.reactive.socket.WebSocketHandler;
import org.springframework.web.reactive.socket.WebSocketMessage;
import org.springframework.web.reactive.socket.server.support.WebSocketHandlerAdapter;
import reactor.core.publisher.Flux;
import java.util.Map;
@SpringBootApplication
public class BootifulApplication {
public static void main(String[] args) {
System.setProperty("spring.profiles.active", "wsserver");
SpringApplication.run(BootifulApplication.class, args);
}
@Bean
SimpleUrlHandlerMapping greetingsHm() {
return new SimpleUrlHandlerMapping(Map.of("/ws/greetings", greetingsWsh()), 10);
}
@Bean
WebSocketHandler greetingsWsh() {
return session -> {
Flux<WebSocketMessage> out = session.receive().map(WebSocketMessage::getPayloadAsText)
.flatMap(name -> Flux.just("Hi, " + name).map(session::textMessage));
return session.send(out);
};
}
}
SimpleUrlHandlerMapping
將 WebSocketHandler
映射到 HTTP URI。 WebSocketHandler
提供反應式 WebSocket 端點邏輯,將傳入的酬載(名稱)轉換為問候語(Hi, NAME!
)以發送到客戶端。
現在,我要做一些我通常不會做的事情。 如果有任何其他方法,朋友們,我肯定更喜歡這個替代方案,而不是這個相當不體面的前進方式。 我不會在禮貌的公司裡做這件事,但我認為沒有其他方法可以完成這件事,沒有其他方法可以證明與 WebSocket 端點通訊有多麼微不足道。 我不會輕易地做這件事。
我.. 要使用 JavaScript
window.addEventListener('load', () => {
const ws = new WebSocket('ws://127.0.0.1:8080/ws/greetings')
ws.addEventListener('open', () => {
ws.send('JavaScript Fans')
})
ws.addEventListener('message', (message) => {
console.log(message.data)
})
})
在範例中,我們在 JavaScript 中設定一個 WebSocket
物件,註冊一個回呼以在 WebSocket 最終準備好時發送資料,並註冊另一個回呼以接收任何到達的回覆。 前往瀏覽器的開發人員工具(每個瀏覽器的說明各不相同,但如果您使用的是 Mac 並且使用的是 Chrome 或 Firefox,您可以嘗試 OPTION
+ CMD
+ I
),然後選擇 Console
。 您將在那裡看到來自 WebSocket 端點的回應。
使用更多程式碼,我們也可以使用 Spring WebSocketClient
與該服務通訊。
您將需要以下依賴項。
org.springframework.boot
: spring-boot-starter-webflux
這是程式碼
package bootiful.websockets.client;
import lombok.SneakyThrows;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Bean;
import org.springframework.web.reactive.socket.WebSocketMessage;
import org.springframework.web.reactive.socket.client.ReactorNettyWebSocketClient;
import org.springframework.web.reactive.socket.client.WebSocketClient;
import reactor.core.publisher.Mono;
import java.net.URI;
@SpringBootApplication
public class BootifulApplication {
@SneakyThrows
public static void main(String[] args) {
System.setProperty("spring.profiles.active", "wsclient");
SpringApplication.run(BootifulApplication.class, args);
Thread.sleep(5_000);
}
@Bean
WebSocketClient webSocketClient() {
return new ReactorNettyWebSocketClient();
}
@Bean
ApplicationListener<ApplicationReadyEvent> ready(WebSocketClient client) {
return event -> client.execute(URI.create("ws://127.0.0.1:8080/ws/greetings"), webSocketSession -> {
WebSocketMessage world = webSocketSession.textMessage("Spring Fans");
return webSocketSession.send(Mono.just(world))
.thenMany(webSocketSession.receive().map(WebSocketMessage::getPayloadAsText).log()).then();
})//
.subscribe();
}
}
這是我放入 application.properties
的內容
spring.main.web-application-type=none
WebSockets 使我們基於瀏覽器的客戶端更加活躍。 但是,我更喜歡 RSocket 用於服務到服務的通訊。
您喜歡這種一目了然的方法嗎? 您學到什麼了嗎? 與往常一樣,我很想聽到您的意見,所以 請在 Twitter 上發聲 (@starbuxman) ! 我會帶著另一期 YMNNALFT 回來,所以一定要錯過。