天天看點

SpringBoot如何整合WebSocket? | 帶你讀《SpringBoot實戰教程》之四十一

上一篇:SpringBoot如何整合ElasticSearch? | 帶你讀《SpringBoot實戰教程》之四十 下一篇:SpringBoot如何整合AngularJS? | 帶你讀《SpringBoot實戰教程》之四十二

本文來自于千鋒教育在阿裡雲開發者社群學習中心上線課程《SpringBoot實戰教程》,主講人楊紅豔,

點選檢視視訊内容

SpringBoot整合WebSocket

HTTP 協定是一種無狀态的、無連接配接的、單向的應用層協定。它采用了請求/響應模型。通信請求隻能由用戶端發起,服務端對請求做出應答處理。這種通信模型有一個弊端:HTTP 協定無法實作伺服器主動向用戶端發起消息。

這種單向請求的缺點,如果伺服器有連續的狀态變化,用戶端要獲知就非常麻煩。大多數 Web 應用程式将通過頻繁的異步JavaScript和XML(AJAX)請求實作長輪詢。輪詢的效率低,非常浪費資源(因為必須不停連接配接,或者 HTTP 連接配接始終打開)。

WebSocket 連接配接允許用戶端和伺服器之間進行全雙工通信,以便任一方都可以通過建立的連接配接将資料推送到另一端。WebSocket 隻需要建立一次連接配接,就可以一直保持連接配接狀态。這相比于輪詢方式的不停建立連接配接顯然效率要大大提高。

那麼如何使用呢?

添加依賴:

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

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

WebSocket的配置類:

//WebSocket的配置類
@Configuration
//開啟對WebSocket的支援
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer{

    
     //注冊一個STOMP協定的節點,并映射到指定的URL
    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        //注冊一個STOMP的endpoint,并指定使用SockJS協定
        registry.addEndpoint("/endpointSocket").withSockJS();
    }

    
     //配置消息代理
    @Override
    public void configureMessageBroker(MessageBrokerRegistry registry) {
        //配置一個廣播式的消息代理
        registry.enableSimpleBroker("/topic");
    }
}           

建立包:com.qianfeng.pojo:

浏覽器向伺服器發送消息實體類:

public class SocketMessage {
    private String message;

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}           

伺服器向浏覽器響應資料的封裝實體類:

public class SocketResponse {
    private String responseMessage;

    public SocketResponse(String responseMessage) {
        this.responseMessage = responseMessage;
    }

    public String getResponseMessage() {
        return responseMessage;
    }
}           

建立包:com.qianfeng.controller

控制類:

@Controller
public class WebSocketController {

    private SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    //當浏覽器向伺服器端發送STOMP請求時,通過@MessageMapping注解來映射/getServerTime位址
    @MessageMapping(value = "/getServerTime")
    //當服務端有消息時,會對訂閱了@SendTo中的路徑的用戶端發送消息
    @SendTo(value = "/topic/getResponse")
    public SocketResponse serverTime(SocketMessage message) throws InterruptedException {
        return new SocketResponse(message.getMessage() + sf.format(new Date()));
    }

    @RequestMapping("/index")
    public String toPage() {
        return "webSocket";
    }    
}           

建立頁面templates:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8"></meta>
    <title>內建內建WebSocket示例</title>
</head>
<body>
<div>
    <button id="connect" onclick="connect();">連接配接</button>
    <button id="disconnect" onclick="disconnect();">斷開連接配接</button>
    <button id="serverTimeId" onclick="getServerTime();">擷取伺服器端時間</button>
    <hr/>
    <span id="showServerTime"></span>
</div>
<script type="text/javascript" src="sockjs.min.js"></script>
<script type="text/javascript" src="stomp.min.js"></script>
<script type="text/javascript" src="jquery-3.1..min.js"></script>
<script src="http://cdn.sockjs.org/sockjs-0.3.min.js"></script>
<script type="text/javascript">
    var stompClient = null;
    $(function(){
        setConnect(false);
    });
    function setConnect(connected) {
        $("#connect").attr({disabled:connected});
        $("#disconnect").attr({disabled:!connected});
    }
    function connect() {
        var socket = new SockJS('/endpointSocket');
        //建立STOMP用戶端連接配接,目标位址為/endpointSocket的STOMP代理
        stompClient = stomp.over(socket);
        //列印stomp輸出資訊
        stompClient.debug = function(str) {
            console.log(str+ "\n");
        };
        //建立連接配接
        stompClient.connect({},function(frame)) {
            setConnect(true);
            //連接配接成功後訂閱/topic/getResponse目标發送的消息,該位址在Controller中用@SendTo指定
            stompClient.subscribe('/topic/getResponse',function(response) {
                showResponse(JSON.parse(response.body).responseMessage);
            });
        });
    }
    function disconnect() {
        if(stompClient != null) {
            stompClient.disconnect();
        }
        setConnect(false);
    }
    function getServerTime() {
        var message = "The server time is : ";
        //發送消息到服務端,/getServerTime位址是由Controller中的@MessageMapping指定
        stompClient.send("/getServerTime",{},JSON.stringify({'message':message}));
    }
    function showResponse(message) {
        var response = $("#showServerTime");
        response.html(message);
    }
</script>
</body>
</html>           

執行結果:

SpringBoot如何整合WebSocket? | 帶你讀《SpringBoot實戰教程》之四十一

配套視訊