最新要闻
- 每日快看:缯怎么读怎么组词_缯怎么读
- 环球时讯:英特尔开始停产11代处理器
- 王治郅视频_王治郅事件-全球最新
- 莫兰迪作品高清大图_莫兰迪作品 每日精选
- 天天消息!22.5万起 小鹏G6开启预售 官方:真正的6边形战士来了
- 全球实时:惠普推出新款无线耳机:充电盒自带触控屏 控制音乐播放
- 全球快播:高考考生遇采访喊话:取消调休 取消调休
- 网购格力空调收到“木各力”牌 商家拒绝退款
- 余承东:特斯拉FSD进入中国我们也不怕 依然可以遥遥领先
- 焦点快播:gtx260m显卡(gtx260m)
- 高考前最后一课丨常德市七中老师收到全班学生送的礼物 笑着笑着就哭了_当前快讯
- dnf带幻影的史诗武器(dnf幻影手镯) 世界热闻
- 当前速递!猪菜磨底VS服务回暖!5月CPI或小幅反弹
- 全球通讯!人工智能(AI)热潮提振了的科技股,并推高了对冲基金的回报,帮助他们挽回去年的损失
- 今日快讯:热力学第一定律功能关系(热力学第一定律)
- 热消息:favorite subject(favorite)
手机
iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
- 警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- 男子被关545天申国赔:获赔18万多 驳回精神抚慰金
- 3天内26名本土感染者,辽宁确诊人数已超安徽
- 广西柳州一男子因纠纷杀害三人后自首
- 洱海坠机4名机组人员被批准为烈士 数千干部群众悼念
家电
全球微资讯!websocket
1. WebSocket介绍
WebSocket 是一种网络通信协议。RFC6455 定义了它的通信标准。
(资料图片仅供参考)
WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。
HTTP 协议是一种无状态的、无连接的、单向的应用层协议。它采用了请求/响应模型。通信请求只能由客户端发起,服务端对请求做出应答处理。
这种通信模型有一个弊端:HTTP 协议无法实现服务器主动向客户端发起消息。
这种单向请求的特点,注定了如果服务器有连续的状态变化,客户端要获知就非常麻烦。大多数 Web 应用程序将通过频繁的异步 AJAX 请求实现长轮询。轮询的效率低,非常浪费资源(因为必须不停连接,或者 HTTP 连接始终打开)。
2. websocket协议
本协议有两部分:握手和数据传输。
握手是基于http协议的。
- 客户端(浏览器)实现
3.1 websocket对象
实现 WebSockets 的 Web 浏览器将通过 WebSocket 对象公开所有必需的客户端功能(主要指支持 Html5 的浏览器)。
以下 API 用于创建 WebSocket 对象:
var ws = new WebSocket(url);
参数url格式说明: ws://ip地址:端口号/资源名称
3.2 websocket事件
WebSocket 对象的相关事件
事件 | 事件处理程序 | 描述 |
---|---|---|
onopen | websocket对象.onopen | 连接建立时触发 |
onmessage | websocket对象.onmessage | 客户端接收服务端数据时触发 |
onerror | websocket对象.onerror | 通信发生错误时触发 |
onclose | websocket对象.onclose | 连接关闭时触发 |
3.3 WebSocket方法
WebSocket 对象的相关方法:
方法 | 描述 |
---|---|
send | 使用连接时发送消息 |
服务器实现
Java WebSocket应用由一系列的WebSocketEndpoint组成。Endpoint 是一个java对象,代表WebSocket链接的一端,对于服务端,我们可以视为处理具体WebSocket消息的接口, 就像Servlet之与http请求一样。
我们可以通过两种方式定义Endpoint:
· 第一种是编程式, 即继承类 javax.websocket.Endpoint并实现其方法。
· 第二种是注解式, 即定义一个POJO, 并添加 @ServerEndpoint相关注解。
实现流程
服务端如何接收数据
通过为 Session 添加 MessageHandler 消息处理器来接收消息,当采用注解方式定义Endpoint时,我们还可以通过 @OnMessage 注解指定接收消息的方法。
服务端如何推送数据
发送消息则由RemoteEndpoint完成,其实例由Session维护,根据使用情况,我们可以通过Session.getBasicRemote获取同步消息发送的实例,然后调用其sendXxx()方法就可以发送消息,可以通过Session.getAsyncRemote获取异步消息发送实例。
实现一个简单的聊天室功能
步骤:
1.首先导入依赖
org.springframework.boot spring-boot-starter-websocket
@Data@AllArgsConstructor@NoArgsConstructorpublic class Message { private Long id; @TableField(value = "from_user_id") private User fromUser; @TableField(value = "to_user_id") private User toUser; private String content; @TableField(fill = FieldFill.INSERT) private LocalDateTime createTime; @TableField(fill = FieldFill.INSERT) private LocalDateTime updateTime; private int messageType; @TableField(exist = false) private String toName; @TableField(exist = false) private String fromName; @TableField(exist = false) private String message; //添加好友码 public static final int ADD_FRIEND = 2; //好友列表消息码 public static final int FRIEND_LIST_TYPE = 3;
@Data@AllArgsConstructor@NoArgsConstructorpublic class Result{ /** * 状态码 */ private Integer code; /** * 提示信息,如果有错误时,前端可以获取该字段进行提示 */ private boolean flag; private String message; private T data; //数据 public static Result success(T object) { Result r = new Result(); r.data = object; r.code = 1; r.flag = true; return r; } public static Result error(String message) { Result r = new Result(); r.message = message; r.code = 0; r.flag = false; return r; }}
@PostMapping("/login") public Result login(@RequestBody User user ,HttpSession session){ String password = user.getPassword(); String username = user.getUsername(); log.info("用户登录操作"); //MD5加密 password = DigestUtils.md5DigestAsHex(password.getBytes()); //根据用户名查找数据库 LambdaQueryWrapper wrapper =new LambdaQueryWrapper<>(); wrapper.eq(User::getUsername,username); User one = userService.getOne(wrapper); if (one == null){ return Result.error("用户不存在,请先注册"); }if (! one.getPassword().equals(password)){ return Result.error("用户名或者密码有误"); } // 登录成功,将用户的ID存储到WebSocket连接的Session中 session.setAttribute("userId", one.getId()); // 假设用户ID为one.getId() String sessionId = session.getId(); return Result.success(one); }
@GetMapping("/getUsername") private String getUsername(HttpSession session) { // 从 HttpSession 中获取用户信息 User user = (User) session.getAttribute("user"); if (user != null) { return user.getUsername(); } return null; }
@Configuration@EnableWebSocketMessageBrokerpublic class WebsocketConfig implements WebSocketMessageBrokerConfigurer { @Bean //注入ServerEndpointExporter bean.对象,自动注册使用了@ServerEndpoint public ServerEndpointExporter serverEndpointExporter(){ return new ServerEndpointExporter(); } @Override public void registerStompEndpoints(StompEndpointRegistry registry) { // 定义一个 WebSocket 入口,客户端需要连接到它才能接收推送消息 registry.addEndpoint("/websocket").withSockJS(); } @Override public void configureMessageBroker(MessageBrokerRegistry config) { // 启用推送的消息代理(即使用 STOMP 实现 WebSocket 的代理) config.enableSimpleBroker("/topic"); // 开启基于用户的 WebSocket 会话 config.setUserDestinationPrefix("/user"); }}public class GetHttpSessionConfig extends ServerEndpointConfig.Configurator { /** * 获取session对象 * @param sec * @param request * @param response */ @Override public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response) { //获取HttpSession.对象 HttpSession httpsession = (HttpSession) request.getHttpSession(); //将httpSession存储到配置对象 sec.getUserProperties().put(HttpSession.class.getName(), httpsession); }}
@ServerEndpoint(value = "/chat",configurator = GetHttpSessionConfig.class)@Component@Slf4jpublic class ChatEndpoint { private Session session; private static HttpSession httpSession; //用来存储每一个客户端对象对应的ChatEndpoint对象 private static final Map onlineUsers = new ConcurrentHashMap<>(); @OnOpen public void onopen(Session session, EndpointConfig config) { //将局部的session对象赋值给成员session this.session = session; //获取Httpsession对象 ,键值对集合,得到键获取值 this.httpSession = (HttpSession) config.getUserProperties().get(HttpSession.class.getName()); String user = (String) this.httpSession.getAttribute("user"); onlineUsers.put(user,session); //广播消息,获取在线的所有好友 String message = MessageUtils.getMessage(true, null, getFriendsName()); broadcastAllUsers(message); } /** * 获取所有在线的好友信息,名称 * @return */ public Set getFriendsName(){ Set set = onlineUsers.keySet(); return set; } /** * 发给所有人的广播 * @param message */ private void broadcastAllUsers(String message){// 拿到所有的用户的chatEndpoint对象 //存储用户的session信息 Set> entries = onlineUsers.entrySet(); //遍历map集合 for (Map.Entry entry : entries) { //获取所有用户对应的session对象 //拥有getBasicRemote发送消息的方法 Session session =entry.getValue(); //发送消息 try { session.getBasicRemote().sendText(message); } catch (IOException e) { e.printStackTrace(); } } } @OnMessage public void onMessage(String message, @PathParam("username") String username){ try { log.info("服务端收到用户username={}的消息:{}", username, message); //将消息转换成message对象 Message msg = JSON.parseObject(message,Message.class); //获取接收方的用户名 String toName = msg.getToName(); //获取消息数据 String message1 = msg.getMessage(); //获取接收方的用户的session对象 Session session = onlineUsers.get(toName); if (session != null) { // 获取当前登录的用户 从session中获取 String user = (String) httpSession.getAttribute("user"); //user代表的是发送方 String message2 = MessageUtils.getMessage(false, user, message1); session.getBasicRemote().sendText(message2); }else { log.info("未找到用户username{}的session",toName); } if (msg.ADD_FRIEND ==2 && session != null){ //获取发送发 String user = (String) httpSession.getAttribute("user"); //获取消息 String message2 = MessageUtils.getMessage(false, user, message1); //发送 session.getBasicRemote().sendText(message2); //将好友添加到相应的列表中,例如用Map存储好友列表 Map> friendLists = (Map>) httpSession.getAttribute("friendLists"); List friendList=friendLists.get(user); friendList.add(toName); friendLists.put(user,friendList); httpSession.setAttribute("friendLists", friendLists); //发送好友列表 Message friendListMessage = new Message(); friendListMessage.setMessageType(3); friendListMessage.setFromName("System"); friendListMessage.setToName(user); friendListMessage.setMessage(JSON.toJSONString(friendList)); ChatEndpoint.send(friendListMessage,getFriendsName()); } else { log.info("未找到用户username{}的session",toName); } } catch (IOException e) { throw new RuntimeException(e); } } private static void send(Message friendListMessage, Set friendsName) { try { String toName = friendListMessage.getToName(); String message = friendListMessage.getMessage(); Session session = onlineUsers.get(toName); if (session != null) { String json = JSON.toJSONString(message); session.getBasicRemote().sendText(json); } else { log.info("未找到用户{}的session", toName); } } catch (IOException e) { throw new RuntimeException(e); } } @OnClose public void onclose(Session session) { //提出session中的记录 String user = (String) this.httpSession.getAttribute("user"); onlineUsers.remove(user); //通知所有用户,此账号下线。 String message = MessageUtils.getMessage(true, null, getFriendsName()); broadcastAllUsers(message); }
关键词:
全球微资讯!websocket
海外直播源码技术文字聊天功能的配置_当前速讯
深入浅出Spring原理及实战「缓存Cache开发系列」
每日快看:缯怎么读怎么组词_缯怎么读
环球时讯:英特尔开始停产11代处理器
王治郅视频_王治郅事件-全球最新
莫兰迪作品高清大图_莫兰迪作品 每日精选
天天消息!22.5万起 小鹏G6开启预售 官方:真正的6边形战士来了
全球实时:惠普推出新款无线耳机:充电盒自带触控屏 控制音乐播放
全球快播:高考考生遇采访喊话:取消调休 取消调休
网购格力空调收到“木各力”牌 商家拒绝退款
余承东:特斯拉FSD进入中国我们也不怕 依然可以遥遥领先
焦点快播:gtx260m显卡(gtx260m)
高考前最后一课丨常德市七中老师收到全班学生送的礼物 笑着笑着就哭了_当前快讯
dnf带幻影的史诗武器(dnf幻影手镯) 世界热闻
当前速递!猪菜磨底VS服务回暖!5月CPI或小幅反弹
热讯:流年
世界百事通!深度学习应用篇-计算机视觉-语义分割综述[5]:FCN、SegNet、Deeplab等分割算法、常用二维三维半立体数据集汇总、前景展望等
每日资讯:美团太细了:Springcloud 微服务优雅停机,如何实现?
全网Jenkins+Gitee+Docker/SSH 部署避坑点总结 每日关注
全球通讯!人工智能(AI)热潮提振了的科技股,并推高了对冲基金的回报,帮助他们挽回去年的损失
今日快讯:热力学第一定律功能关系(热力学第一定律)
热消息:favorite subject(favorite)
天天看点:辽宁省沈阳市2023-06-06 16:27发布大风蓝色预警
每日报道:qq显示iphone在线没有显示4g(qq显示iphone在线)
全球百事通!正整数包括什么分数(正整数包括什么)
鸡汤用高压锅煮要煮多久 高压锅炖鸡汤要压多少分钟
守护者之铠(永恒守护者腿铠)-全球消息
充满“海洋”味!比亚迪宋PLUS冠军版来了:选它还是四驱哈弗枭龙MAX
世界热头条丨精装版丰田陆巡 全新雷克萨斯GX全球首发:能越野的日系豪华!
美国一列满载全新汽车的火车脱轨:弯弯曲曲扭成“贪吃蛇”
快消息!K60系列终极大作!曝Redmi K60 Ultra 7月登场
重庆一女生考完哭着说终于不用做数学了:网友神回复-焦点观察
汉字的演变历史手抄报_汉字的演变历史 天天最新
高考“钉子户”梁实谈第27次高考:文综重大失误
世界短讯!珍惜时间的名人小故事(珍惜时间的名人)
全球播报:百度贴吧怎么注册帐号登录(百度贴吧怎么注册帐号)
热推荐:太极杨氏85赵斌视频(赵斌杨氏85式太极拳)
Nginx安装部署及性能优化 当前看点
每日动态!Map
恩施市教育局电子政务系统(恩施市教育局电子政务登录)
tom ford男友(sufjan stevens男朋友)_头条焦点
全球通讯!“宗”这个字应该如何正确读音?
董明珠:格力空调10年免费包修 对手不敢这么做
天玑9200手机出手 5G上行速度跑出440Mbps新纪录-世界热点
每日看点!扎克伯格批苹果Vision Pro头显:社交属性太差 不如跟Meta
梅西打义乌厂商措手不及:迈阿密新队服来不及生产 每日时讯
北大屠夫称大学生就业难关键在父母:大学生是普通教育 不要把自己当精英 世界播报
今日观点!医保卡_医保卡里的钱可以取出来吗
qq用手机怎么设置空白名字_手机qq怎么弄空白名字
当前速看:【机构调研记录】凯石基金调研江苏雷利
RTOS测试(韩国方案)
pxo理论_pxo-全球动态
runningman超能力特辑第二季_running man超能力特辑|今亮点
泰国(硬盘)
【读财报】年初以来99单IPO项目终止:海通证券数量居首,华金证券撤否率最高
人类首次!我国科研人员监测到伽马射线暴全过程:来自20多亿年前
今热点:iOS 17体验评测:20条Bug 9个变化 不值得升级
每日热门:学生打架老师要求用英语复述过程 两人散装英语让网友笑趴
福建福州:智能服务机器人产销两旺
华电国际:6月8日融券卖出80.13万股,融资融券余额2.83亿元
目标永兴岛 航程900海里 “海巡03”轮首次巡航西沙海域
环球观热点:全能型锋线大将试训勇士,他是双向合同的理性选择?
世界微资讯!半年91家公司涨幅翻倍!林园、谢治宇、赵建平三位大佬谁抓了超级牛股?
【世界快播报】Oil-Dri Corp of America(ODC.US):2023年Q3财报实现营收1.054亿美元
单硫型水化硫铝酸钙英文_单硫型水化硫铝酸钙_世界焦点
江西铜业:业绩说明会定于6月15日举行
天天观焦点:qq三国国战时间表2021_qq三国国战时间
研报存多项问题,招商证券及4名分析师被出具警示函_环球视点
中超联赛有观众使用激光笔向球场照射,中国足协公布处罚决定
商汤:公司B类普通股股份人民币柜台将自6月19日起推出_当前关注
世界新消息丨坚守“全球车标准”,第4代帝豪2023冠军款上市
热头条丨大北农:定增募资不超19.43亿元申请获深交所审核通过
lol全球总决赛s6 lol全球总决赛视频回放)
高中生期末班主任评语大全(高中生期末班主任评语)
高考英语不会的可以选C 苹果:我是Ctrl+C 报道
海航管控空姐体重 超重停飞引热议:这不在监管标准内 其他航空公司不跟进
临港新片区与7家QFLP试点管理企业签署合作备忘录-世界信息
全球微头条丨A股共75只个股发生大宗交易 派特尔溢价率27.65%居首
全球速看:我之前一直在跟新入行的师弟师妹说,趁年轻学习能力强,抓紧时间转行吧!
50道常见高频大厂面试题-微资讯
读改变未来的九大算法笔记07_搜索引擎
安装指定版本的mysql(安装mysql5
A股IPO动态:豪江智能(301320.SZ)等三股今日上市 今日关注
金融工程主要学什么科-全球要闻
今日热门!突发!中国电信全省崩溃,发生了什么?利好不断,A股明天要起飞?
全球热讯:宁时的意思_凝视的意思
商汤-W(00020):增设B类股份人民币柜台 环球热议
【新视野】深夜22点,埃格努宣布意外决定,蔡斌渔翁得利,中国女排喜出望外
全球热门:打工人狂喜!微信PC版3.9.5正式发布:锁定功能上线
竟内置华为服务套件 800块山寨机用起来到底咋样? 焦点短讯
代驾师傅雨中救下跳河女子 滴滴:奖励3000元现金-世界微动态
独立显卡10年来最惨!AMD再不努力 Intel就追上了-微速讯
《变形金刚7:超能勇士崛起》今日上映:终极BOSS宇宙大帝登场_看热讯
惠民保2023:保障升级持续拓面,短期内不会“凉凉”
世界观速讯丨通知!放假3天!陕西多地明确:明起,免费!
凝聚汽车产业高质量发展智慧 2023中国汽车重庆论坛开幕 焦点热闻
讯息:我是中国人诗歌朗诵搭配视频 我是中国人诗歌
要式证券属于侠义票据的特征 要式证券
盐城515人才申请入口(盐城515) 环球头条