springboot集成socketIo,实现webSocket

之前都是使用http接口请求,最近有用到WebSocket的场景,客户端之间长连接通讯,记录一下spring boot整合socketIO的过程。

  1. 国际惯例,引入依赖
    在这里插入图片描述
  2. application.yml(或者是application.properties)配置文件添加socketIo配置
    在这里插入图片描述
  3. 添加socketIoConfig配置类
@Configuration
public class SocketConfig {
    private static final Logger logger = LoggerFactory.getLogger(SocketConfig.class);
    @Value("${socketIo.host}")
    private String host;
    @Value("${socketIo.port}")
    private Integer port;
    @Value("${socketIo.workCount}")
    private int workCount;
    @Value("${socketIo.allowCustomRequests}")
    private boolean allowCustomRequests;
    @Value("${socketIo.upgradeTimeout}")
    private int upgradeTimeout;
    @Value("${socketIo.pingTimeout}")
    private int pingTimeout;
    @Value("${socketIo.pingInterval}")
    private int pingInterval;
    @Value("${socketIo.maxFramePayloadLength}")
    private int maxFramePayloadLength;
    @Value("${socketIo.maxHttpContentLength}")
    private int maxHttpContentLength;
    
    /**SocketIOServer配置*/
    @Bean("socketIOServer")
    public SocketIOServer socketIOServer() {
        com.corundumstudio.socketio.Configuration config = new com.corundumstudio.socketio.Configuration();
        //配置host
        config.setHostname(host);
        //配置端口
        config.setPort(port);
        //开启Socket端口复用
        com.corundumstudio.socketio.SocketConfig socketConfig = new com.corundumstudio.socketio.SocketConfig();
        socketConfig.setReuseAddress(true);
        config.setSocketConfig(socketConfig);
        //连接数大小
        config.setWorkerThreads(workCount);
        //允许客户请求
        config.setAllowCustomRequests(allowCustomRequests);
        //协议升级超时时间(毫秒),默认10秒,HTTP握手升级为ws协议超时时间
        config.setUpgradeTimeout(upgradeTimeout);
        //Ping消息超时时间(毫秒),默认60秒,这个时间间隔内没有接收到心跳消息就会发送超时事件
        config.setPingTimeout(pingTimeout);
        //Ping消息间隔(毫秒),默认25秒。客户端向服务器发送一条心跳消息间隔
        config.setPingInterval(pingInterval);
        //设置HTTP交互最大内容长度        config.setMaxHttpContentLength(maxHttpContentLength);
        //设置最大每帧处理数据的长度,防止他人利用大数据来攻击服务器       config.setMaxFramePayloadLength(maxFramePayloadLength);
        config.setTransports(Transport.POLLING, Transport.WEBSOCKET);
        /**config.setOrigin("*");*/
        return new SocketIOServer(config);
    }
	/**开启SocketIOServer注解支持*/
    @Bean
    public SpringAnnotationScanner springAnnotationScanner(SocketIOServer socketServer) {
        return new SpringAnnotationScanner(socketServer);
    }
}
  1. 添加消息主体实体
@Data
@ToString
public class MessageDto extends BaseEntity{
    /**源客户端用户名*/
    private String sourceUserName;

    /**目标客户端用户名-入参*/
    private String targetRoom;

    /**消息类型*/
    private String msgType;

    /**消息内容*/
    private String msgContent;

    /**空构造方法*/
    public MessageDto() {
    }

    /**
     * 构造方法
     * @param sourceUserName 发起client
     * @param targetRoom 目标room
     * @param msgType 消息类型
     * @param msgContent 消息内容
     */
    public MessageDto(String sourceUserName, String targetRoom, String msgType, String msgContent) {
        this.sourceUserName = sourceUserName;
        this.targetRoom = targetRoom;
        this.msgType = msgType;
        this.msgContent = msgContent;
    }

    /**
     * json解析构造方法
     * @param messageJson json字符串
     * @throws Exception 异常
     */
    public MessageDto(String messageJson) throws Exception{
        MessageDto messageDto = new ObjectMapper().readValue(messageJson, MessageDto.class);
        this.sourceUserName = messageDto.getSourceUserName();
        this.targetRoom = messageDto.getTargetRoom();
        this.msgType = messageDto.getMsgType();
        this.msgContent = messageDto.getMsgContent();
    }
}
  1. socketHandler

socketHandler内包含socket的connect、disconnect、event及message等信息。

  • clientMap<String,List>是ConcurrentHashMap类,key为roomId,value为sessionId的list集合。用于存room(房间)空间内的所有client对应的sessionID。
  • OnConnect
    在这里插入图片描述
    OnConnect是客户端连接webSocket的触发事件,可以做校验、clientMap的put等。
  • OnDisconnect
    在这里插入图片描述
    客户端断开连接是调用,刷新客户端信息。
  • OnEvent
    在这里插入图片描述
    用于监听客户端emit的事件,并发送事件sendEvent。
  1. 模拟客户端,代码如下:
public static void main(String[] args) {
        //服务端socket.io连接通信地址
        String url = "http://127.0.0.1:8083";
        try {
            IO.Options options = new IO.Options();
            options.transports = new String[]{"websocket"};
            options.reconnectionAttempts = 2;
            //失败重连的时间间隔
            options.reconnectionDelay = 1000;
            //连接超时时间(ms)
            options.timeout = 500;
            //userId: 唯一标识 传给服务端存储
            final Socket socket = IO.socket(url + "?userName=dong&appKey=abc-56&roomId=abc-56-1", options);
            socket.on(Socket.EVENT_CONNECT, args1 -> System.out.println(JSON.toJSONString(args1)));
            socket.on("ewsSocketMsg", objects -> System.out.println("服务端dong:" + objects[0].toString()));
            socket.on("ewsAllClientsMsg", objects -> System.out.println("服务端dong:" + objects[0].toString()));
            socket.connect();

            while (true) {
                Thread.sleep(10000);
                //自定义事件`push_data_event` -> 向服务端发送消息
                MessageDto messageDto = new MessageDto();
                messageDto.setSourceUserName("lipenghui");
                messageDto.setTargetRoom("abc-56-1");
                messageDto.setMsgType("2");
                messageDto.setMsgContent("ceshi guangbo");
                socket.emit("ewsSocketMsg", JSON.toJSONString(messageDto));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

整理完毕!

### 集成Netty-SocketIO实现Spring Boot中的实时通信 在Spring Boot项目中集成Netty-SocketIO可以有效支持WebSocket协议,从而实现实时双向通信。这不仅限于简单的消息推送,还可以用于构建聊天应用、在线游戏或其他任何需要低延迟交互的应用场景。 #### 添加依赖项 要在Spring Boot应用程序中使用Netty-SocketIO,首先需引入必要的Maven或Gradle依赖: 对于Maven配置文件`pom.xml`应加入如下内容[^1]: ```xml <dependency> <groupId>com.corundumstudio.socketio</groupId> <artifactId>netty-socketio</artifactId> <version>2.0.7</version> </dependency> ``` 而对于采用Gradle构建工具,则应在`build.gradle`里添加: ```groovy implementation 'com.corundumstudio.socketio:netty-socketio:2.0.7' ``` #### 初始化Socket.IO服务器实例 创建一个新的Java类来启动并配置Socket.IO服务端口监听器。通常情况下会将其设置为与现有HTTP(S)服务器不同的端口号运行,以便区分两者之间的流量。 下面是一个基本的例子展示如何初始化一个Socket.IO Server对象,并指定其绑定地址以及端口等参数: ```java import com.corundumstudio.socketio.SocketIOServer; // ... other imports ... @Configuration public class SocketIoConfig { @Bean public SocketIOServer socketIOServer() { Configuration config = new Configuration(); config.setHostname("localhost"); config.setPort(9092); return new SocketIOServer(config); } } ``` #### 处理连接事件 通过定义特定的方法处理客户端发起的不同类型的请求(如建立连接、断开连接),这些方法可以通过注解的形式注册到相应的处理器上。例如,在接收到新的客户端连接时触发某些逻辑操作;当某个已存在的连接被关闭时执行清理工作等等。 ```java @EventListener(ApplicationReadyEvent.class) public void startListeningForEvents() throws InterruptedException, ExecutionException, TimeoutException { socketIOServer.addEventListener("chat message", ChatMessage.class, (client, data, ackRequest) -> { System.out.println("received chat message from client " + client.getSessionId().toString()); // Broadcast the received message to all connected clients. socketIOServer.getBroadcastOperations().sendEvent("chat message", data); }); socketIOServer.start(); Runtime.getRuntime().addShutdownHook(new Thread(() -> { try { socketIOServer.stop(); } catch (IOException e) { throw new RuntimeException(e); } })); } ``` 以上代码片段展示了如何监听来自前端发送过来的消息事件(`chat message`)并将之广播给所有当前处于活动状态下的订阅者们。 #### 启动Spring Boot应用 完成上述配置之后就可以正常编译打包部署该程序了。如果一切顺利的话,现在应该可以在浏览器控制台或者其他测试工具里面尝试向这个新搭建起来的服务发送一些简单的JSON格式的数据包来进行初步验证[^2]。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冰红茶不会渴

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值