1. 程式人生 > >第十篇:Spring Boot整合WebSocket

第十篇:Spring Boot整合WebSocket

WebSocket是通過一個Socket來實現雙工非同步通訊的。直接使用WebSocket或者SockJS協議顯得特別繁瑣。使用它的子協議STOMP,它是一個更高級別的協議,STOMP協議使用一個基於幀格式來定義訊息,與HTTP的Request和Response類似。

環境依賴

Spring Boot對使用WebSocket提供了支援,配置原始碼在org.springframework.boot.autoconfigure.websocket包下。

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

順便說一句,springboot的高階元件會自動引用基礎的元件,像spring-boot-starter-websocket就引入了spring-boot-starter-web和spring-boot-starter,所以不要重複引入。

配置Websocket

@Configuration
public class WebSocketConfig {
    @Bean
    public
ServerEndpointExporter serverEndpointExporter (){ return new ServerEndpointExporter(); } }

處理WebSocket

@ServerEndpoint("/websocket")
@Component
public class WebSocketService {

    private final Logger log = LoggerFactory.getLogger(this.getClass());

    private static int COUNT = 0;
private static CopyOnWriteArraySet<WebSocketService> websocket = new CopyOnWriteArraySet<WebSocketService>(); private Session session; /* 建立連線的時候呼叫 */ @OnOpen public void onOpen(Session session) { this.session = session; websocket.add(this); addOnlineCount(); log.info("當前線上人數:" + COUNT); try { sendMessage("連線成功"); } catch (IOException e) { e.printStackTrace(); } } @OnClose public void onclose() { websocket.remove(this); subOnlineCount(); log.info("有一連線關閉!當前線上人數為" + getOnlineCount()); } /* 接收到客戶端的資訊 */ @OnMessage public void shoudaoMessage(String message, Session session) { log.info("server 收到的資訊是:" + message); //群發訊息 for (WebSocketService item : websocket) { try { item.sendMessage(message); } catch (IOException e) { e.printStackTrace(); } } } /** * 發生錯誤時呼叫 */ @OnError public void onError(Session session, Throwable error) { log.error("發生錯誤"); error.printStackTrace(); } public void sendMessage(String message) throws IOException { this.session.getBasicRemote().sendText(message); } /** * 群發自定義訊息 */ public static void sendInfo(String message) throws IOException { for (WebSocketService item : websocket) { try { item.sendMessage(message); } catch (IOException e) { continue; } } } public static synchronized int getOnlineCount() { return COUNT; } public static synchronized void addOnlineCount() { WebSocketService.COUNT++; } public static synchronized void subOnlineCount() { WebSocketService.COUNT--; } }

新建HTML檔案

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8"/>
    <title>Title</title>
</head>
<body>
<input id="text" type="text" /><button onclick="send()">Send</button>
<button onclick="closeWebSocket()">Close</button>
<div id="message">
</div>
</body>
<script>
    var websocket = null;
    if('WebSocket' in window){
        websocket = new WebSocket("ws://localhost:8080/websocket");
        // 建立成功後的回撥函式
        websocket.onopen = function (ev) {
            setMessageInnerHTML("open");
        }
        websocket.onclose=function(){
            setMessageInnerHTML("close");
        }
        websocket.onmessage=function (ev) {
            setMessageInnerHTML(ev.data);
        }
        //監聽視窗關閉事件,當視窗關閉時,主動去關閉websocket連線,防止連線還沒斷開就關閉視窗,server端會拋異常。
        window.onbeforeunload = function(){
            websocket.close();
        }

    }else {
        alert("瀏覽器不支援");
    }
    //將訊息顯示在網頁上
    function setMessageInnerHTML(innerHTML){
        document.getElementById('message').innerHTML += innerHTML + '<br/>';
    }

    //關閉連線
    function closeWebSocket(){
        websocket.close();
    }

    //傳送訊息
    function send(){
        var message = document.getElementById('text').value;
        websocket.send(message);
    }
</script>
</html>

伺服器推送

@RestController
public class WebSocketSendMessageController {
    @Autowired
    private WebSocketService socketService;
    @GetMapping("/send")
    public String sendMessage(){
        try {
            socketService.sendInfo("大家好");
        } catch (IOException e) {
            e.printStackTrace();
            return "fail";
        }
        return "succcess";
    }
}

測試

用瀏覽器開啟剛剛新建的html檔案
在這裡插入圖片描述
可以在多個視窗開啟,看看控制檯日誌資訊
在這裡插入圖片描述

傳送訊息
在這裡插入圖片描述
在這裡插入圖片描述

伺服器推送訊息
在這裡插入圖片描述
在這裡插入圖片描述
可以看到客戶端接受到了訊息

原始碼下載:https://github.com/chenjary/SpringBoot