實現功能
? ? ? ? 基于Springboot與Vue架構,首先使用Websocket實現頻道訂閱,在實現點對點與群發功能后,在前端調用windows自帶的消息通知,實現推送功能。
開發環境
- Springboot 2.6.7
- vue?2.6.11
- socket-client?1.0.0
準備工作
在 Vue.js 項目中安裝sockjs-client和stompjs。
npm install sockjs-client stompjs
在后端項目中添加依賴。
<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等主要函數。
代碼如下所示。
websocket.js
import SockJS from 'sockjs-client';
import Stomp from 'stompjs';const userid = JSON.parse(sessionStorage.getItem('CurUser')).idclass WebSocketService {constructor() {this.stompClient = null;this.subscriptions = new Map(); // 存儲訂閱的頻道}// 連接 WebSocketconnect() {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,代碼如下所示。
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 {@Resourcepublic AppConfig appConfig;@Overridepublic void configureMessageBroker(MessageBrokerRegistry registry) {registry.enableSimpleBroker("/user", "/topic1", "/topic2", "/mass");// 點對點使用的訂閱前綴(客戶端訂閱路徑上會體現出來),不設置的話,默認也是 /user/// 注意,這里必須和上面設置的Broker:/user 一致(兩個都可以自定義,但必須一致)。否則連接不上registry.setUserDestinationPrefix("/user/");// 指服務端接收地址的前綴,意思就是說客戶端給服務端發消息的地址的前綴}@Overridepublic 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。
// 初始化 WebSocket 連接
WebSocketService.connect();
// 定義全局通知的回調
WebSocketService.onGlobalNotification = (message) => {this.sendNotification('xxx',message)// this.$bus.$emit("postTrigger")
};
// 發送通知的方法sendNotification (title, body) {// console.log("sendNotification", Notification.permission)// 檢查瀏覽器是否支持 Notification APIif ('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處填寫后端對應接口。
WebSocketService.sendMessage('/MethodApi', {content: "message you want send"});
Springboot
? ? ? ? 在后端需要在controller文件中實現對應的MethodApi接口函數, 確定消息傳遞的目標用戶與對應的消息,調用messagingTemplate中的函數convertAndSendToUser,完成在頻道/user/userid/alone/getResponse的消息通知。
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協議,配置如下:
module.exports = {devServer: {port:8001,https:true,proxy: {'/api': {target: "http://localhost:8091/", // 代理目標的基礎路徑secure: true, // 如果是https接口,需要配置這個參數changeOrigin: true, // 支持跨域pathRewrite: {'^/api': '',}}}},
}