如何在Grails中实现用户之间的推送通知?
在Grails中实现用户间推送通知
核心方案选择
Grails本身无内置推送机制,结合WebSocket(双向实时通信)是这类场景的最优解,它能支持不同浏览器登录的用户间实时消息传递。
步骤1:配置WebSocket支持
Grails 3+可借助Spring Boot的WebSocket自动配置实现,无需额外插件。
1.1 添加依赖
在build.gradle中引入WebSocket相关依赖:
implementation 'org.springframework.boot:spring-boot-starter-websocket'
1.2 配置WebSocket端点
创建配置类grails-app/config/WebSocketConfig.groovy:
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 @Configuration @EnableWebSocketMessageBroker class WebSocketConfig implements WebSocketMessageBrokerConfigurer { @Override void configureMessageBroker(MessageBrokerRegistry config) { // 启用内存消息代理,处理/user前缀的目标地址 config.enableSimpleBroker('/user') // 客户端发送消息的前缀标识 config.setApplicationDestinationPrefixes('/app') } @Override void registerStompEndpoints(StompEndpointRegistry registry) { // 注册WebSocket端点,支持跨域与SockJS降级(兼容低版本浏览器) registry.addEndpoint('/notification-websocket') .setAllowedOriginPatterns('*') .withSockJS() } }
步骤2:实现消息处理逻辑
创建控制器grails-app/controllers/NotificationController.groovy,处理消息发送与推送:
import org.springframework.messaging.handler.annotation.MessageMapping import org.springframework.messaging.handler.annotation.SendToUser import org.springframework.messaging.simp.SimpMessagingTemplate import org.springframework.web.bind.annotation.PostMapping import org.springframework.web.bind.annotation.RequestBody import org.springframework.web.bind.annotation.RestController @RestController class NotificationController { // 注入消息模板,用于主动向指定用户推送消息 SimpMessagingTemplate simpMessagingTemplate // 接收客户端通过WebSocket发送的消息,自动推送给目标用户 @MessageMapping('/send-notification') @SendToUser('/queue/notifications') Map handleNotification(Map payload) { // 此处可添加消息持久化、权限校验等业务逻辑 return [ sender: payload.sender, content: payload.content, timestamp: new Date().getTime() ] } // 提供REST接口,供后端业务逻辑触发推送(比如订单状态变更通知) @PostMapping('/api/send-notification') void sendNotificationViaRest(@RequestBody Map payload) { // 向指定用户推送消息,目标路径格式:/user/{目标用户ID}/queue/notifications simpMessagingTemplate.convertAndSendToUser( payload.targetUserId, '/queue/notifications', [ sender: payload.sender, content: payload.content, timestamp: new Date().getTime() ] ) } }
步骤3:前端客户端实现
在用户登录后的GSP页面中添加WebSocket客户端代码:
<script src="https://cdn.jsdelivr.net/npm/sockjs-client@1/dist/sockjs.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/stompjs@2.3.3/lib/stomp.min.js"></script> <script> // 从后端获取当前登录用户ID(需结合Grails Spring Security实现) const currentUserId = '${currentUser.id}' // 初始化SockJS与Stomp客户端 const socket = new SockJS('/notification-websocket') const stompClient = Stomp.over(socket) // 建立WebSocket连接并订阅当前用户的通知队列 stompClient.connect({}, function(frame) { console.log('WebSocket连接成功: ' + frame) stompClient.subscribe('/user/queue/notifications', function(notification) { const message = JSON.parse(notification.body) // 展示通知(可替换为弹窗、页面消息栏等样式) alert(`来自${message.sender}的通知:${message.content}`) }) }) // 发送通知的触发函数(比如绑定按钮点击事件) function sendNotification(targetUserId, content) { stompClient.send('/app/send-notification', {}, JSON.stringify({ sender: currentUserId, targetUserId: targetUserId, content: content })) } </script> <!-- 测试按钮:向user2发送通知 --> <button onclick="sendNotification('user2', '这是一条测试推送消息')">给user2发通知</button>
步骤4:用户关联与权限校验
- 连接身份绑定:结合Grails Spring Security,在WebSocket握手时验证用户身份,确保每个连接都对应已登录用户,避免非法连接。
- 消息权限校验:在发送消息前,校验发送者与目标用户的关系(如好友、上下级),防止恶意推送。
步骤5:场景测试验证
- Chrome浏览器登录user1,打开页面确认WebSocket连接成功。
- Firefox浏览器登录user2,打开页面确认WebSocket连接成功。
- 在user1页面点击测试按钮,user2页面会实时弹出通知提示。
- 也可通过POST请求调用
/api/send-notification接口,传入参数触发推送。
生产环境注意事项
- 替换跨域配置中的
*为具体业务域名,避免安全风险。 - 增加消息持久化逻辑,用户离线时存储消息,上线后自动推送。
- 前端实现WebSocket断开自动重连机制,提升稳定性。
内容的提问来源于stack exchange,提问作者abuallrub
相关产品推荐
相关产品推荐

