SpringBoot实现WebSocket即时通讯的示例代码

目录
  • 1、引入依赖
  • 2、WebSocketConfig 开启WebSocket
  • 3、WebSocketServer
  • 4、测试连接发送和接收消息
  • 5、在线测试地址
  • 6、测试截图

1、引入依赖

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<dependency>
	<groupId>org.projectlombok</groupId>
	<artifactId>lombok</artifactId>
</dependency>
<dependency>
	<groupId>com.alibaba</groupId>
	<artifactId>fastjson</artifactId>
	<version>1.2.3</version>
</dependency>

2、WebSocketConfig 开启WebSocket

package com.shucha.deveiface.web.config;

/**
 * @author tqf
 * @Description
 * @Version 1.0
 * @since 2022-04-12 15:35
 */
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;

/**
 * 开启WebSocket
 */
@Configuration
public class WebSocketConfig {
    @Bean
    public ServerEndpointExporter serverEndpointExporter(){
        return new ServerEndpointExporter();
    }
}
 

3、WebSocketServer

package com.shucha.deveiface.web.ws;

/**
 * @author tqf
 * @Description
 * @Version 1.0
 * @since 2022-04-12 15:33
 */
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.WebSocketSession;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;

@Component
@ServerEndpoint("/webSocket/{userId}")
@Slf4j
public class WebSocketServer {
    private Session session;
    private String userId;
    /**静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。*/
    private static int onlineCount = 0;
    private static CopyOnWriteArraySet<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<>();

    /**
     * concurrent包的线程安全set,用来存放每个客户端对应的MyWebSocket对象
     */
    private static ConcurrentHashMap<String,WebSocketServer> webSocketMap = new ConcurrentHashMap();

    /**
     * 为了保存在线用户信息,在方法中新建一个list存储一下【实际项目依据复杂度,可以存储到数据库或者缓存】
     */
    private final static List<Session> SESSIONS = Collections.synchronizedList(new ArrayList<>());

    /**
     * 建立连接
     * @param session
     * @param userId
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("userId") String userId) {
        this.session = session;
        this.userId = userId;
        webSocketSet.add(this);
        SESSIONS.add(session);
        if (webSocketMap.containsKey(userId)) {
            webSocketMap.remove(userId);
            webSocketMap.put(userId,this);
        } else {
            webSocketMap.put(userId,this);
            addOnlineCount();
        }
        // log.info("【websocket消息】有新的连接, 总数:{}", webSocketSet.size());
        log.info("[连接ID:{}] 建立连接, 当前连接数:{}", this.userId, webSocketMap.size());
    }

    /**
     * 断开连接
     */
    @OnClose
    public void onClose() {
        webSocketSet.remove(this);
        if (webSocketMap.containsKey(userId)) {
            webSocketMap.remove(userId);
            subOnlineCount();
        }
        // log.info("【websocket消息】连接断开, 总数:{}", webSocketSet.size());
        log.info("[连接ID:{}] 断开连接, 当前连接数:{}", userId, webSocketMap.size());
    }

    /**
     * 发送错误
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error) {
        log.info("[连接ID:{}] 错误原因:{}", this.userId, error.getMessage());
        error.printStackTrace();
    }

    /**
     * 收到消息
     * @param message
     */
    @OnMessage
    public void onMessage(String message) {
        // log.info("【websocket消息】收到客户端发来的消息:{}", message);
        log.info("[连接ID:{}] 收到消息:{}", this.userId, message);
    }

    /**
     * 发送消息
     * @param message
     * @param userId
     */
    public void sendMessage(String message,Long userId) {
        WebSocketServer webSocketServer = webSocketMap.get(String.valueOf(userId));
        if (webSocketServer!=null){
            log.info("【websocket消息】推送消息, message={}", message);
            try {
                webSocketServer.session.getBasicRemote().sendText(message);
            } catch (Exception e) {
                e.printStackTrace();
                log.error("[连接ID:{}] 发送消息失败, 消息:{}", this.userId, message, e);
            }
        }
    }

    /**
     * 群发消息
     * @param message
     */
    public void sendMassMessage(String message) {
        try {
            for (Session session : SESSIONS) {
                if (session.isOpen()) {
                    session.getBasicRemote().sendText(message);
                    log.info("[连接ID:{}] 发送消息:{}",session.getRequestParameterMap().get("userId"),message);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取当前连接数
     * @return
     */
    public static synchronized int getOnlineCount() {
        return onlineCount;
    }

    /**
     * 当前连接数加一
     */
    public static synchronized void addOnlineCount() {
        WebSocketServer.onlineCount++;
    }

    /**
     * 当前连接数减一
     */
    public static synchronized void subOnlineCount() {
        WebSocketServer.onlineCount--;
    }

}

4、测试连接发送和接收消息

package com.shucha.deveiface.web.controller;

import com.alibaba.fastjson.JSONObject;
import com.shucha.deveiface.web.ws.WebSocketServer;
import lombok.Data;
import lombok.experimental.Accessors;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author tqf
 * @Description
 * @Version 1.0
 * @since 2022-04-12 15:44
 */
@RestController
@RequestMapping("/web")
public class TestWebSocket {
    @Autowired
    private WebSocketServer webSocketServer;

    /**
     * 消息发送测试
     */
    @GetMapping("/test")
    public void test(){
        for (int i=1;i<4;i++) {
            WebsocketResponse response = new WebsocketResponse();
            response.setUserId(String.valueOf(i));
            response.setUserName("姓名"+ i);
            response.setAge(i);
            webSocketServer.sendMessage(JSONObject.toJSONString(response), Long.valueOf(String.valueOf(i)));
        }
    }

    /**
     * 群发消息测试(给当前连接用户发送)
     */
    @GetMapping("/sendMassMessage")
    public void sendMassMessage(){
        WebsocketResponse response = new WebsocketResponse();
        response.setUserName("群发消息模板测试");
        webSocketServer.sendMassMessage(JSONObject.toJSONString(response));
    }

    @Data
    @Accessors(chain = true)
    public static class WebsocketResponse {
        private String userId;
        private String userName;
        private int age;
    }
}

5、在线测试地址

websocket 在线测试

6、测试截图

访问测试发送消息:http://localhost:50041//web/test

测试访问地址:ws://192.168.0.115:50041/webSocket/1   wss://192.168.0.115:50041/webSocket/2

到此这篇关于SpringBoot实现WebSocket即时通讯的示例代码的文章就介绍到这了,更多相关SpringBoot WebSocket即时通讯内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 教你在Spring Boot微服务中集成gRPC通讯的方法

    一.首先声明gRPC接口 这里引入的是最新的gRpc-core 1.37版本, 采用的grcp-spring-boot-starter封装的版本进行实现,github地址: https://github.com/yidongnan/grpc-spring-boot-starter 要实现gRpc通讯, 先定义接口以及入参出参信息 syntax = "proto3"; option java_multiple_files = true; option java_package = &qu

  • SpringBoot实现WebSocket即时通讯的示例代码

    目录 1.引入依赖 2.WebSocketConfig 开启WebSocket 3.WebSocketServer 4.测试连接发送和接收消息 5.在线测试地址 6.测试截图 1.引入依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency>

  • NodeJs 实现简单WebSocket即时通讯的示例代码

    服务器的实现很简单,先装一个nodeJs的模块,叫nodejs-websocket , 直接在nodeJs命令行中敲入:npm install nodejs-websocket回车就可以安装好了,然后就可以开始建立服务器了,因为有了nodejs-websocket模块,所以很多工作都不用我们自己做,直接调用别人封装好的方法就行了: 服务端代码 根据客户端传来的消息判断哪个是game1,哪个是game2,保存connection对象. var ws = require("nodejs-websoc

  • koa socket即时通讯的示例代码

    前言 http的特点是一问一答,而即时通讯是需要双向通信的,这样以前的即时通信只能使用轮询的方式通过周期性的ajax请求获取数据,直到websocket出现,就完美实现了双向通信 一 即时通讯方式简介 段轮询 前台使用setInterval进行定时请求后台,这样无疑非常浪费性能 长轮询和长连接(html5的EventSource) 客服端连接一次,服务端不断开连接,服务端接收到新消息就发送给前台,客服端和服务端保持一直连接,缺点是只有服务端向客服端输出 websocket websocket不再

  • NetCore WebSocket即时通讯示例

    NetCore WebSocket 即时通讯示例,供大家参考,具体内容如下 1.新建Netcore Web项目 2.创建简易通讯协议 public class MsgTemplate { public string SenderID { get; set; } public string ReceiverID { get; set; } public string MessageType { get; set; } public string Content { get; set; } } Se

  • nodejs结合Socket.IO实现websocket即时通讯

    目录 为什么要用 websocket Socket.io 开源项目 效果预览 app.js index.html 为什么要用 websocket websocket 是一种网络通信协议,一般用来进行实时通信会使用到. websocket 协议和 http 协议类似,http 协议有一个缺陷,只能由客户方端发起请求,服务端根据请求 url 和传过去的参数返回对应结果 websocket 是双向通信的,只要 websocket 连接建立起来,可以由客户端给服务端发送数据,也可以由服务端主动给客户端发

  • SpringBoot实现扫码登录的示例代码

    目录 一.首先咱们需要一张表 二.角色都有哪些 三.接口都需要哪些? 四.步骤 五.疯狂贴代码 SpringBoot中操作WebSocket 最近有个项目涉及到websocket实现扫码登录,看到一篇不错的技术文,分享一下. 一.首先咱们需要一张表 这表是干啥的呢?就是记录一下谁扫码了.谁登录了. User_Token表 字段如下: uuid : 用于确保唯一性 userId :谁登录的 loginTime :登录时间 createTime :创建时间 用于判断是否过期 state:是否二维码失

  • Python3 socket即时通讯脚本实现代码实例(threading多线程)

    Python 提供了两个级别访问的网络服务.: 低级别的网络服务支持基本的 Socket,它提供了标准的 BSD Sockets API,可以访问底层操作系统Socket接口的全部方法. 高级别的网络服务模块 SocketServer, 它提供了服务器中心类,可以简化网络服务器的开发. ------------------------------------------------服务端代码-------------------------------------- __author__ = "

  • springboot 使用自定义的aspect的示例代码

    对某个类型中的方法进行拦截,然后加入固定的业务逻辑,这是AOP面向切面编程可以做的事,在springboot里实现aop的方法也有很多, spring-boot-starter-aop 或者 aspectjweaver 都是可以实现的,不过我们在实现之前,先来看一下aop里的几个概念. 概念 切面(Aspect):是指横切多个对象的关注点的一个模块化,事务管理就是J2EE应用中横切关注点的很好示例.在Spring AOP中,切面通过常规类(基本模式方法)或者通过使用了注解@Aspect的常规类来

  • SpringBoot 签到奖励实现方案的示例代码

    前言 最近在做社交业务,用户进入APP后有签到功能,签到成功后获取相应的奖励: 项目状况:前期尝试业务阶段: 特点: 快速实现(不需要做太重,满足初期推广运营即可) 快速投入市场去运营 用户签到: 用户在每次启动时查询签到记录(规则:连续7日签到从0开始,签到过程中有断签从0开始) 如果今日未签到则提示用户可以进行签到 用户签到获取相应的奖励 提到签到,脑海中首先浮现特点: 需要记录每位用户每天的签到情况 查询时根据规则进行签到记录情况 需求&流程设计&技术实现方案 需求原型图 查询签到记

  • Springboot实现Shiro整合JWT的示例代码

    写在前面 之前想尝试把JWT和Shiro结合到一起,但是在网上查了些博客,也没太有看懂,所以就自己重新研究了一下Shiro的工作机制,然后自己想了个(傻逼)办法把JWT和Shiro整合到一起了 另外接下来还会涉及到JWT相关的内容,我之前写过一篇博客,可以看这里:Springboot实现JWT认证 Shiro的Session机制 由于我的方法是改变了Shiro的默认的Session机制,所以这里先简单讲一下Shiro的机制,简单了解Shiro是怎么确定每次访问的是哪个用户的 Servlet的Se

随机推荐