位置: 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)

  • 惠普519打印机怎么连接wifi(惠普519打印机怎么清洗打印头)

    惠普519打印机怎么连接wifi(惠普519打印机怎么清洗打印头)

  • 抖音怎么设置直播提醒(抖音怎么设置直播定时关闭)

    抖音怎么设置直播提醒(抖音怎么设置直播定时关闭)

  • 小米充电宝无法充电(小米充电宝无法给iphone充电)

    小米充电宝无法充电(小米充电宝无法给iphone充电)

  • 微信转文字失败怎么办(企业微信转文字失败)

    微信转文字失败怎么办(企业微信转文字失败)

  • netflix是什么

    netflix是什么

  • 快手收藏的显示不出来(快手收藏显示999是啥意思)

    快手收藏的显示不出来(快手收藏显示999是啥意思)

  • 可以删除字符串尾部空格的函数(删除字符串中的指定字符,字符串和要删除)

    可以删除字符串尾部空格的函数(删除字符串中的指定字符,字符串和要删除)

  • 苹果x没有指纹锁吗(苹果13有没有指纹)

    苹果x没有指纹锁吗(苹果13有没有指纹)

  • vivoy50支持5g吗(vivoy50支持电信4g吗)

    vivoy50支持5g吗(vivoy50支持电信4g吗)

  • 快手私信删了另一个手机登录能看见吗(快手私信删了另一个账号)

    快手私信删了另一个手机登录能看见吗(快手私信删了另一个账号)

  • lg电脑是什么牌子(lg电脑是什么牌子中文名)

    lg电脑是什么牌子(lg电脑是什么牌子中文名)

  • iphone11主屏幕按钮怎么设置(苹果11主屏幕键)

    iphone11主屏幕按钮怎么设置(苹果11主屏幕键)

  • 八位的二进制数+0110101的补码是(八位的二进制数10010110的补码为)

    八位的二进制数+0110101的补码是(八位的二进制数10010110的补码为)

  • 微博怎么不显示年龄(微博怎么不显示ip地址)

    微博怎么不显示年龄(微博怎么不显示ip地址)

  • 网络安全防护技术包括(网络安全防护技术有哪几种类型)

    网络安全防护技术包括(网络安全防护技术有哪几种类型)

  • 微信提示音怎么调大小(微信提示音怎么设置自定义铃声)

    微信提示音怎么调大小(微信提示音怎么设置自定义铃声)

  • iphonex怎么验机(iphonex怎样验机)

    iphonex怎么验机(iphonex怎样验机)

  • ipad air2是第几代(苹果平板ipadair2是第几代)

    ipad air2是第几代(苹果平板ipadair2是第几代)

  • vivoz3怎么隐藏刘海(vivo怎么隐藏刘海)

    vivoz3怎么隐藏刘海(vivo怎么隐藏刘海)

  • 苹果8重启方法(苹果重启方法怎么设置)

    苹果8重启方法(苹果重启方法怎么设置)

  • 淘宝短信提醒怎么取消(淘宝短信提醒怎么关?)

    淘宝短信提醒怎么取消(淘宝短信提醒怎么关?)

  • 抖音怎么用原账户登录(抖音原账号)

    抖音怎么用原账户登录(抖音原账号)

  • qq解除关系是拉黑了吗(qq解除关系会提示吗)

    qq解除关系是拉黑了吗(qq解除关系会提示吗)

  • 红米note8用的什么摄像头(红米note8用的什么闪存)

    红米note8用的什么摄像头(红米note8用的什么闪存)

  • ps分辨率的单位是什么(ps分辨率单位2怎么去掉)

    ps分辨率的单位是什么(ps分辨率单位2怎么去掉)

  • 华为p30pro后盖是什么材质(华为p30pro换后盖多少钱)

    华为p30pro后盖是什么材质(华为p30pro换后盖多少钱)

  • 已经发过的朋友圈还能设置权限吗(已经发过的朋友圈怎么改可见范围)

    已经发过的朋友圈还能设置权限吗(已经发过的朋友圈怎么改可见范围)

  • 抖音搜索对方知道吗(抖音搜索别人对方会知道吗?)

    抖音搜索对方知道吗(抖音搜索别人对方会知道吗?)

  • unalias命令  取消命令别名(unistack怎么关掉)

    unalias命令 取消命令别名(unistack怎么关掉)

  • 浙江税务网上办税大厅官网
  • 纳税调整增加额在报表的哪里
  • 特许权使用费收入
  • 个税申报人员信息采集表模板
  • 增值税加计扣除5%政策
  • 收到投资款需要缴纳什么税
  • 自建厂房出售如何计算所得税
  • 租办公用房要交房产税吗
  • 准予扣除的职工福利费
  • 房产税原价包括地价吗
  • 挂靠企业所得税怎么办?
  • 医院收到卫生局补助会计分录怎么写
  • 公司发放节日礼品
  • 开发票时税点开里怎么算?
  • 每月交的社保什么时候到账
  • 微税平台抄税的步骤是怎样的?
  • 企业以前年度的亏损在哪查
  • 营改增后餐饮业税种
  • 财务审核火车票真伪辨别
  • 加工费的增值税计入什么科目
  • 会计帐务处理程序
  • 资产处置收益期末有余额吗
  • 工会经费是不是应付职工薪酬
  • 资产负债表里的存货怎么算
  • 什么是冻结账户的情形
  • 年终奖发放与补发的区别
  • 苹果macbook 系统
  • CodeIgniter扩展核心类实例详解
  • 劳务佣金合法吗?
  • 贴现息计入什么科目
  • [ChatGPT] 从 GPT-3.5 到 GPT-5 的进化之路 | ChatGPT和程序员 : 协作 or 取代
  • 驱动开发函数详解
  • 微信小程序开发者工具
  • 专利收费的职能包括
  • 资本公积常用的计量方法
  • 增值税专用发票丢了怎么补救
  • 工商年报股东实缴出资金额能写0吗
  • 金融债券利息收入免企业所得税吗
  • 公司车转个人名下车牌需要换吗
  • sql server数据库连接端口1434
  • 经营性存款人罚款
  • 人力资源行业企业成长
  • 房地产企业土地增值税预缴
  • 无形资产账面价值和账面余额的区别
  • 商业承兑汇票怎么接收
  • 收到的现金货款转到公户备注往来款可以吗
  • 认缴制下实收资本需要验资吗
  • 三年期定期存款利率怎么算
  • 手写发票还能用么
  • SQLSERVER 中datetime 和 smalldatetime类型分析说明
  • xp系统开机按什么还原
  • 怎么禁止p2p下载器
  • 编程乱码
  • win7系统桌面快捷键
  • qbdagent2002.exe - qbdagent2002是什么进程 有什么用
  • hpm是什么格式的文件
  • win7的网络设置
  • Win8.1怎么打开无线网卡
  • windows10如何关闭快捷键
  • kcleaner是什么文件夹
  • win7系统如何连接共享打印机
  • 英雄联盟windows10
  • Win10 Mobile RedStone预览版14267已知问题与修复内容汇总
  • macbook编译java
  • node.js server-side
  • shell字符串截取加替换
  • jquery.ui
  • jquery动态添加的元素怎么添加事件
  • python中导入语句
  • unity5用什么语言
  • js模拟用户点击
  • js html css
  • jquery设置内容
  • javascript学习指南
  • python三种类型
  • python例子大全
  • 长春市税务局电话号
  • 贸易型企业进项发票
  • 广东广州税务局电话
  • 山西省税务
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

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

    友情链接: 武汉网站建设