Spring WebSocket Stomp 整合Vue
描述:将websocket应用在实际的项目中,用于后台应用向浏览器推送消息。架构:传统的springmvc基于xml配置的(但是websocket配置是基于java config配置,可以穿插的配置),前端采用vue.js.启动报错:java.lang.IllegalArgumentException: Async support must be enabled on a se...
描述:
将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>
红框为浏览器向后台应用推送的消息
后台向浏览器推送的消息
微信公众号:
JAVA程序猿成长之路
分享资源,记录程序猿成长点滴。专注于Java,Spring,SpringBoot,SpringCloud,分布式,微服务。
更多推荐
所有评论(0)