SpringBoot+netty-socketio实现服务器端消息推送
作者:ATwill... 发布时间:2023-11-15 06:14:31
标签:SpringBoot,netty-socketio,服务器端,推送
首先:因为工作需要,需要对接socket.io框架对接,所以目前只能使用netty-socketio。websocket是不支持对接socket.io框架的。
netty-socketio顾名思义他是一个底层基于netty'实现的socket。
在springboot项目中的集成,请看下面的代码
maven依赖
<dependency>
<groupId>com.corundumstudio.socketio</groupId>
<artifactId>netty-socketio</artifactId>
<version>1.7.11</version>
</dependency>
下面就是代码了
首先是配置参数
#socketio配置
socketio:
host: localhost
port: 9099
# 设置最大每帧处理数据的长度,防止他人利用大数据来攻击服务器
maxFramePayloadLength: 1048576
# 设置http交互最大内容长度
maxHttpContentLength: 1048576
# socket连接数大小(如只监听一个端口boss线程组为1即可)
bossCount: 1
workCount: 100
allowCustomRequests: true
# 协议升级超时时间(毫秒),默认10秒。HTTP握手升级为ws协议超时时间
upgradeTimeout: 1000000
# Ping消息超时时间(毫秒),默认60秒,这个时间间隔内没有接收到心跳消息就会发送超时事件
pingTimeout: 6000000
# Ping消息间隔(毫秒),默认25秒。客户端向服务器发送一条心跳消息间隔
pingInterval: 25000
上面的注释写的很清楚。下面是config代码
import com.corundumstudio.socketio.Configuration;
import com.corundumstudio.socketio.SocketConfig;
import com.corundumstudio.socketio.SocketIOServer;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/**
* kcm
*/
@Component
public class PushServer implements InitializingBean {
@Autowired
private EventListenner eventListenner;
@Value("${socketio.port}")
private int serverPort;
@Value("${socketio.host}")
private String serverHost;
@Value("${socketio.bossCount}")
private int bossCount;
@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;
@Override
public void afterPropertiesSet() throws Exception {
Configuration config = new Configuration();
config.setPort(serverPort);
config.setHostname(serverHost);
config.setBossThreads(bossCount);
config.setWorkerThreads(workCount);
config.setAllowCustomRequests(allowCustomRequests);
config.setUpgradeTimeout(upgradeTimeout);
config.setPingTimeout(pingTimeout);
config.setPingInterval(pingInterval);
SocketConfig socketConfig = new SocketConfig();
socketConfig.setReuseAddress(true);
socketConfig.setTcpNoDelay(true);
socketConfig.setSoLinger(0);
config.setSocketConfig(socketConfig);
SocketIOServer server = new SocketIOServer(config);
server.addListeners(eventListenner);
server.start();
System.out.println("启动正常");
}
}
在就是监听代码
import com.corundumstudio.socketio.AckRequest;
import com.corundumstudio.socketio.SocketIOClient;
import com.corundumstudio.socketio.annotation.OnConnect;
import com.corundumstudio.socketio.annotation.OnDisconnect;
import com.corundumstudio.socketio.annotation.OnEvent;
import org.apache.commons.lang3.StringUtils;
import org.bangying.auth.JwtSupport;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.UUID;
@Component
public class EventListenner {
@Resource
private ClientCache clientCache;
@Resource
private JwtSupport jwtSupport;
/**
* 客户端连接
*
* @param client
*/
@OnConnect
public void onConnect(SocketIOClient client) {
String userId = client.getHandshakeData().getSingleUrlParam("userId");
// userId = jwtSupport.getApplicationUser().getId().toString();
// userId = "8";
UUID sessionId = client.getSessionId();
clientCache.saveClient(userId, sessionId, client);
System.out.println("建立连接");
}
/**
* 客户端断开
*
* @param client
*/
@OnDisconnect
public void onDisconnect(SocketIOClient client) {
String userId = client.getHandshakeData().getSingleUrlParam("userId");
if (StringUtils.isNotBlank(userId)) {
clientCache.deleteSessionClient(userId, client.getSessionId());
System.out.println("关闭连接");
}
}
//消息接收入口,当接收到消息后,查找发送目标客户端,并且向该客户端发送消息,且给自己发送消息
// 暂未使用
@OnEvent("messageevent")
public void onEvent(SocketIOClient client, AckRequest request) {
}
}
本地缓存信息
import com.corundumstudio.socketio.SocketIOClient;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
/**
* kcm
*/
@Component
public class ClientCache {
//本地缓存
private static Map<String, HashMap<UUID, SocketIOClient>> concurrentHashMap=new ConcurrentHashMap<>();
/**
* 存入本地缓存
* @param userId 用户ID
* @param sessionId 页面sessionID
* @param socketIOClient 页面对应的通道连接信息
*/
public void saveClient(String userId, UUID sessionId,SocketIOClient socketIOClient){
if(StringUtils.isNotBlank(userId)){
HashMap<UUID, SocketIOClient> sessionIdClientCache=concurrentHashMap.get(userId);
if(sessionIdClientCache==null){
sessionIdClientCache = new HashMap<>();
}
sessionIdClientCache.put(sessionId,socketIOClient);
concurrentHashMap.put(userId,sessionIdClientCache);
}
}
/**
* 根据用户ID获取所有通道信息
* @param userId
* @return
*/
public HashMap<UUID, SocketIOClient> getUserClient(String userId){
return concurrentHashMap.get(userId);
}
/**
* 根据用户ID及页面sessionID删除页面链接信息
* @param userId
* @param sessionId
*/
public void deleteSessionClient(String userId,UUID sessionId){
concurrentHashMap.get(userId).remove(sessionId);
}
}
下面是存储客户端连接信息
import com.corundumstudio.socketio.SocketIOClient;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
/**
* kcm
*/
@Component
public class ClientCache {
//本地缓存
private static Map<String, HashMap<UUID, SocketIOClient>> concurrentHashMap=new ConcurrentHashMap<>();
/**
* 存入本地缓存
* @param userId 用户ID
* @param sessionId 页面sessionID
* @param socketIOClient 页面对应的通道连接信息
*/
public void saveClient(String userId, UUID sessionId,SocketIOClient socketIOClient){
if(StringUtils.isNotBlank(userId)){
HashMap<UUID, SocketIOClient> sessionIdClientCache=concurrentHashMap.get(userId);
if(sessionIdClientCache==null){
sessionIdClientCache = new HashMap<>();
}
sessionIdClientCache.put(sessionId,socketIOClient);
concurrentHashMap.put(userId,sessionIdClientCache);
}
}
/**
* 根据用户ID获取所有通道信息
* @param userId
* @return
*/
public HashMap<UUID, SocketIOClient> getUserClient(String userId){
return concurrentHashMap.get(userId);
}
/**
* 根据用户ID及页面sessionID删除页面链接信息
* @param userId
* @param sessionId
*/
public void deleteSessionClient(String userId,UUID sessionId){
concurrentHashMap.get(userId).remove(sessionId);
}
}
控制层推送方法
@RestController
@RequestMapping("/push")
public class PushController {
@Resource
private ClientCache clientCache;
@Autowired
private JwtSupport jwtSupport;
@GetMapping("/message")
public String pushTuUser(@Param("id") String id){
Integer userId = jwtSupport.getApplicationUser().getId();
HashMap<UUID, SocketIOClient> userClient = clientCache.getUserClient(String.valueOf(userId));
userClient.forEach((uuid, socketIOClient) -> {
//向客户端推送消息
socketIOClient.sendEvent("chatevent","服务端推送消息");
});
return "success";
}
}
来源:https://blog.csdn.net/kang649882/article/details/104840441/
0
投稿
猜你喜欢
- Java 15 在 2020 年 9 月发布,虽然不是长久支持版本,但是也带来了 14 个新功能,这些新功能中有不少是十分实用的。Java
- 前言RxJava 在 GitHub 主页上的自我介绍是 "a library for composing asynchronous
- 1 前言任何一门语言都需要基本的流程控制语句,其思想也符合人类判断问题或做事的逻辑过程。什么是流程控制呢?流程就是做一件事情的顺序,或者说是
- 知识点:1.使用SQL Helper创建数据库2.数据的增删查改(PRDU:Put、Read、Delete、Update)背景知识:上篇文章
- jmap命令可以打印java进程的JVM堆信息,今天在某台机器上运行该命令查看 19560进程的堆信息jmap -heap 19560出现以
- Web UI项目中, 很多 Spring controller 视图函数直接返回 html 页面, 还有一些视图函数是要重定向或转发到其他的
- java 实现MD5加密算法的简单实例实现代码:import java.security.NoSuchAlgorithmException;
- 获取和释放 monitor 锁的时机本文我们研究下 synchronized 背后的 monitor 锁。我们都知道,最简单的同步方式就是利
- 项目结构项目路径可以自己定义,只要路径映射正确就可以pom.xml <properties> <spring.versio
- 前言如今多线程编程已成为了现代软件开发中的重要部分,而并发编程中的线程同步问题更是一道难以逾越的坎。在Java语言中,synchronize
- 要实现摇一摇的功能,类似于微信的摇一摇方法1:通过分析加速计数据来判断是否进行了摇一摇操作(比较复杂)方法2:iOS自带的Shake监控AP
- 1、一个示例回顾Future一些业务场景我们需要使用多线程异步执行任务,加快任务执行速度。JDK5新增了Future接口,用于描述一个异步计
- 【程序1】 题目:有1、2、3、4个数字,能组成多少个互不相同且无重复数字的三位数?都是多少? 1.程序分析:可填在百位、十位、个位的数字都
- 本文主要给大家介绍java的InputStream 流的使用。(1)FileInputstream: 子类,读取数据的通道使用步骤:1.获取
- 用了MyBatis的同行,应该见过foreach,它一般是这样用的:<select id="foreachTest"
- 一、简介Android的消息机制主要是指Handler的运行机制,那么什么是Handler的运行机制那?通俗的来讲就是,使用Handler将
- 记录一下微信第三方实现登录的方法。还是比较简单。一、必要的准备工作1.首先需要注册并被审核通过的微信开放平台帐号,然后创建一个移动应用,也需
- 前言本文给你提供在Spring Boot 应用程序中编写好的单元测试的机制,并且深入技术细节。我们将带你学习如何以可测试的方式创建Sprin
- PS:本文包含了大部分strings函数的说明,并附带举例说明。本来想自己整理一下的,发现已经有前辈整理过了,就转了过来。修改了原文一些源码
- 本文实例为大家分享了PropertyDescriptor反射调用set和get方法,供大家参考,具体内容如下第一段:package com.