栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

【SpringBoot学习】43、SpringBoot 使用 Uniapp 集成 Websocket 实现消息推送

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【SpringBoot学习】43、SpringBoot 使用 Uniapp 集成 Websocket 实现消息推送

文章目录
  • SpringBoot 使用 Uniapp 集成 Websocket 实现消息推送
    • 1、SpringBoot 配置
      • (1)依赖配置
      • (2)Websocket 配置
      • (3)测试控制层
      • (4)服务端业务主动发送消息
    • 2、Uniapp 配置
    • 3、生产环境 Nginx 配置
  • 微信公众号

SpringBoot 使用 Uniapp 集成 Websocket 实现消息推送 1、SpringBoot 配置 (1)依赖配置

导入依赖,一样的 stater,这里就不多概述了

        
            org.springframework.boot
            spring-boot-starter-websocket
        
(2)Websocket 配置

websocket 的配置

package com.ruoyi.business.common.websocket;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;


@Configuration
public class WebSocketConfig {

    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }
}

WebSocket 服务端

package com.ruoyi.business.common.websocket;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;


@Slf4j
@Component
@ServerEndpoint("/open/webSocket/{userId}")
public class WebSocketServer {

    
    private static int onlineCount = 0;
    
    private static ConcurrentHashMap webSocketMap = new ConcurrentHashMap<>();
    
    private Session session;
    
    private String userId = "";

    
    @OnOpen
    public void onOpen(Session session, @PathParam("userId") String userId) {
        this.session = session;
        this.userId = userId;
        if (webSocketMap.containsKey(userId)) {
            webSocketMap.remove(userId);
            //加入set中
            webSocketMap.put(userId, this);
        } else {
            //加入set中
            addOnlineCount();
            webSocketMap.put(userId, this);
        }
        log.info("用户连接:" + userId + ",当前在线人数为:" + getOnlineCount());
    }

    
    @OnClose
    public void onClose() {
        if (webSocketMap.containsKey(userId)) {
            webSocketMap.remove(userId);
            //从set中删除
            subOnlineCount();
        }
        log.info("用户退出:" + userId + ",当前在线人数为:" + getOnlineCount());
    }

    
    @OnMessage
    public void onMessage(String message, Session session) {
        //log.info("收到客户端消息:" + userId + ",报文:" + message);
        //可以群发消息
        //消息保存到数据库、redis
        
    }


    
    @OnError
    public void onError(Session session, Throwable error) {
        log.error("用户错误:" + this.userId + ",原因:" + error.getMessage());
        error.printStackTrace();
    }

    
    public void sendMessage(String message) {
        try {
            this.session.getBasicRemote().sendText(message);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    
    public static void sendInfo(String userId, String message) {
        log.info("发送消息到:" + userId + ",报文:" + message);
        if (StringUtils.isNotBlank(userId) && webSocketMap.containsKey(userId)) {
            webSocketMap.get(userId).sendMessage(message);
        } else {
            log.error("用户" + userId + ",不在线!");
        }
    }

    
    public static synchronized int getOnlineCount() {
        return onlineCount;
    }

    
    public static synchronized void addOnlineCount() {
        WebSocketServer.onlineCount++;
    }

    
    public static synchronized void subOnlineCount() {
        WebSocketServer.onlineCount--;
    }
}
(3)测试控制层
package com.ruoyi.business.common.websocket;

import com.ruoyi.common.core.domain.AjaxResult;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;


@RestController
@RequestMapping("/open/webSocket")
public class WebSocketController {

    @ApiOperation("测试通讯")
    @GetMapping("/test/{userId}/{message}")
    public AjaxResult test(@PathVariable("userId") String userId, @PathVariable("message") String message) {
        WebSocketServer.sendInfo(userId, message);
        return AjaxResult.success("发送成功");
    }
}

请求地址/open 开头,是配置了权限拦截放开

(4)服务端业务主动发送消息

需要推送消息的地方使用 sendMessage 带用户 ID 的方法即可

// 推送消息
        WebSocketServer.sendInfo(String.valueOf(storeInfo.getStoreUserId()), "您有新的职工订单,请及时配送");
2、Uniapp 配置

登录成功,初始化连接 websocket,退出的时候,也需要关闭 websocket,要不然推送消息接收不到

 request.connectionWebSocket();

封装的方法,其中 onSocketOpen 中有一个 setInterval 定时器 sendSocketMessage 发送消息到服务端,因为 websocket 默认时间为一分钟就会自动断开连接,所以需要实时通讯,保证 websocket 是在线状态

缓存中存放的 webSocketOnLine 状态,是在页面上显示消息是否在线的判断依据,页面定时获取这个状态显示在页面上即可,即实时更新消息状态是否在线

function connectionWebSocket() {
    let user = uni.getStorageSync(config.cachePrefix + 'user');
    if (validator.isEmpty(user)) {
        return;
    }
    //连接
    uni.connectSocket({
        url: config.wsUrl + user.userId,
    });
    //打开websocket回调
    uni.onSocketOpen(function (res) {
        uni.setStorageSync(config.cachePrefix + 'webSocketOnLine', true);
        showMsg('消息连接成功');
        //每隔5秒钟发送一次心跳,避免websocket连接因超时而自动断开
        setInterval(function () {
            uni.sendSocketMessage({
                data: '心跳检测'
            });
        }, 5 * 1000);
    });
    //连接失败回调
    uni.onSocketError(function (res) {
        uni.setStorageSync(config.cachePrefix + 'webSocketOnLine', false);
        showMsg('消息连接失败');
    });
    //关闭websocket打印
    uni.onSocketClose(function (res) {
        uni.setStorageSync(config.cachePrefix + 'webSocketOnLine', false);
        showMsg('消息连接已关闭');
    });
    //服务端过来内容之后打印
    uni.onSocketMessage(function (res) {
        console.log(res);
        showMsg(res.data);
        speekText(res.data);
    });
}

退出系统或者关闭界面时,需要关闭 websocket,要不然即使用户 ID 在线,也接收不到消息

uni.closeSocket();
3、生产环境 Nginx 配置

生产环境部署,websocket 必须加上代理配置,这样 Nginx 才能正确转发 websocket 的通讯

		location /project-service {
			# websocket 必须加上的配置
			proxy_set_header Upgrade $http_upgrade;
			proxy_set_header Connection "upgrade";
		}

如果你的服务器是通过 https 访问的, 则 websocket 访问地址同样也需要从 ws 修改为 wss

	baseUrl: 'http://192.168.3.6:8080/project-service',
	wsUrl: 'ws://192.168.3.6:8080/project-service/open/webSocket/',

上面两个配置,在服务器开启了 https 的前提下,需要讲 http 修改为 https,wx 修改为 wss

到此 SpringBoot 使用 Uniapp 集成 Websocket 实现消息推送,OK

微信公众号

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/852473.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号