以下基于 Vue3 + Spring Boot 3.2 的 WebSocket 消息弹窗实现方案:
后端实现(Spring Boot 3.2)
- 添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
- WebSocket 配置类
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/ws-notification")
.setAllowedOriginPatterns("*")
.withSockJS();
}
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.enableSimpleBroker("/topic");
registry.setApplicationDestinationPrefixes("/app");
}
}
- 消息通知服务
@Service
public class NotificationService {
private final SimpMessagingTemplate messagingTemplate;
public NotificationService(SimpMessagingTemplate messagingTemplate) {
this.messagingTemplate = messagingTemplate;
}
public void sendGlobalNotification(String message) {
Map<String, Object> payload = new HashMap<>();
payload.put("timestamp", System.currentTimeMillis());
payload.put("content", message);
payload.put("type", "ALERT");
messagingTemplate.convertAndSend("/topic/notifications", payload);
}
}
- 测试控制器(可选)
@RestController
@RequestMapping("/api/notify")
public class TestController {
private final NotificationService notificationService;
public TestController(NotificationService notificationService) {
this.notificationService = notificationService;
}
@PostMapping
public ResponseEntity<?> triggerNotification(@RequestParam String message) {
notificationService.sendGlobalNotification(message);
return ResponseEntity.ok().build();
}
}
前端实现(Vue3)
- 安装依赖
npm install @stomp/stompjs sockjs-client
- WebSocket 工具类(src/utils/websocket.js)
import { reactive } from 'vue'
import { Client } from '@stomp/stompjs'
const useWebSocket = () => {
const state = reactive({
client: null,
isConnected: false
})
const connect = () => {
state.client = new Client({
brokerURL: 'http://localhost:8080/ws-notification',
debug: function (str) {
console.log('STOMP: ' + str)
},
reconnectDelay: 5000,
heartbeatIncoming: 4000,
heartbeatOutgoing: 4000
})
state.client.onConnect = () => {
state.isConnected = true
state.client.subscribe('/topic/notifications', (message) => {
const payload = JSON.parse(message.body)
// 触发全局事件或更新store
const event = new CustomEvent('global-notification', { detail: payload })
window.dispatchEvent(event)
})
}
state.client.activate()
}
const disconnect = () => {
if (state.client) {
state.client.deactivate()
state.isConnected = false
}
}
return { state, connect, disconnect }
}
export default useWebSocket
- 全局通知组件(src/components/GlobalNotification.vue)
<script setup>
import { ref, onMounted, onBeforeUnmount } from 'vue'
const notifications = ref([])
let timeoutId = null
const showNotification = (payload) => {
notifications.value.push({
id: Date.now(),
...payload
})
if (!timeoutId) {
processQueue()
}
}
const processQueue = () => {
if (notifications.value.length === 0) {
timeoutId = null
return
}
timeoutId = setTimeout(() => {
notifications.value.shift()
processQueue()
}, 3000)
}
onMounted(() => {
window.addEventListener('global-notification', (e) => {
showNotification(e.detail)
})
})
onBeforeUnmount(() => {
window.removeEventListener('global-notification')
clearTimeout(timeoutId)
})
</script>
<template>
<div class="fixed top-4 right-4 z-50 space-y-2">
<div
v-for="notification in notifications"
:key="notification.id"
class="p-4 bg-white rounded-lg shadow-lg border-l-4 border-blue-500 min-w-[300px]"
>
<div class="font-semibold">{{ notification.type }}</div>
<div class="text-gray-600">{{ notification.content }}</div>
<div class="text-xs text-gray-400 mt-2">
{{ new Date(notification.timestamp).toLocaleTimeString() }}
</div>
</div>
</div>
</template>
- 在 App.vue 中初始化
<script setup>
import { onMounted } from 'vue'
import GlobalNotification from '@/components/GlobalNotification.vue'
import useWebSocket from '@/utils/websocket'
const { connect, disconnect } = useWebSocket()
onMounted(() => {
connect()
})
// 可选:处理断线重连等
</script>
<template>
<RouterView />
<GlobalNotification />
</template>
使用流程
- 后端启动后,调用
/api/notify?message=测试消息发送通知 - 前端会自动建立 WebSocket 连接
- 收到通知后会在右上角显示持续3秒的弹窗
- 多个通知会排队依次显示
扩展建议
- 添加消息类型样式(成功/警告/错误)
- 增加消息关闭按钮
- 添加音效提示
- 连接状态监控
- JWT 认证支持
- 消息持久化存储
- 用户特定的通知通道
测试技巧
- 使用 Postman 的 WebSocket 功能测试后端
- 在浏览器控制台测试事件触发:
window.dispatchEvent(new CustomEvent('global-notification', {
detail: {
timestamp: Date.now(),
content: "测试消息",
type: "SUCCESS"
}
}))

浙公网安备 33010602011771号