位置: IT常识 - 正文

Java使用WebStocket实现前后端互发消息(java使用循环结构输出九九乘法表)

编辑:rootadmin
Java使用WebStocket实现前后端互发消息

推荐整理分享Java使用WebStocket实现前后端互发消息(java使用循环结构输出九九乘法表),希望有所帮助,仅作参考,欢迎阅读内容。

文章相关热门搜索词:java使用循环结构输出九九乘法表,java使用while循环对n以内的偶数求和,java使用while循环对n以内的偶数求和,java使用for循环作等腰三角形,java使用正则表达式替换,java使用指定版本的jar包,java使用递归的方法求n!,java使用正则表达式替换,内容如对您有帮助,希望把文章链接给更多的朋友!

记录一下自己使用WebStocket实现服务器主动发消息的过程和踩得雷。

需求:车牌识别系统识别到车牌后,持续向前端推送车牌信息,直到前端回复收到。

测试需求:新增 客户后,持续向前端推送客户信息,直到前端收到消息,并且回复收到。

1.引入WebStocket的依赖<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId><version>2.7.0</version></dependency>

2.创建配置类 WebScoketConfig

import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.web.socket.server.standard.ServerEndpointExporter;/** * 开启WebSocket支持 */@Configurationpublic class WebSocketConfig { @Bean public ServerEndpointExporter serverEndpointExporter() { return new ServerEndpointExporter(); }}

新增客户的业务层

  这里实现了新增 客户后,持续向前端推送客户信息。

  实现思路:本来是打算 让前端接收到客户信息,回复后端的时候,后端修改数据库中此条客户的 接收状态的字段,然后每次后端往前端发送消息的时候都去数据库查询一次 客户信息的接收状态,如果已经接收到了就不往前端推送。但是好像会造成一边读数据库,一边修改数据库,会出现脏读的问题,而且我在 WebScoketConfigServer 中并不能创建Service层的对象,总是报空指针。

  最后,决定使用 static修饰的静态变量来实现对前端是否接受到消息和是否发送的是同一条重复的消息进行判断。然后根据返回的结果决定是否继续往前端推送消息。

import io.recycle.modules.rest.api.dto.system.CustomerDto;import io.recycle.modules.rest.api.dto.system.CustomerQueryDto;import io.recycle.modules.rest.api.dto.weigh.CardDto;import io.recycle.modules.rest.api.dto.weigh.CustomerParam;import io.recycle.modules.rest.api.dto.weigh.CustomerWeighDto;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import java.util.List;import java.util.Map;import io.recycle.modules.rest.api.dao.RecycleCustomerDao;import io.recycle.modules.rest.api.entity.RecycleCustomerEntity;import io.recycle.modules.rest.api.service.RecycleCustomerService;@Service("recycleCustomerService")public class RecycleCustomerServiceImpl implements RecycleCustomerService{private static int count=0;@Autowiredprivate NoticeWebsocket noticeWebsocket;@Autowiredprivate RecycleCustomerDao recycleCustomerDao;@Overridepublic void save(RecycleCustomerEntity recycleCustomer){recycleCustomerDao.save(recycleCustomer);//测试webstocket,实现新增客户往前端推送消息,直到前端回复////测试webstocketboolean flag = false;do{try {Thread.sleep(300); //休息300毫秒} catch (InterruptedException e) {e.printStackTrace();System.out.println("休息时出错000000");}//往前端发送消息System.out.println("count===="+count);boolean resultFlag = noticeWebsocket.sendMessage("新增了用户:" + recycleCustomer.toString(),count);flag = resultFlag;if (resultFlag){System.out.println("停止往前端发送数据,因为 resultFlag 为: "+resultFlag+"==说明前端已接收的消息");}else {System.out.println("往前端发送数据,因为 resultFlag 为: "+resultFlag+"==说明前端还没接收到消息");}}while ( !flag );System.out.println("停止往前端发送数据,因为 delFlag 为: "+flag);count = count +1;}}

3.创建WebScoketConfigServer

在websocket协议下,后端服务器相当于ws里的客户端,需要用@ServerEndpoint指定访问的路径,并使用@Component注入容器。

这里实现了新增 客户后,持续向前端推送客户信息,直到前端收到消息,并且回复收到。

Java使用WebStocket实现前后端互发消息(java使用循环结构输出九九乘法表)

实现思路:

import com.alibaba.fastjson.JSONObject;import io.recycle.modules.rest.api.dao.RecycleCustomerDao;import io.recycle.modules.rest.api.dto.websocket.NoticeWebsocketResp;import io.recycle.modules.rest.api.entity.RecycleCustomerEntity;import lombok.extern.slf4j.Slf4j;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import org.springframework.util.StringUtils;import javax.websocket.*;import javax.websocket.server.PathParam;import javax.websocket.server.ServerEndpoint;import java.io.IOException;import java.util.*;import java.util.concurrent.ConcurrentHashMap;/** * @ServerEndpoint 注解是一个类层次的注解,它的功能主要是将目前的类定义成一个websocket服务器端, * 注解的值将被用于监听用户连接的终端访问URL地址,客户端可以通过这个URL来连接到WebSocket服务器端 */@ServerEndpoint("/chepaisend")@Component@Slf4jpublic class NoticeWebsocket { //记录连接的客户端 public static Map<String, Session> clients = new ConcurrentHashMap<>(); /** * userId关联sid(解决同一用户id,在多个web端连接的问题) */ public static Map<String, Set<String>> conns = new ConcurrentHashMap<>(); private String sid = null; //一些记录发送消息状态 private static int initFlag =0; private static int tempFlag =0; //区分新旧消息的变量 private static int sum=0; /** * 连接成功后调用的方法 * @param session * */ @OnOpen public void onOpen(Session session) { this.sid = UUID.randomUUID().toString(); clients.put(this.sid, session); log.info(this.sid + "连接开启!"); } /** * 连接关闭调用的方法 */ @OnClose public void onClose() { log.info(this.sid + "连接断开!"); clients.remove(this.sid); } /** * 判断是否连接的方法 * @return */ public static boolean isServerClose() { if (NoticeWebsocket.clients.values().size() == 0) { log.info("已断开"); return true; }else { log.info("已连接"); return false; } } /** * 发送给所有用户 * @param noticeType */ public static boolean sendMessage(String noticeType,int count){ //判断是否是新的新增客户 System.out.println("count= "+count+",sum= "+sum+",initFlag= "+initFlag+",tempFlag= "+tempFlag); if (sum != count){ NoticeWebsocketResp noticeWebsocketResp = new NoticeWebsocketResp(); noticeWebsocketResp.setNoticeType(noticeType); sendMessage(noticeWebsocketResp); sum = count; } //判断前端是否 回复了 收到消息 相等没收到,不相等 收到 if (initFlag==tempFlag){ NoticeWebsocketResp noticeWebsocketResp = new NoticeWebsocketResp(); noticeWebsocketResp.setNoticeType(noticeType); sendMessage(noticeWebsocketResp); }else { //收到消息了,别发同一个消息了 tempFlag = initFlag; return true; } tempFlag = initFlag; //没收到消息继续发 return false; } /** * 发送给所有用户 * @param noticeWebsocketResp */ public static void sendMessage(NoticeWebsocketResp noticeWebsocketResp){ String message = JSONObject.toJSONString(noticeWebsocketResp); for (Session session1 : NoticeWebsocket.clients.values()) { try { session1.getBasicRemote().sendText(message); } catch (IOException e) { e.printStackTrace(); } } } /** * 根据用户id发送给某一个用户 * **/ public static void sendMessageByUserId(String userId, NoticeWebsocketResp noticeWebsocketResp) { if (!StringUtils.isEmpty(userId)) { String message = JSONObject.toJSONString(noticeWebsocketResp); Set<String> clientSet = conns.get(userId); if (clientSet != null) { Iterator<String> iterator = clientSet.iterator(); while (iterator.hasNext()) { String sid = iterator.next(); Session session = clients.get(sid); if (session != null) { try { session.getBasicRemote().sendText(message); } catch (IOException e) { e.printStackTrace(); } } } } } } /** * 收到客户端消息后调用的方法 * @param message * @param session */ @OnMessage public void onMessage(String message, Session session) { log.info("收到来自窗口"+"的信息:"+message); if ("已接收到消息".equals(message)){ //收到消息,改变flag的值 System.out.println("前端已经收到消息,开始改变 initFlag的值,此时initFlag= "+initFlag); initFlag = initFlag +1; System.out.println("前端已经收到消息,已经改变 initFlag的值,此时initFlag== "+initFlag); } } /** * 发生错误时的回调函数 * @param error */ @OnError public void onError(Throwable error) { log.info("错误"); error.printStackTrace(); }}

封装的发送消息的对象

import io.swagger.annotations.ApiModel;import io.swagger.annotations.ApiModelProperty;import lombok.Data;@Data@ApiModel("ws通知返回对象")public class NoticeWebsocketResp<T> { @ApiModelProperty(value = "通知类型") private String noticeType; @ApiModelProperty(value = "通知内容") private T noticeInfo;}

4.WebSocket调用

用户端调用此接口,主动将消息发送给后端,后端接收到消息后再主动推送给指定/全部用户,可以实现消息的私聊和群发功能。

import io.recycle.common.utils.R;import io.recycle.modules.rest.api.service.impl.NoticeWebsocket;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;@RestController@RequestMapping("/order")public class OrderController {@GetMapping("/test") public R test() { NoticeWebsocket.sendMessage("你好,WebSocket",1); return R.ok(); }}

前端WebSocket连接

<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>SseEmitter</title></head><body><div id="message"></div></body><script> var limitConnect = 0; init(); function init() { //开启webstocket服务的ip地址 ws:// + ip地址 + 访问路径 var ws = new WebSocket('ws://127.0.0.1:8191/double-win/chepaisend');// 获取连接状态 console.log('ws连接状态:' + ws.readyState);//监听是否连接成功 ws.onopen = function () { console.log('ws连接状态:' + ws.readyState); limitConnect = 0; //连接成功则发送一个数据 ws.send('我们建立连接啦'); }// 接听服务器发回的信息并处理展示 ws.onmessage = function (data) { console.log('接收到来自服务器的消息:'); console.log(data); //接收到 消息后给后端发送的 确认收到消息,后端接收到后 不再重复发消息 ws.send('已接收到消息'); //完成通信后关闭WebSocket连接 // ws.close(); }// 监听连接关闭事件 ws.onclose = function () { // 监听整个过程中websocket的状态 console.log('ws连接状态:' + ws.readyState); reconnect(); }// 监听并处理error事件 ws.onerror = function (error) { console.log(error); } } function reconnect() { limitConnect ++; console.log("重连第" + limitConnect + "次"); setTimeout(function(){ init(); },2000); }</script></html>

项目启动后,打开写好的前端页面后控制台打印连接信息

 新增客户后,前端接收到,并回复收到了

  新增客户后,前端接收到,并回复收到了,后端停止推送

前端接收到,但是骗后端没收到,或者说后端不知道 前端已经接收到消息。 

后端展示,后端一直往前端推送

 

本文链接地址:https://www.jiuchutong.com/zhishi/298859.html 转载请保留说明!

上一篇:css深度选择器deep(css选择器nth)

下一篇:睿智的目标检测——PyQt5搭建目标检测界面(睿智目标检测yolov8)

  • 增值税有哪些二类税种
  • 处置公司车辆账务处理
  • 建筑公司办公室照片真实
  • 三证合一是哪三证孩子上学
  • 增值税不视同销售行为有哪些
  • 当月有进项无销项月末怎么处理
  • 原材料进口关税怎么算
  • 违约金收入是否征税
  • 职工集资建房款属公款吗
  • 国际贸易公司注册需要什么条件海南
  • 机器设备折旧费用属于间接生产费用
  • 法律关系的内容是指
  • 卖股票为什么要留一手
  • 普票开票开给个人怎么开
  • 营改增的会计分录
  • "税务 政策"
  • 高亮!这些发票不能抵扣增值税
  • 收款收据可以做账么
  • 成本分析总结报告
  • 企业已确认销售收入的售出商品发生销售折让,且不属于
  • 印花税是怎么计税的
  • 鸿蒙超级终端搜不到
  • 怎么检查windows版本
  • windows11我的电脑怎么放到桌面
  • 调整以前年度所得税汇算清缴报表,在哪调减虚增的成本
  • 费用发票可以不上账吗
  • 在window系统中哪些用户可以查看日志
  • 笔记本电脑连无线网老是掉线怎么回事
  • 如何修复win11系统
  • 公司入股的钱叫什么
  • 所得税特殊性税率是多少
  • 怎么查上市公司
  • win11更新卡主
  • 应付账款讲解
  • 其他业务收入属于收入吗
  • 代扣手续费是啥意思
  • 企业成立多久可以注销
  • 在树洞中休息的英语
  • ChatGLM-6B (介绍以及本地部署)
  • 公司变更需要哪些资料~问华杰 财务
  • 以前年度损益调整借贷方向
  • 农业合作社需要纳税吗
  • 征收率是税率吗
  • 应交税费月末要结平
  • 应付职工薪酬中的职工是指
  • 审计外聘人员支付标准
  • 小企业会计准则主要按照什么计量
  • 免税普票要交企业所得税吗
  • 个人捐赠支出税前扣除条件
  • 电子承兑被退回要重新背书怎么办
  • mysql 子查询
  • 用友t3软件财务软件具体操作
  • 加盖发票专用章有效什么意思
  • 网络销售还可以叫什么
  • 小规模纳税人需要每月报税吗
  • 用友t3固定资产反结账的操作步骤
  • 发票代码和发票号码是唯一的吗
  • 会计账簿的更换和保管有哪些要求
  • 分类不同
  • freebsd配置dns
  • 如何解决电脑蓝屏0X0000007B
  • surface 优惠
  • windowsxp收藏夹在哪
  • linux常见信号
  • windows10对话框是什么
  • 怎么查看自己mac电脑有没有被人使用过
  • 盗版xp黑屏的解决办法
  • win10 ie浏览器双击没有反应
  • linux监控软件zabbix
  • win10切换登陆账户为administrator
  • 怎么对js代码程序进行设计
  • perl中的$1
  • shell 函数 return
  • 批处理新建多个文件夹
  • 请找到以下
  • shell脚本技巧
  • js 设计模式
  • 怎么看网页的编码格式
  • 小规模纳税人网上申报
  • 区域化管理的利与弊
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

    网站地图: 企业信息 工商信息 财税知识 网络常识 编程技术

    友情链接: 武汉网站建设