苍穹外卖day10(黑马程序员)
苍穹外卖 day10 笔记WebSocket什么是 WebSocketWebSocket是一种全双工的网络通信方式客户端和服务器建立连接之后双方都可以随时主动给对方发消息不必像传统网页那样「每次都要重新发起一次请求」。可以把它理解成HTTP像发短信——你问一句对方答一句想再问再发一条。WebSocket像打电话——线路接通后两边随时说话不用每句话都重新拨号。在技术上的要点连接一般从一次HTTP 升级握手开始浏览器先发带Upgrade: websocket的请求服务器同意后同一条 TCP 连接就升级为 WebSocket之后在这条连接上传 WebSocket 帧。数据以帧frame为单位传输开销比反复建连的 HTTP 要小适合高频、实时场景聊天、订单状态推送、大屏数据刷新等。WebSocket 和 HTTP 的区别对比项HTTPWebSocket通信模型主要是请求—响应客户端发起服务器返回一次交互通常结束长连接 双向建立后客户端、服务器都能主动推送连接方式常用短连接HTTP/1.1 可 keep-alive但语义仍是「一次请求一次响」先握手再长连连接保持打开谁先发几乎总是客户端先请求建立后服务端也可主动往客户端发实时性要靠轮询定时请求或 SSE 等折中方案才有「伪实时」天然适合实时推送头部开销每次请求常带较多 HTTP 头握手后帧头相对小适合频繁小消息典型场景打开网页、REST 接口、表单提交在线客服、即时通知、协同编辑、实时行情一句话HTTP 适合「拿资源、调接口」WebSocket 适合「连着不断互相推消息」的实时通信。packagecom.sky.websocket;importorg.springframework.stereotype.Component;importjavax.websocket.OnClose;importjavax.websocket.OnMessage;importjavax.websocket.OnOpen;importjavax.websocket.Session;importjavax.websocket.server.PathParam;importjavax.websocket.server.ServerEndpoint;importjava.util.Collection;importjava.util.HashMap;importjava.util.Map;/** * WebSocket服务 */ComponentServerEndpoint(/ws/{sid})publicclassWebSocketServer{//存放会话对象privatestaticMapString,SessionsessionMapnewHashMap();/** * 连接建立成功调用的方法 */OnOpenpublicvoidonOpen(Sessionsession,PathParam(sid)Stringsid){System.out.println(客户端sid建立连接);sessionMap.put(sid,session);}/** * 收到客户端消息后调用的方法 * * param message 客户端发送过来的消息 */OnMessagepublicvoidonMessage(Stringmessage,PathParam(sid)Stringsid){System.out.println(收到来自客户端sid的信息:message);}/** * 连接关闭调用的方法 * * param sid */OnClosepublicvoidonClose(PathParam(sid)Stringsid){System.out.println(连接断开:sid);sessionMap.remove(sid);}/** * 群发 * * param message */publicvoidsendToAllClient(Stringmessage){CollectionSessionsessionssessionMap.values();for(Sessionsession:sessions){try{//服务器向客户端发送消息session.getBasicRemote().sendText(message);}catch(Exceptione){e.printStackTrace();}}}}代码逐行讲解含注释含义包与导入行内容说明package com.sky.websocket;类放在websocket包下和业务里的 WebSocket 放一起。Component相关org.springframework.stereotype.Component把该类交给Spring 容器管理便于别的 Bean 注入WebSocketServer例如来单后调用sendToAllClient。OnOpen/OnMessage/OnCloseJSR-356Java WebSocket API里的注解分别标记「连接打开」「收到消息」「连接关闭」时要调的方法。Session表示和某一个客户端的那条 WebSocket 会话用来发消息、关连接。PathParam从路径里取变量和ServerEndpoint(/ws/{sid})里的{sid}对应。ServerEndpoint声明这是一个WebSocket 服务端端点括号里是访问路径相对应用根路径实际完整地址还取决于是否配置了 context-path。Collection/HashMap/MapsessionMap用Map存「业务 id → Session」方便按人管理、群发时遍历。类上的注解与类注释内容说明/** WebSocket服务 */类注释说明这个类负责提供 WebSocket 服务。ComponentSpring 扫描后注册为 Bean注意若用 JDK 自带ServerEndpoint 内嵌 Tomcat有时还要配ServerEndpointExporter课程里一般会一起讲。ServerEndpoint(/ws/{sid})连接地址形如/ws/某个sid例如/ws/1sid常用来区分客户端如用户 id、门店 id方便日志和sessionMap的 key。sessionMap与注释「存放会话对象」//存放会话对象privatestaticMapString,SessionsessionMapnewHashMap();注释含义这里不是用来存「聊天内容」而是存当前已连接上的每一个客户端会话。static所有WebSocketServer实例共享同一张表因为ServerEndpoint每连接可能对应不同实例用 static 才能保证「全站会话」在一起群发才找得到所有人。keyString sid路径里的sid用来标识是谁连上来了。valueSession和该客户端通信用的对象发消息要用它。onOpen— 注释「连接建立成功调用的方法」OnOpenpublicvoidonOpen(Sessionsession,PathParam(sid)Stringsid){OnOpen浏览器/前端new WebSocket(url)握手成功后容器会调这个方法。Session session当前这条连接的会话对象。PathParam(sid) String sid从 URL/ws/{sid}里解析出的那一段例如连的是/ws/admin1则sid为admin1。System.out.println(客户端sid建立连接);sessionMap.put(sid,session);打日志谁连上了。put(sid, session)把「这个 sid」和「这条 Session」绑定后面群发或按人发都要靠这张表。onMessage— 注释「收到客户端消息后调用的方法」/** * 收到客户端消息后调用的方法 * * param message 客户端发送过来的消息 */OnMessagepublicvoidonMessage(Stringmessage,PathParam(sid)Stringsid){OnMessage该客户端发来一段文本时触发这里按String接收文本帧。message客户端发的字符串内容Javadoc 注释已说明。sid仍是路径上的 id表示是谁发的。System.out.println(收到来自客户端sid的信息:message);仅打印若要做「回显、广播、业务处理」可在这里加逻辑。onClose— 注释「连接关闭调用的方法」/** * 连接关闭调用的方法 * * param sid */OnClosepublicvoidonClose(PathParam(sid)Stringsid){OnClose连接断开用户关页面、网络断了、服务端关连接等时调用。这里只传了sid没有Session因为连接已断通常只需从 map 里删掉避免内存泄漏和向已死连接发消息。System.out.println(连接断开:sid);sessionMap.remove(sid);从sessionMap移除注释对应关系「连接关闭」→ 不再保留该会话。sendToAllClient— 注释「群发」/** * 群发 * * param message */publicvoidsendToAllClient(Stringmessage){业务方法不是 WebSocket 生命周期注解给当前所有在线客户端发同一条文本。message要广播的内容Javadoc 里的param message即此意。一般由Service在「新订单来了」时注入WebSocketServer后调用。CollectionSessionsessionssessionMap.values();for(Sessionsession:sessions){try{//服务器向客户端发送消息session.getBasicRemote().sendText(message);sessionMap.values()取出所有在线Session。注释「服务器向客户端发送消息」表示这里是服务端主动推送相对onMessage的「客户端发来」。getBasicRemote().sendText(message)同步方式向该 Session 发一段文本若要多线程并发发可考虑getAsyncRemote()课程里常用BasicRemote即可。}catch(Exceptione){e.printStackTrace();}}}某个连接已失效仍留在 map 里时sendText可能抛异常catch后打印避免一条失败导致后面人都收不到可根据需要再remove无效 session。小结对照注释注释/注解一句话WebSocket服务本类职责处理 WebSocket 连接与推送。存放会话对象Map 里是在线客户端的Sessionkey 为sid。连接建立成功调用的方法onOpen登记会话。收到客户端消息后调用的方法onMessage处理客户端上行文本。连接关闭调用的方法onClose移除会话。群发sendToAllClient对所有在线连接sendText。服务器向客户端发送消息在循环里用Session向浏览器推送。客户催单模块Controller层/** * 客户催单 * param id * return */GetMapping(/reminder/{id})ApiOperation(用户订单催单)publicResultreminder(PathVariable(id)Longid){orderService.reminder(id);returnResult.success();}Service层Overridepublicvoidreminder(Longid){//根据id查询订单OrdersordersorderMapper.getById(id);if(ordersnull){thrownewOrderBusinessException(MessageConstant.ORDER_STATUS_ERROR);}MapmapnewHashMap();map.put(type,2);//1:表示来单提醒2表示客户催单map.put(orderId,id);map.put(content,订单号orders.getNumber());StringjsonJSONObject.toJSONString(map);WebSocketServer.sendToAllClient(json);}根据传回来的orders的对象解析里面的orderId然后转换成json格式最后传递给WebSocketServer实现群发的功能
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2480096.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!