You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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:场景测试验证

  1. Chrome浏览器登录user1,打开页面确认WebSocket连接成功。
  2. Firefox浏览器登录user2,打开页面确认WebSocket连接成功。
  3. 在user1页面点击测试按钮,user2页面会实时弹出通知提示。
  4. 也可通过POST请求调用/api/send-notification接口,传入参数触发推送。

生产环境注意事项

  • 替换跨域配置中的*为具体业务域名,避免安全风险。
  • 增加消息持久化逻辑,用户离线时存储消息,上线后自动推送。
  • 前端实现WebSocket断开自动重连机制,提升稳定性。

内容的提问来源于stack exchange,提问作者abuallrub

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 22:45:53