Spring WebSocket Stomp 整合Vue


描述:

將websocket應用在實際的項目中,用於后台應用向瀏覽器推送消息。

架構:

傳統的springmvc基於xml配置的(但是websocket配置是基於java config配置,可以穿插的配置),前端采用vue.js.

啟動報錯:

java.lang.IllegalArgumentException: Async support must be enabled on a servlet and for all filters involved in async request processing. This is done in Java code using the Servlet API or by adding "<async-supported>true</async-supported>" to servlet and filter declarations in web.xml. Also you must use a Servlet 3.0+ container‘

解決:

需要在你的web.xml中所有的servlet和filter中添加<async-supported>true</async-supported>

引入依賴:spring版本需要4.x

<dependency>
     <groupId>org.springframework</groupId>
     <artifactId>spring-websocket</artifactId>
     <version>${spring.version}</version>
</dependency>

webscoket相關配置

WebSocketStompConfig.java 用於配置webscoket

package com.xdja.dsc.webscoket.config; 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; /** * * @ClassName: WebSocketStompConfig * @Description: webscoket配置 * @author niugang * @date 2018年11月6日 */ @Configuration //啟動websocket和基於代理的STOMP消息 @EnableWebSocketMessageBroker public class WebSocketStompConfig extends AbstractWebSocketMessageBrokerConfigurer { @Override public void registerStompEndpoints(StompEndpointRegistry registry) { //將clientMessage注冊為STOMP的一個端點 //客戶端在訂閱或發布消息到目的路徑前,要連接該端點 //setAllowedOrigins允許所有域連接,否則瀏覽器可能報403錯誤 registry.addEndpoint("/clientMessage").setAllowedOrigins("*").withSockJS(); } @Override public void configureMessageBroker(MessageBrokerRegistry registry) { registry.enableSimpleBroker("/queue", "/topic"); //后台應用接收瀏覽器消息端點前綴,這個將直接路由到@MessageMapping上 registry.setApplicationDestinationPrefixes("/app"); } } 

MessageService.java  后台向前端推送消息類

package com.xdja.dsc.webscoket.service; import com.alibaba.fastjson.JSONObject; import com.xdja.dsc.validation.exception.ServiceException; import com.xdja.dsc.validation.result.Result; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.messaging.simp.SimpMessageSendingOperations; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; /** * * @ClassName: MessageService * @Description: 向瀏覽器后台應用推送消息 * @author niugang * @date 2018年11月6日 */ @Service @EnableScheduling public class MessageService { @Autowired private SimpMessageSendingOperations messageTemplate; private Logger logger = LoggerFactory.getLogger(MessageService.class); /** * * @param info * @date 2018年11月6日 * @throws NullPointerException 參數為null時 */ public void sendMessage(Result info) { if (info == null) { throw new NullPointerException("info object not null"); } JSONObject jsonObject = new JSONObject(); jsonObject.put("code", info.getCode()); jsonObject.put("message", info.getMessage()); String resStr = jsonObject.toJSONString(); logger.info("send message to browser,message content [{}]", resStr); messageTemplate.convertAndSend("/topic/notify", resStr); } /** * * 40秒訊輪模擬向瀏覽器推消息 * @date 2018年11月6日 * @throws */ @Scheduled(cron = "0/40 * * * * ? ") public void test() { this.sendMessage(new Result(ServiceException.Service.DUPLICATED)); } } 

ReceiveClientController.java 接收前端發送的消息

package com.xdja.dsc.webscoket.controller; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.messaging.handler.annotation.MessageMapping; import org.springframework.stereotype.Controller; /** * * @ClassName: ReciveClientController * @Description: 測試瀏覽器向后台應用推送的消息 * @author niugang * @date 2018年11月6日 */ @Controller public class ReceiveClientController { private Logger logger = LoggerFactory.getLogger(ReceiveClientController.class); /** * 接收客戶端發送的消息 * @param content * @date 2018年11月6日 * @throws */ @MessageMapping("receive") public void receiveMessage(String content){ logger.info("browser send message content [{}]",content); } } 

前端vue

<script>
    import SockJS from 'sockjs-client';
    import Stomp from 'stompjs';
    export default {
        data(){
            return {
        
            }
        },
        methods:{
            //初始化
            initWebSocket(){
                this.connection();
              //模擬客戶端向后台推送消息
            let self = this;
                // 斷開重連機制,嘗試發送消息,捕獲異常發生時重連
                this.timer = setInterval(() => {
                    try {
                        self.stompClient.send("/app/receive",{},"test");
                    } catch (err) {
                        console.log("斷線了: " + err);
                        self.connection();
                    }
                }, 5000);
            },
            //建立連接
            connection() {
                // 建立連接對象
                //連接服務端提供的通信接口,連接以后才可以訂閱廣播消息和個人消息
                let _that=this;
                //后台服務ip和port
                _that.socket = new SockJS('http://localhost:8083/dsc/clientMessage');
                // 獲取STOMP子協議的客戶端對象
                _that.stompClient = Stomp.over(_that.socket);
                // 向服務器發起websocket連接
                _that.stompClient.connect('guest','guest',(frame) => {
                    // 訂閱服務端提供的某個topic
                    _that.stompClient.subscribe('/topic/notify', (msg) => {
                        //msg.body存放的是服務端發送給我們的信息
                        let  resData= JSON.parse(msg.body);
                        _that.$notify({
                            title: '警告',
                            message: "病毒查殺后台消息推送測試......",
                            type: 'warning'
                        });
                    });
                }, (err) => {
                });

            },
            disconnect() {
                if (this.stompClient != null) {
                    this.stompClient.disconnect();
                    console.log("Disconnected");
                }
            }
        },
        //銷毀頁面之前,斷開連接
        beforeDestroy: function () {
            //頁面離開時斷開連接,清除定時器
            this.disconnect();
            clearInterval(this.timer);
        },
        mounted(){
            //調用初始化websocket方法
            this.initWebSocket();
        },

    }
</script>

紅框為瀏覽器向后台應用推送的消息

后台向瀏覽器推送的消息

微信公眾號

                          


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM