Springboot + websocket

添加依賴:

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

進行設置:

import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;

/**
 * @author Fuyuanwu
 * @date 2019/11/7 16:24
 */
@Configuration
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
    /**
     * 將"/hello"路徑註冊爲STOMP端點,這個路徑與發送和接收消息的目的路徑有所不同,這是一個端點,客戶端在訂閱或發佈消息到目的地址前,要連接該端點,
     * 即用戶發送請求url="/applicationName/hello"與STOMP server進行連接。之後再轉發到訂閱url;
     * PS:端點的作用——客戶端在訂閱或發佈消息到目的地址前,要連接該端點。
     *
     * @param stompEndpointRegistry
     */
    public void registerStompEndpoints(StompEndpointRegistry stompEndpointRegistry) {
        // 在網頁上可以通過"/applicationName/hello"來和服務器的WebSocket連接
        stompEndpointRegistry.addEndpoint("/hello").setAllowedOrigins("*").withSockJS();
    }

    /**
     * 配置了一個簡單的消息代理,如果不重載,默認情況下回自動配置一個簡單的內存消息代理,用來處理以"/topic"爲前綴的消息。這裏重載configureMessageBroker()方法,
     * 消息代理將會處理前綴爲"/topic"和"/user"的消息。
     *
     * @param registry
     */
    @Override
    public void configureMessageBroker(MessageBrokerRegistry registry) {
        // 服務端向客戶端廣播/發送消息時允許通過的代理。即,服務端想向客戶端發送消息必須要要以 "/topic", "/user" 爲前綴,否則消息就發不出去。
        registry.enableSimpleBroker("/topic", "/user");
        // 表示客戶端向服務端 發送/訂閱 消息的路徑前綴。
        registry.setApplicationDestinationPrefixes("/web");
        // 服務端向單個客戶端(點對點推送)時,服務器推送給客戶端的路徑前綴。
        registry.setUserDestinationPrefix("/user");
    }
}

編寫用來測試的 controller :

import com.desuo.common.util.JsonUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.messaging.simp.annotation.SubscribeMapping;
import org.springframework.web.bind.annotation.RestController;

import java.security.Principal;

/**
 * @author Fuyuanwu
 * @date 2019/11/7 16:37
 */
@RestController
public class TestController {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());
    private final SimpMessagingTemplate simpMessagingTemplate;

    public TestController(SimpMessagingTemplate simpMessagingTemplate) {
        this.simpMessagingTemplate = simpMessagingTemplate;
    }

    // 測試客戶端主動發消息給服務端
    @MessageMapping("/message/test")
    public String receiveMessage(Principal principal, Book book) {
        logger.info("receive message principal name: {}", principal.getName());
        logger.info("這是客戶端發過來的數據: {}", JsonUtil.writeValueAsString(book));
        // 測試:服務端主動發給客戶端之廣播消息。也可以用 @SendTo("/topic/message") 註解
        simpMessagingTemplate.convertAndSend("/topic/message", "這是一條服務端向你廣播的消息");
        // 測試:服務端主動發給客戶端之一對一消息。也可以用 @SendToUser("/topic/message/test") 註解
        simpMessagingTemplate.convertAndSendToUser(principal.getName(), "/topic/message/test", "這是一條服務端向你單獨發送的消息");
        // 測試:向客戶端的默認路徑發送消息默認。默認路徑的規則爲 "/topic/" + @MessageMapping中的路徑,所以這裏的路徑就是:/topic/message/test
        // 根據規則,客戶端通過 subscribe 這個路徑 /topic/message/test 可以收到return的消息
        return "這條是服務端接受到請求後,走默認路徑給你返回的消息. receiveMessage";
    }

    // 測試客戶端主動發訂閱給服務端
    @SubscribeMapping("/subscribe/test")
    public String receiveSubscribe(Principal principal) {
        logger.info("receive subscriber principal name: {}", principal.getName());
        // 根據規則,客戶端通過 subscribe 這個路徑 /topic/subscribe/test 可以收到return的消息
        return "這條是服務端接受到請求後,走默認路徑給你返回的消息. receiveSubscribe";
    }

    public static class Book {
        private String title;
        private String color;

        public String getTitle() {
            return title;
        }

        public void setTitle(String title) {
            this.title = title;
        }

        public String getColor() {
            return color;
        }

        public void setColor(String color) {
            this.color = color;
        }
    }
}

前端向後端發送和接收消息:

let sock = new SockJS(this.serverUrls.material + '/hello')

let stompClient = this.stompClient = Stomp.over(sock)

stompClient.connect({}, function () {
    console.log('connected............')

    // 這個會接收到後臺廣播的消息
    stompClient.subscribe('/topic/message', function (message) {
      console.log('receive message form subscribe path: /topic/message', message)
    })
    // 這個會接收到後臺點對點發送過來的消息
    stompClient.subscribe('/user/topic/message/test', function (message) {
      console.log('receive message form subscribe path: /user/topic/message/test', message)
    })
    // 這個是後臺在接收到 前臺通過 stompClient.send('/web/message/test'.....) 發出的消息後,後臺延默認路徑返回的消息。
    stompClient.subscribe('/topic/message/test', function (message) {
      console.log('receive message form subscribe path: /topic/message/test', message)
    })

    // 主動發送調閱消息給後臺
    stompClient.subscribe('/web/subscribe/test', function (message) {
      console.log('receive message form subscribe path: /web/subscribe/test', message)
    })
    // 這個是後臺在接收到 前臺通過 stompClient.subscribe('/topic/subscribe'.....) 發出的訂閱消息後,後臺延默認路徑返回的消息。
    stompClient.subscribe('/topic/subscribe', function (message) {
      console.log('receive message form subscribe path: /topic/subscribe', message)
    })


    // 主動發送消息給後臺
    stompClient.send('/web/message/test', {}, JSON.stringify({title: 'Thinking in Java', color: 'yellow'}))
})

參考文檔:

spring websocket:https://docs.spring.io/spring/docs/5.2.1.RELEASE/spring-framework-reference/web.html#websocket-stomp

stomp-js:https://stomp-js.github.io/api-docs/latest/classes/CompatClient.html

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