范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

SpringBoot整合Socket实战案例,实现单点群发,1对1,1对多

  作者:小目标青年
  来源:https://blog.csdn.net/qq_35387940  本篇内容:
  后端 + 前端简单HTML页面 功能场景点:群发,所有人都能收到 局部群发,部分人群都能收到 单点推送, 指定某个人的页面
  惯例,先看看本次实战示例项目结构:
  可以看到内容不多,也就是说,springboot 整合socket, 跟着我学,轻轻松松。
  不多说,开始: ① pom引入核心依赖              com.alibaba         fastjson         1.2.75                   com.corundumstudio.socketio         netty-socketio         1.7.7                   org.springframework.boot         spring-boot-starter-web                   org.springframework.boot         spring-boot-starter-test         test       ② yml加上配置项server:   port: 8089   socketio:    host: localhost    port: 8503    maxFramePayloadLength: 1048576    maxHttpContentLength: 1048576    bossCount: 1    workCount: 100    allowCustomRequests: true    upgradeTimeout: 10000    pingTimeout: 60000    pingInterval: 25000 ③ 创建socket配置加载类 MySocketConfig.javaimport com.corundumstudio.socketio.SocketConfig; import com.corundumstudio.socketio.SocketIOServer; import com.corundumstudio.socketio.annotation.SpringAnnotationScanner; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;   /**  * @Author: JCccc  * @Description:  * @Date: 2022/06/13 21:50  */ @Configuration public class MySocketConfig{       @Value("${socketio.host}")     private String host;       @Value("${socketio.port}")     private Integer port;       @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;       @Bean     public SocketIOServer socketIOServer() {         SocketConfig socketConfig = new SocketConfig();         socketConfig.setTcpNoDelay(true);         socketConfig.setSoLinger(0);         com.corundumstudio.socketio.Configuration config = new com.corundumstudio.socketio.Configuration();         buildSocketConfig(socketConfig, config);         return new SocketIOServer(config);     }       /**      * 扫描netty-socketIo的注解( @OnConnect、@OnEvent等)      */     @Bean     public SpringAnnotationScanner springAnnotationScanner() {         return new SpringAnnotationScanner(socketIOServer());     }       private void buildSocketConfig(SocketConfig socketConfig, com.corundumstudio.socketio.Configuration config) {         config.setSocketConfig(socketConfig);         config.setHostname(host);         config.setPort(port);         config.setBossThreads(bossCount);         config.setWorkerThreads(workCount);         config.setAllowCustomRequests(allowCustomRequests);         config.setUpgradeTimeout(upgradeTimeout);         config.setPingTimeout(pingTimeout);         config.setPingInterval(pingInterval);     } } ④创建消息实体 MyMessage.java/**  * @Author: JCccc  * @Date: 2022-07-23 9:05  * @Description:  */ public class MyMessage {       private String type;       private String content;       private String from;       private String to;       private String channel;         public String getType() {         return type;     }       public void setType(String type) {         this.type = type;     }       public String getContent() {         return content;     }       public void setContent(String content) {         this.content = content;     }       public String getFrom() {         return from;     }       public void setFrom(String from) {         this.from = from;     }       public String getTo() {         return to;     }       public void setTo(String to) {         this.to = to;     }       public String getChannel() {         return channel;     }       public void setChannel(String channel) {         this.channel = channel;     } }
  代码简析:
  ⑤创建 socket handler 负责记录客户端 连接、下线
  MySocketHandler.java import com.corundumstudio.socketio.SocketIOClient; import com.corundumstudio.socketio.SocketIOServer; import com.corundumstudio.socketio.annotation.OnConnect; import com.corundumstudio.socketio.annotation.OnDisconnect; import com.socket.mysocket.util.SocketUtil; import org.springframework.beans.factory.annotation.Autowired; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component;     /**  * @Author: JCccc  * @Description:  * @Date: 2022/6/23 21:21  */ @Component public class MySocketHandler {     private final Logger log = LoggerFactory.getLogger(this.getClass());     @Autowired     private SocketIOServer socketIoServer;     @PostConstruct     private void start(){         try {             socketIoServer.start();         }catch (Exception e){             e.printStackTrace();         }     }     @PreDestroy     private void destroy(){         try {         socketIoServer.stop();         }catch (Exception e){             e.printStackTrace();         }     }     @OnConnect     public void connect(SocketIOClient client) {         String userFlag = client.getHandshakeData().getSingleUrlParam("userFlag");         SocketUtil.connectMap.put(userFlag, client);         log.info("客户端userFlag: "+ userFlag+ "已连接");     }     @OnDisconnect     public void onDisconnect(SocketIOClient client) {         String userFlag = client.getHandshakeData().getSingleUrlParam("userFlag");         log.info("客户端userFlag:" + userFlag + "断开连接");         SocketUtil.connectMap.remove(userFlag, client);     } }
  代码简析:
  ⑥ 封装的socket 小函数
  SocketUtil.java import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.corundumstudio.socketio.AckRequest; import com.corundumstudio.socketio.SocketIOClient; import com.corundumstudio.socketio.annotation.OnEvent; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils;   import java.util.Map; import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap;   /**  * @Author: JCccc  * @Description:  * @Date: 2022/6/23 21:28  */ @Component public class SocketUtil {       private final Logger log = LoggerFactory.getLogger(this.getClass());       //暂且把用户&客户端信息存在缓存     public static ConcurrentMap connectMap = new ConcurrentHashMap<>();       @OnEvent(value = "CHANNEL_SYSTEM")     public void systemDataListener(String receiveMsg) {         if (!StringUtils.hasLength(receiveMsg)){             return;         }         JSONObject msgObject = (JSONObject) JSON.parse(receiveMsg);         String userFlag = String.valueOf(msgObject.get("from"));         String content = String.valueOf(msgObject.get("content"));         log.info("收到用户 : {} 推送到系统频道的一条消息 :{}",userFlag,content );     }       public void sendToAll(Map msg,String sendChannel) {         if (connectMap.isEmpty()){             return;         }         //给在这个频道的每个客户端发消息         for (Map.Entry entry : connectMap.entrySet()) {             entry.getValue().sendEvent(sendChannel, msg);         }     }       public void sendToOne(String userFlag, Map msg,String sendChannel) {         //拿出某个客户端信息         SocketIOClient socketClient = getSocketClient(userFlag);         if (Objects.nonNull(socketClient) ){             //单独给他发消息             socketClient.sendEvent(sendChannel,msg);         }     }         /**      * 识别出客户端      * @param userFlag      * @return      */     public SocketIOClient getSocketClient(String userFlag){         SocketIOClient client = null;         if (StringUtils.hasLength(userFlag) &&  !connectMap.isEmpty()){             for (String key : connectMap.keySet()) {                 if (userFlag.equals(key)){                     client = connectMap.get(key);                 }             }         }         return client;     } }
  代码简析:
  ⑦写1个接口,模拟场景,前端页面调用后端接口,做消息推送
  TestController.java import com.socket.mysocket.dto.MyMessage; import com.socket.mysocket.util.SocketUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*;   import java.util.HashMap; import java.util.Map;   /**  * @Author: JCccc  * @Description:  * @Date: 2022/06/13 21:50  */ @RestController public class TestController {     public final static String SEND_TYPE_ALL = "ALL";     public final static String SEND_TYPE_ALONE = "ALONE";     @Autowired     SocketUtil socketUtil;       @PostMapping("/testSendMsg")     public String testSendMsg(@RequestBody MyMessage myMessage){         Map map = new HashMap<>();         map.put("msg",myMessage.getContent());           //群发         if (SEND_TYPE_ALL.equals(myMessage.getType())){             socketUtil.sendToAll( map,myMessage.getChannel());             return "success";         }         //指定单人         if (SEND_TYPE_ALONE.equals(myMessage.getType())){             socketUtil.sendToOne(myMessage.getTo(), map, myMessage.getChannel());             return "success";         }           return "fail";     } }
  代码简析:
  好了,7步了。一切已经就绪了。 前端简单页面
  接下来搞点前端HTML页面, 玩一玩看看效果:
  第一个页面:
  TestClientStudentJC.html             我要连SOCKET                                   给系统推消息                  
  代码简析:
  第二个页面,跟第一个基本一样,改一下用户唯一标识:
  TestClientStudentPU.html             我要连SOCKET                                   给系统推消息                  
  OK,把项目跑起来,开始玩。
  直接访问客户端页面 模拟学生 JC连接socket:
  http://127.0.0.1:8089/TestClientStudentJC.html
  可以看到服务端有监测到:
  这里监测的:
  先试试客户端给系统推消息先:
  可以看到服务端成功收到消息:
  这种方式,其实是因为服务监听了相关的频道:
  前端使用JS推到这个系统频道:
  ps: 其实前端给服务端推消息,其实调用接口就可以。
  OK,进入核心应用场景1:群发,所有人都能收到
  系统给连上的客户端都推送消息
  {  "type": "ALL",  "content":"你们好,这是一条广播消息,全部人都能收到",  "channel":"CHANNEL_SYSTEM"  }
  看看效果:
  然后是场景2,局部群发,部分人群都能收到
  其实也就是通过HTML 客户端监听主题做区分就好:
  直接拉人口,升3 :
  模拟2个学生,1个老师都连接上了socket
  当然,老师监听的是 老师频道:
  然后我们模拟推送一下消息到指定的老师频道:
  {
  "type"  : "ALL"  ,
  "content"  :"给老师们推一条消息!!!"  ,
  "channel"  :"CHANNEL_TEACHER"
  }
  最后一个场景,也就是单点推送,指定某个人收到
  模拟 学生 PU 给 学生JC 推消息:
  可以看到在学生频道的JC正常收到了PU的消息:
  好了,该篇就到这吧。

知名老戏骨演出临时被取消,父子二人无奈摆烂,坐路边嗑瓜子提到演员陈佩斯这位老戏骨,相信大家对他一定不陌生吧,在近些年陈佩斯因为年纪大了,很少露面于银幕,但其实在私底下,他为了自己儿子的入行,也付出了很多努力。目前的陈佩斯也在不停的为自己女人过了50岁,秋天穿衣要懂得穿长不穿短,才能更优雅得体每个年龄阶段的女性,都有自己的穿衣风格重心。像年轻的姑娘就比较追求怎么穿得活泼可爱三四十岁的女人可能在琢磨着要怎么穿才能更有女人味更加性感但对于过了五十岁的女性来说,这些风格对自己第六集烂脸式护肤这7条你可能天天都在做每天都在护肤的你,是否知道自己护肤的方式不正确呢?以上7大烂脸式护肤,你中招了吗?那我们在日常生活中应该如何正确护肤呢?一起来扒扒护肤潜规则吧!一多种护肤品混合使用更补水?错误!原看脸是男神颜值,一上时尚封面全垮掉,肖战像女星,朱一龙显老娱乐圈堪称时尚界的典范,它始终引领着一代人的潮流。那什么才是真正的时尚呢?我想起码从发型到服装的搭配,整体看起来要有协调性,让人看着舒服。如果当造型师发挥得当的时候,对男星来说无疑染发头皮容易过敏的快试试这个,内含DIY染发剂推荐本人是少白头,每年染发的频率很高,但与此同时,几乎每次染发都会有或轻或重的过敏现象(一般都是痒和掉一块块的头皮)直到我发现了欧莱雅头皮锁护乳在涂染发膏前,把这个涂在头皮上,稍微按摩远超国足!越南替补球员2年豪购6辆跑车,没事就带白人妻子去兜风北京时间9月10日,越媒的消息,曾入选过1次越南队的前越南国青队球员小裴进勇迷上了跑车,从2020年底开始,他狂购6辆豪车,总共花费超过了1122亿越南盾(3300万人民币)。随着张康阳欲退出!准备出售国米,标价12亿欧,沙特土豪渴望接盘新赛季国米的成绩非常平淡,意甲赛场遭遇两场败仗,欧冠第一轮又被拜仁痛打,蓝黑军团在面对实力较强的球队时,缺乏足够的竞争力。球员们的士气也得不到提升,这让每场在现场观战的老板张康阳都绝了!还不起8亿贷款,欧冠3冠王,12亿卖了!老板开2千万超跑过去100多年的时间里,意大利足坛只有一支球队拿到过比国际米兰还多的欧冠冠军数,AC米兰曾经拿过5次欧冠冠军,而国米也拿到过3次,再往后就是尤文图斯的2次了!可以说,国际米兰在意大亚洲杯半决赛!初慧萱和李文霞双星闪耀,中国女篮领先日本9分9月10日晚20点30分,U18女子篮球亚洲杯半决赛,中国U18女篮对阵日本U18女篮。上半场,日本队开局72领先,随后中国队加强防守,首节结束,中国队以1312逆转领先日本队第二本周侃评哈雷尔加盟费城东契奇47分破纪录1哈雷尔与76人达成两年520万美元合同北京时间9月7日,据NBA著名记者Woj报道,自由球员蒙特雷兹哈雷尔与费城76人达成一份两年价值520万美元合同,其中第二年为球员选项。侃评欧锦赛如火如荼地进行,有近几十位NBA球员,感叹中国却一人没有北京时间2022年9月13日,我们继续关注篮坛的大事小情。虽然现阶段没有中国男篮的世预赛比赛,但是欧洲区可谓是神仙打架,欧洲新王东契奇希腊怪兽字母哥行走的五花肉约老师德国小黑施罗德
地方国资赋能,华光环能技术资金双轮驱动,乘双碳春风疾驰(报告出品方分析师民生证券严家源邓永康)1打造环保能源领域综合服务商1。1地方国资赋能,加快行业布局无锡华光环保能源集团股份有限公司(以下简称公司)成立于1958年8月,2003年2022年四川甘洛县GDP达52。26亿元地方一般公共财政收入增速居凉山州第一封面新闻记者罗石芊1月20日,封面新闻记者从四川凉山州甘洛县统计局获悉,2022年,甘洛县地区生产总值(GDP)52。26亿。地方一般公共财政收入突破3亿元,达3。03亿元,增长3地方两会观察全力推动经济运行整体好转从地方两会看稳增长新举措近期,各地两会密集召开。2023年经济增速目标怎么定,各地稳增长有哪些新举措,引发广泛关注。中央经济工作会议提出,2023年要坚持稳字当头稳中求进。推动经济运行整体好转。记者在地方三年老平台换新13代酷睿i7体验瞬间拉满2020年初,因为工作原因笔者斥资近万元,收了一套成色还不错的X299平台。以当时的多核旗舰i910980XEX299主板为核心,搭配416GBDDR4内存以及1TB英特尔760P中国游戏直播平台兵败海外作为游戏产业的下游,游戏直播平台乘着移动互联网发展的东风迅速崛起,在国内开展了一场轰轰烈烈的千播大战。在国内竞争激烈的20162018年,部分头部平台将目光投向了海外,在业内掀起了大数据ClickHouse进阶(十)ClickHouse的ArrayJoin子句ClickHouse的ArrayJoin子句Arrayjoin子句允许在数据表的内部,与数组类型的字段进行join操作,从而将一行数组展开为多行。首先我们创建一张MergeTree气道中的粘膜IgA抗体可防止SARS2感染至少八个月气道中高水平的粘膜IgA抗体可防止SARSCoV2感染至少八个月。Omicron感染会产生持久的粘膜抗体,从而降低再次感染的风险。这些是瑞典卡罗林斯卡医学院和丹德吕德医院的研究人员七言诗新年舒怀花开花落又来年,两鬓霜白银发添。喜逢佳节心激荡,吟诗赋章情怡然。读古阅今千万书,胸怀大志永向前。光阴流水日如梭,征途路上再新篇。张灯结彩庆新年,烦恼忧愁随风远。往事尽抛珍今日,挥毫新春走基层新年换房记视频加载中住房关系民生福祉,涉及千家万户。对北京市民刘女士来说,这个新年是一家人最高兴的新年住房换购手续已经办妥,很快就能入住新房了。近日,在北京市石景山区不动产登记事务中心,记者V观财报青农商行董监高变阵行长监事长同日辞任,什么原因?中新经纬1月19日电(魏薇)18日晚间,青岛农村商业银行股份有限公司(下称青农商行)发布了多份公告,涉及执行董事行长辞职,监事长辞职,聘任新行长等内容。就在半年前,青农商行原董事长即使渺小如尘埃,我们依然可以做自己的英雄2022年末,人生经历了大坎,曾经在漫长的黑夜里被无边无际的黑洞所吞噬,感恩身边的家人和亲朋好友给予的温暖,让我可以乐观坚强得前行。张兰所著的我的九条命这本书是同学得知我遇到的事情