集群特殊服务--Notification Service使用说明

博客介绍了集群特殊服务Notification Service的使用说明,聚焦信息技术领域中集群服务的相关内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

集群特殊服务--Notification Service使用说明
<think>我们正在讨论如何配置Ruoyi-APP接收Ruoyi-Vue发送的消息,实现前后端信息通信。根据Ruoyi-Vue-Plus框架的特性,我们可以考虑以下几种方式: 1. **WebSocket实时通信**:Ruoyi-Vue-Plus集了Sa-Token,可以使用WebSocket实现实时消息推送。 2. **HTTP接口调用**:APP通过轮询或长轮询方式从后端获取消息。 3. **使用消息队列**:如RabbitMQ、Kafka等,但需要额外中间件支持。 4. **第三方推送服务**:如极光推送、个推等。 考虑到Ruoyi-Vue-Plus框架已经集了Sa-Token,并且支持WebSocket,这里我们重点介绍使用WebSocket实现。 ### 步骤1:后端配置(Ruoyi-Vue-Plus) Ruoyi-Vue-Plus框架中已经内置了WebSocket支持,基于Sa-Token的WebSocket模块。我们需要做以下配置: #### 1.1 添加依赖 在`ruoyi-common`模块的`pom.xml`中确认已有以下依赖(一般已集): ```xml <dependency> <groupId>cn.dev33</groupId> <artifactId>sa-token-reactor-spring-boot-starter</artifactId> </dependency> <dependency> <groupId>cn.dev33</groupId> <artifactId>sa-token-stp</artifactId> </dependency> <dependency> <groupId>cn.dev33</groupId> <artifactId>sa-token-socket-spring-boot-starter</artifactId> </dependency> ``` #### 1.2 配置WebSocket 在`application.yml`中配置WebSocket: ```yaml sa-token: # websocket配置 socket: # 端口号(默认为8080,注意要和主端口冲突) port: 8081 ``` #### 1.3 创建消息处理器 创建一个类,继承`SaSocketHandler`,并重写相应方法。例如: ```java import cn.dev33.satoken.socket.SaSocketHandler; import cn.dev33.satoken.stp.StpUtil; import org.springframework.stereotype.Component; @Component public class MySaSocketHandler extends SaSocketHandler { // 连接建立时触发 @Override public void afterConnection(Object handshake) { // 获取连接唯一标识 String sessionId = getSession().getSessionId(); // 认证用户(这里假设连接时携带token进行认证) String token = getHandshakeParam("token"); StpUtil.checkLogin(token); // 绑定会话与当前用户 StpUtil.getSessionByLoginId(StpUtil.getLoginIdByToken(token)).set("socket", sessionId); } // 收到消息时触发 @Override public void handleTextMessage(String message) { // 这里处理收到的消息 System.out.println("收到消息:" + message); // 可以回复消息 sendMessage("服务端回复: " + message); } // 连接关闭时触发 @Override public void afterClose() { // 清理工作 } } ``` #### 1.4 发送消息给APP 在需要发送消息的地方,可以通过会话ID发送消息: ```java // 获取用户的会话ID(需要提前在连接时绑定) String sessionId = (String) StpUtil.getSessionByLoginId(userId).get("socket"); // 发送消息 SaSocketTemplate.sendMessage(sessionId, "要发送的消息内容"); ``` ### 步骤2:前端配置(Ruoyi-Vue) 在Ruoyi-Vue前端,可以使用WebSocket API或者第三方库(如SockJS)来连接WebSocket。由于APP是移动端,我们需要在APP中实现WebSocket客户端。 #### 2.1 在APP中实现WebSocket客户端 在APP中(Android使用WebSocket客户端库,如OkHttp的WebSocket;iOS使用URLSessionWebSocketTask)建立连接。 以Android(Kotlin)为例: ```kotlin val client = OkHttpClient() val request = Request.Builder() .url("ws://your-server-ip:8081") // WebSocket地址 .addHeader("token", "用户token") // 携带token .build() val webSocket = client.newWebSocket(request, object : WebSocketListener() { override fun onOpen(webSocket: WebSocket, response: Response) { // 连接功 } override fun onMessage(webSocket: WebSocket, text: String) { // 收到消息 runOnUiThread { // 更新UI,显示消息 } } override fun onClosed(webSocket: WebSocket, code: Int, reason: String) { // 连接关闭 } override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) { // 连接失败 } }) ``` ### 步骤3:Ruoyi-Vue发送消息给APP 在Ruoyi-Vue前端,可以通过调用后端接口,由后端通过WebSocket发送给APP。 例如,在Vue组件中: ```javascript // 调用后端接口发送消息 import request from '@/utils/request' export function sendMsgToApp(userId, message) { return request({ url: '/system/message/sendToApp', method: 'post', data: { userId, message } }) } ``` 后端创建接口: ```java @PostMapping("/sendToApp") public AjaxResult sendToApp(@RequestParam Long userId, @RequestParam String message) { // 根据userId获取该用户的WebSocket会话ID String sessionId = ...; // 从缓存或数据库中获取 SaSocketTemplate.sendMessage(sessionId, message); return AjaxResult.success(); } ``` ### 注意事项 1. **安全性**:连接WebSocket时需要进行身份认证(通过token)。 2. **会话管理**:需要将会话ID与用户ID绑定,以便定向发送消息。 3. **断线重连**:APP端需要实现断线重连机制。 4. **心跳机制**:维持长连接,避免断开。 ### 备选方案:使用HTTP长轮询 如果WebSocket实现复杂,也可以考虑使用HTTP长轮询。APP定期向后端请求消息,后端在有消息时返回,否则保持连接直到超时。 在Ruoyi-Vue-Plus中,可以创建一个消息队列(如使用Redis的List),APP轮询接口: ```java @GetMapping("/pollMessage") public AjaxResult pollMessage() { // 从Redis中获取该用户的消息 List<String> messages = redisTemplate.opsForList().range("user:msg:" + userId, 0, -1); // 清空已读消息 redisTemplate.delete("user:msg:" + userId); return AjaxResult.success(messages); } ``` APP端定时调用此接口(注意频率)。 ### 总结 推荐使用WebSocket实现实时通信。以上步骤提供了从后端配置到前端APP的实现思路。具体实现时,需要根据Ruoyi-Vue-Plus的版本和项目结构进行调整。 §§相关问题§§ 1. 如何保证WebSocket连接的安全性? 2. 在Ruoyi-Vue-Plus中如何集第三方推送服务? 3. 如何处理WebSocket连接断开和重连? 4. 如何实现消息的持久化存储(离线消息)?</think>### 配置 Ruoyi-APP 接收 Ruoyi-Vue 消息的实现方案 要实现 Ruoyi-APP 接收 Ruoyi-Vue 发送的消息,本质是建立前后端实时通信通道。根据 Ruoyi-Vue-Plus 框架特性,推荐以下两种主流方案: --- #### 方案 1:WebSocket 实时通信(推荐) **原理**:建立全双工通信通道,实现消息实时推送 **实现步骤**: 1. **后端配置(Ruoyi-Vue-Plus)** 在 `ruoyi-common` 模块添加依赖: ```xml <!-- pom.xml --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency> ``` 创建 WebSocket 配置类: ```java @Configuration @EnableWebSocket public class WebSocketConfig implements WebSocketConfigurer { @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { registry.addHandler(appMessageHandler(), "/ws/app") .setAllowedOrigins("*") .addInterceptors(new HttpSessionHandshakeInterceptor()); } @Bean public WebSocketHandler appMessageHandler() { return new AppMessageHandler(); } } ``` 创建消息处理器: ```java public class AppMessageHandler extends TextWebSocketHandler { private static final Map<String, WebSocketSession> sessions = new ConcurrentHashMap<>(); // 连接建立时绑定用户ID @Override public void afterConnectionEstablished(WebSocketSession session) { String userId = (String) session.getAttributes().get("userId"); sessions.put(userId, session); } // 接收前端消息 @Override protected void handleTextMessage(WebSocketSession session, TextMessage message) { // 处理APP发送的消息 } // 发送消息给APP public static void sendToApp(String userId, String message) { WebSocketSession session = sessions.get(userId); if(session != null && session.isOpen()) { session.sendMessage(new TextMessage(message)); } } } ``` 2. **前端(Ruoyi-Vue)发送消息** 在 Vue 组件中调用: ```javascript // 使用WebSocket发送消息 const ws = new WebSocket(`ws://${location.host}/ws/app?userId=${this.userId}`); ws.onopen = () => { ws.send(JSON.stringify({ type: "NOTIFICATION", content: "新订单提醒" })); }; ``` 3. **APP 端接收消息(Android 示例)** ```kotlin private val webSocketClient = OkHttpClient() fun connectWebSocket(userId: String) { val request = Request.Builder() .url("ws://your-server-ip:port/ws/app?userId=$userId") .build() webSocketClient.newWebSocket(request, object : WebSocketListener() { override fun onMessage(webSocket: WebSocket, text: String) { // 处理收到的消息 runOnUiThread { showNotification(text) } } }) } ``` --- #### 方案 2:HTTP 长轮询 + 消息队列 **适用场景**:需要消息持久化或兼容旧设备 **实现步骤**: 1. **后端消息存储** 在 `ruoyi-system` 模块创建消息表: ```sql CREATE TABLE sys_app_message ( message_id BIGINT PRIMARY KEY AUTO_INCREMENT, user_id BIGINT NOT NULL, content VARCHAR(500) NOT NULL, status CHAR(1) DEFAULT '0' COMMENT '0未读 1已读', create_time DATETIME ); ``` 2. **消息发送接口** ```java @PostMapping("/sendToApp") public AjaxResult sendToApp(@RequestBody AppMessage message) { // 消息入库(带用户ID) messageService.insertMessage(message); return AjaxResult.success("消息已发送"); } ``` 3. **APP 轮询接口** ```java @GetMapping("/pollMessages") public AjaxResult pollMessages(@RequestParam Long userId) { List<AppMessage> messages = messageService.selectUnread(userId); // 标记为已读 messages.forEach(msg -> messageService.markAsRead(msg.getMessageId())); return AjaxResult.success(messages); } ``` 4. **APP 端实现轮询** ```kotlin private val handler = Handler(Looper.getMainLooper()) private val pollRunnable = object : Runnable { override fun run() { apiService.pollMessages(userId).enqueue { response -> if(response.isSuccessful) { processMessages(response.body().data) } handler.postDelayed(this, 10000) // 每10秒轮询 } } } // 启动轮询 handler.post(pollRunnable) ``` --- ### 关键配置注意事项 1. **安全认证** 在 WebSocket 连接时校验 token: ```java // WebSocketConfig 中添加拦截器 registry.addHandler(handler, "/ws/app") .addInterceptors(new AuthInterceptor()); public class AuthInterceptor extends HttpSessionHandshakeInterceptor { @Override public boolean beforeHandshake(ServerHttpRequest request, ...) { String token = request.getHeaders().getFirst("Token"); if(!tokenService.verifyToken(token)) { throw new AuthenticationException("无效Token"); } return true; } } ``` 2. **消息格式规范** 推荐统一使用 JSON 格式: ```json { "msgId": "20231001_001", "msgType": "ORDER_UPDATE", "content": "订单状态已更新", "timestamp": 1696123456789, "extra": {"orderId": 12345} } ``` 3. **离线消息处理** 在消息表中增加字段: ```sql ALTER TABLE sys_app_message ADD COLUMN is_pushed BOOLEAN DEFAULT 0 COMMENT '是否已推送'; ``` --- ### 性能优化建议 1. **WebSocket 心跳机制** ```java // 服务端配置心跳 @Bean public ServletServerContainerFactoryBean createWebSocketContainer() { ServletServerContainerFactoryBean container = new ServletServerContainerFactoryBean(); container.setMaxSessionIdleTimeout(300000); // 5分钟超时 container.setAsyncSendTimeout(20000); // 20秒发送超时 return container; } ``` 2. **使用 Redis 发布订阅** 当集群部署时,通过 Redis 广播消息: ```java @Autowired private RedisTemplate<String, String> redisTemplate; public void sendToApp(String userId, String message) { redisTemplate.convertAndSend("app:msg:" + userId, message); } ``` 3. **APP 端省电策略** ```kotlin // Android 使用WorkManager定时轮询 val constraints = Constraints.Builder() .setRequiredNetworkType(NetworkType.CONNECTED) .build() val pollRequest = PeriodicWorkRequestBuilder<MessageWorker>( 15, TimeUnit.MINUTES) // 每15分钟 .setConstraints(constraints) .build() WorkManager.getInstance(context).enqueue(pollRequest) ``` --- ### 部署注意事项 1. **Nginx 反向代理** WebSocket 需要特殊配置: ```nginx location /ws/ { proxy_pass http://backend; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } ``` 2. **防火墙开放端口** 确保 APP 能访问到 WebSocket 端口(默认 80/443 或自定义端口) ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值