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