zoukankan      html  css  js  c++  java
  • 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>
    

    红框为浏览器向后台应用推送的消息

    后台向浏览器推送的消息

    微信公众号

                              
  • 相关阅读:
    Servlet生命周期
    DAO 开发模式的几个类
    Iterator用法
    mysql相似于oracle的to_char() to_date()方法
    Java Web页面跳转
    JSP 连接MySQL 5.1
    采用DOM进行表格的修改操作
    使用css让XML文件按照HTML的风格显示出来
    正则表达式Regular Expression
    什么是“堆”,"栈","堆栈","队列",它们的区别
  • 原文地址:https://www.cnblogs.com/niugang0920/p/12187110.html
Copyright © 2011-2022 走看看