前言: 消息推送技术,之前你可能用过 Ajax 轮询。轮询是在特定的的时间间隔(如每1秒),由浏览器对服务器发出HTTP请求,然后由服务器返回最新的数据给客户端的浏览器。这种传统的模式带来很明显的缺点,即浏览器需要不断的向服务器发出请求,然而HTTP请求可能包含较长的头部,其中真正有效的数据可能只是很小的一部分,显然这样会浪费很多的带宽等资源。有了长连接的websocket,能更好的节省服务器资源和带宽,并且能够更实时地进行通讯。 WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。 WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。
依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
webSocket的配置文件
@Configuration
/**
* 注解开启使用STOMP协议来传输基于代理(message broker)的消息
*/
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
/*@Resource
private GetHeaderParamInterceptor getHeaderParamInterceptor;*/
/**
* 注册stomp的端点
*/
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
// 允许使用socketJs方式访问,允许跨域
// 在网页上我们就可以通过这个链接
// http://localhost:8080//ws/endpointChat
// 来和服务器的WebSocket连接
registry.addEndpoint("/ws/endpointChat")
.setAllowedOrigins("*")
.withSockJS();
}
@Override
/**
* 配置消息代理
*/
public void configureMessageBroker(MessageBrokerRegistry registry) {
//点对点queue,广播式topic
registry.enableSimpleBroker("/queue","/topic");
//registry.setUserDestinationPrefix("/user");
}
/**
* @Description 采用自定义拦截器 获取connect时候传递的参数
* @Author mk
* @Date 2020/12/17 9:47
* @Param
* @Return
*
*/
/* @Override
public void configureClientInboundChannel(ChannelRegistration registration) {
registration.interceptors(getHeaderParamInterceptor);
}*/
}
websocket处理类controller
@Controller
public class WsController {
@MessageMapping("/ws/nf")
@SendTo("/topic/nf")
public String handleNF() {
return "公告通知";
}
}
前端代码
const actions = {
connect(context){
context.state.stomp = Stomp.over(new SockJS("http://39.104.74.107:9090/ws/endpointChat"));
context.state.stomp.connect({}, frame=> {
//公告
context.state.stomp.subscribe("/topic/nf", message=> {
context.commit('toggleNFDot', true);
});
}, failedMsg=> {
});
}
}
const mutations = {
toggleNFDot(state, newValue){
state.nfDot = newValue;
},
}
用户发送系统通知,在系统通知保存到数据库后,发送websocket消息
sendNFMsg(){
this.dialogLoading = true;
var _this = this;
SendMsg({message: this.message, title: this.title}).then(resp=> {
_this.dialogLoading = false;
if (resp && resp.status == 200) {
var data = resp.data;
_this.$message({type: "success", message: resp.data.msg});
if (resp.data.code == 2000000) {
_this.$store.state.stomp.send("/ws/nf", {}, '');
_this.initSysMsgs();
_this.cancelSend();
}
}
})
},
用户进入home页面,发起后端请求,看是否有未读消息,来控制闹钟小红点的显示
initSysMsgs(){
var _this = this;
getMsg().then(resp=> {
_this.sysmsgs=resp.data.data;
var isDot = false;
resp.data.data.forEach(msg=> {
if (msg.state == 0) {
isDot = true;
}
})
_this.$store.commit('toggleNFDot', isDot);
})
}
效果图:
参考自“江南一点雨”大神的vhr项目