实现功能
基于Springboot与Vue架构,首先使用Websocket实现频道订阅,在实现点对点与群发功能后,在前端调用windows自带的消息通知,实现推送功能。
开发环境
- Springboot 2.6.7
- vue 2.6.11
- socket-client 1.0.0
准备工作
在 Vue.js 项目中安装sockjs-client和stompjs。
java
npm install sockjs-client stompjs
在后端项目中添加依赖。
XML
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
WebSocket
为完成单播或者广播的频道的订阅功能,需要在前端和后端完成WebSocket的基本配置。
前端配置
需在vue项目中新建websocket.js文件,主要完成:
1.获取userid
2.定义WebSocketService,完成connect、subscribe、unsubscribe、sendMessage、disconnect等主要函数。
代码如下所示。
javascript
websocket.js
import SockJS from 'sockjs-client';
import Stomp from 'stompjs';
const userid = JSON.parse(sessionStorage.getItem('CurUser')).id
class WebSocketService {
constructor() {
this.stompClient = null;
this.subscriptions = new Map(); // 存储订阅的频道
}
// 连接 WebSocket
connect() {
const socket = new SockJS("/api/broadcast"); // 后端地址
this.stompClient = Stomp.over(socket);
this.stompClient.connect({}, () => {
console.log('do connect method');
console.log('stompClient', this.stompClient)
this.subscribe('/user/' + userid.toString() + '/alone/getResponse', (response) => {
if (this.onGlobalNotification) {
console.log("message print", response)
// this.onGlobalNotification(JSON.parse(message.body));
this.onGlobalNotification(response.body);
}
});
});
}
// 订阅频道
subscribe(destination, callback) {
const subscription = this.stompClient.subscribe(destination, callback);
this.subscriptions.set(destination, subscription);
}
// 取消订阅
unsubscribe(destination) {
const subscription = this.subscriptions.get(destination);
if (subscription) {
subscription.unsubscribe();
this.subscriptions.delete(destination);
}
}
// 发送消息到后端
sendMessage(destination, message) {
console.log("sendMessage method , message is ", message.content)
this.stompClient.send(destination, {}, message.content);
}
// 断开连接
disconnect() {
if (this.stompClient) {
this.stompClient.disconnect();
console.log('WebSocket 断开连接!');
}
}
}
export default new WebSocketService();
后端配置
在后端同样需要完成频道的订阅,新建文件WebSocketConfig.java,代码如下所示。
java
package com.wms.common;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
import javax.annotation.Resource;
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Resource
public AppConfig appConfig;
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.enableSimpleBroker(
"/user", "/topic1", "/topic2", "/mass"
);
// 点对点使用的订阅前缀(客户端订阅路径上会体现出来),不设置的话,默认也是 /user/
// 注意,这里必须和上面设置的Broker:/user 一致(两个都可以自定义,但必须一致)。否则连接不上
registry.setUserDestinationPrefix("/user/");
// 指服务端接收地址的前缀,意思就是说客户端给服务端发消息的地址的前缀
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
// 注册一个STOMP的endpoint端点,并指定使用SockJS协议
// 前端使用这个地址连接后端 WebSocket接口
registry.addEndpoint("/broadcast", "/point")
// 允许所有源跨域。还可以指定ip配置:http://ip:*
// 低版本的SpringBoot(2.1.5.RELEASE 就不行)不行
.setAllowedOriginPatterns(appConfig.getFrontHttpUrl()) // 此处填写前端页面地址
.withSockJS();
}
}
Vue
在用户登录之后,首先初始化WebSocket 连接,然后定义全局通知的回调,在回调函数onGlobalNotification中实现调用windows自带的通知功能Notification。
javascript
// 初始化 WebSocket 连接
WebSocketService.connect();
// 定义全局通知的回调
WebSocketService.onGlobalNotification = (message) => {
this.sendNotification('xxx',message)
// this.$bus.$emit("postTrigger")
};
javascript
// 发送通知的方法
sendNotification (title, body) {
// console.log("sendNotification", Notification.permission)
// 检查浏览器是否支持 Notification API
if ('Notification' in window) {
// 如果通知权限已经授予
if (Notification.permission === "granted") {
new Notification(title, {
body: body,
icon: logoIcon,
requireInteraction: true
});
} else if (Notification.permission !== "denied") {
// 请求用户授权
Notification.requestPermission().then(permission => {
if (permission === "granted") {
new Notification(title, {
body: body,
icon: logoIcon,
requireInteraction: true
});
}
});
}
} else {
console.log("浏览器不支持通知功能。");
}
},
在需要发送消息的地方使用函数sendMessage,在MethodApi处填写后端对应接口。
javascript
WebSocketService.sendMessage(
'/MethodApi',
{content: "message you want send"});
Springboot
在后端需要在controller文件中实现对应的MethodApi接口函数, 确定消息传递的目标用户与对应的消息,调用messagingTemplate中的函数convertAndSendToUser,完成在频道/user/userid/alone/getResponse的消息通知。
java
controller.java
@Autowired
private SimpMessagingTemplate messagingTemplate;
// p2p notification
@MessageMapping("/MethodApi")
public void p2pNotify(String content){
System.out.println(content);
// 可在此处通过接受到的消息确定目标用户 userid(int) 与 对应的消息 message(string)
System.out.println("=====发送通知=====");
messagingTemplate.convertAndSendToUser(userid.toString(),"/alone/getResponse",message);
}
效果图
此时就可以在本地进行测试了,效果如下:

服务器部署
因为windows系统通知需要浏览器给予网页权限,所以需要vue启用https协议,配置如下:
javascript
module.exports = {
devServer: {
port:8001,
https:true,
proxy: {
'/api': {
target: "http://localhost:8091/", // 代理目标的基础路径
secure: true, // 如果是https接口,需要配置这个参数
changeOrigin: true, // 支持跨域
pathRewrite: {
'^/api': '',
}
}
}
},
}