Spring Boot整合WebSocket介紹 頂 原

WebSocket 簡介

WebSocket 是 HTML5 一種新的協議。它實現了瀏覽器與服務器全雙工通信,能更好的節省服務器資源和帶寬並達到實時通訊,它建立在 TCP 之上,同 HTTP 一樣通過 TCP 來傳輸數據,但是它和 HTTP 最大不同是:

  • WebSocket 是一種雙向通信協議,在建立連接後,WebSocket 服務器和 Browser/Client Agent 都能主動的向對方發送或接收數據,就像 Socket 一樣;
  • WebSocket 需要類似 TCP 的客戶端和服務器端通過握手連接,連接成功後才能相互通信。

整合示例

本示例爲演示WebSocket的廣播式模式,即服務端有消息時,會將消息發送給所有連接了當前endpoint的 Browser/Client Agent

 1. maven引入依賴包

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <boot.version>1.3.6.RELEASE</boot.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>${boot.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
            <version>${boot.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
            <version>${boot.version}</version>
        </dependency>
    </dependencies>

2. 編寫WebSocket的配置類

import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.AbstractWebSocketMessageBrokerConfigurer;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;

/**
 * @author ZhangPengFei
 * @Discription
 * @Data 2017-3-7
 * @Version 1.0.0
 */
@Configuration
//開啓對WebSocket的支持
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer{

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

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

3. 瀏覽器向服務器端發送消息的實體封裝類

/**
 * @author ZhangPengFei
 * @Discription
 * @Data 2017-3-7
 * @Version 1.0.0
 */
public class SocketMessage {
	private String message;

	public String getMessage() {
		return message;
	}

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

4. 服務器向瀏覽器響應數據的封裝實體類

/**
 * @author ZhangPengFei
 * @Discription
 * @Data 2017-3-7
 * @Version 1.0.0
 */
public class SocketResponse {
	private String responseMessage;

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

	public String getResponseMessage() {
		return responseMessage;
	}
}

5. 請求控制器

import com.os.china.entity.SocketMessage;
import com.os.china.entity.SocketResponse;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.stereotype.Controller;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @author ZhangPengFei
 * @Discription
 * @Data 2017-3-7
 * @Version 1.0.0
 */
@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()));
	}
}

6. 配置WebMvc視圖映射

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

/**
 * @author ZhangPengFei
 * @Discription
 * @Data 2017-3-7
 * @Version 1.0.0
 */
@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter{
	/**
	 * MVC視圖控制器配置
	 * @param registry
	 */
	@Override
	public void addViewControllers(ViewControllerRegistry registry) {
		//添加一個請求映射地址爲/index,返回對應視圖頁面爲webSocket
		registry.addViewController("/index").setViewName("/webSocket");
	}
}

7. 腳本添加,將 stomp.min.js(STOMP協議的客戶端腳本),socketjs.min.js(SocketJS的客戶端腳本)和 jQuery腳本放在src/main/resources/static下

注:STOMP協議的客戶端連接詳細介紹,請移步至我的另外一篇文章,WebSocket子協議STOMP詳解 https://my.oschina.net/feinik/blog/853875

8. 在項目的src/main/resources/templates下新建webSocket.html頁面

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8"/>
    <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.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>

9. 編寫SpringBoot的啓動類

import org.springframework.boot.Banner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * @author ZhangPengFei
 * @Discription
 * @Data 2017-3-7
 * @Version 1.0.0
 */
@SpringBootApplication
public class ApplicationTest {

	public static void main(String[] args) {
		SpringApplication application = new SpringApplication(ApplicationTest.class);
		application.setBannerMode(Banner.Mode.OFF);
		application.run(args);
	}
}

10. 啓動並測試,也可打開多個瀏覽器窗口連接到WebSocket服務端,在其中一個瀏覽器窗口中點擊獲取服務器時間,其他兩個也將接收到消息

好了,整合到此完結,具體代碼已上傳至GitHub https://github.com/AIFEINIK/SpringBoot-Learn/tree/master/spring-boot-websocket

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章