maven项目使用netty,前端是vue2,实现通讯

news2024/12/23 6:50:41

引入的java包

<!--        以下是即时通讯-->
        <!-- Netty core modules  -->
        <dependency>
            <groupId>io.netty</groupId>
            <artifactId>netty-all</artifactId>
            <version>4.1.76.Final</version> <!-- 使用最新的稳定版本 -->
        </dependency>
        <!-- Optional: Support for WebSocket -->
        <dependency>
            <groupId>io.netty</groupId>
            <artifactId>netty-handler-proxy</artifactId>
            <version>4.1.76.Final</version>
        </dependency>
        <!-- Optional: Support for HTTP/2 -->
        <dependency>
            <groupId>io.netty</groupId>
            <artifactId>netty-resolver-dns-native-macos</artifactId>
            <version>4.1.76.Final</version>
            <classifier>osx-x86_64</classifier>
            <optional>true</optional>
        </dependency>

2.创建project对象(这个对象是跟业务相关的,如果业务简单,不创建也可以,最后传输的都是字符串)

@Getter
@Setter
public class Project {
    private GroupStudentService groupStudentService;
    private Integer schoolId;  //学校id
    private Integer projectId;  //项目id
    private Integer leafId;  //小节id
    private Integer leafTypeId;  //小节类型
    private Integer chapterId;  //章节id
    private Object currentLeaf;//当前小节
    private  Integer currentLeafIndex;//当前小节的下标
    private  Integer currentChapterIndex;//当前章节的下标


    public Project(Integer projectId,
                   Integer leafId,
                   Integer leafTypeId,
                   Integer chapterId,
                   Object currentLeaf,
                   Integer currentLeafIndex,
                   Integer currentChapterIndex,Integer schoolId) {
        this.projectId = projectId;
        this.leafId = leafId;
        this.leafTypeId = leafTypeId;
        this.chapterId = chapterId;
        this.currentLeaf = currentLeaf;
        this.currentLeafIndex = currentLeafIndex;
        this.currentChapterIndex = currentChapterIndex;
        this.schoolId= schoolId;

    }

    public Project() {
    }

3.创建WebsocketHandler

public class WebsocketHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {

    // 定义一个全局变量用来保存所有连接的客户端Channel
    private static final Set<Channel> connectedChannels = Collections.newSetFromMap(new ConcurrentHashMap<>());

    // 当有新的连接时,将Channel添加到集合中
    public void handlerAdded(ChannelHandlerContext ctx) {
        connectedChannels.add(ctx.channel());
    }

    // 当连接关闭时,从集合中移除该Channel
    public void handlerRemoved(ChannelHandlerContext ctx) {
        connectedChannels.remove(ctx.channel());
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) {
        String text = msg.text();
        String prefix = text.substring(0, 7); //截取前缀
        if (prefix.contains("switch")) {//当前数据是切换小节
            handleSwitch(text.substring(7));
        } else if (prefix.contains("xsData")) {//当前数据是学生提交作业给老师的
           handleStudentData(text.substring(7));
        }
    }

    //这个是专门用来切换小节的,老师切换上一节,下一节,跳到指定小节,学生的大屏页面也跟着切换
    private void handleSwitch(String parts) {
        //把parts转成jsonobject对象
        JSONObject jsonObject = JSON.parseObject(parts);
        Integer projectId = (int) jsonObject.get("projectId");
        Integer leafId = (int) jsonObject.get("leafId");
        Integer leafTypeId = (int) jsonObject.get("leafTypeId");
        Integer chapterId = (int) jsonObject.get("chapterId");
        Integer currentLeafIndex = (int) jsonObject.get("currentLeafIndex");
        Integer currentChapterIndex = (int) jsonObject.get("currentChapterIndex");
        Object currentLeaf = jsonObject.get("currentLeaf");
        Integer schoolId = (int) jsonObject.get("institutionId");
        Project project = new Project(projectId,
                leafId,
                leafTypeId,
                chapterId,
                currentLeaf,
                currentLeafIndex,
                currentChapterIndex, schoolId);
        Gson gson = new Gson();
        String jsonProject = gson.toJson(project);
        if (project != null) {
            for (Channel channel : connectedChannels) {
                if (channel.isActive()) { // 检查通道是否仍然活跃
                    channel.writeAndFlush(new TextWebSocketFrame("switch:" + jsonProject));
                }
            }

        }
    }
    //这个是专门用来学生提交数据的,学生提交数据,老师大屏上能展示数据
    private void handleStudentData(String parts) {
        //把parts转成jsonobject对象
        JSONObject jsonObject = JSON.parseObject(parts);
        Integer projectId =Integer.valueOf(jsonObject.get("projectId").toString());
        Integer leafId = Integer.valueOf(jsonObject.get("leafId").toString());
        Integer schoolId = Integer.valueOf( jsonObject.get("institutionId").toString());
        Project project = new Project();
        project.setProjectId(projectId);
        project.setSchoolId(schoolId);
        project.setLeafId(leafId);
        Gson gson = new Gson();
        String jsonProject = gson.toJson(project);
        if (project != null) {
            for (Channel channel : connectedChannels) {
                if (channel.isActive()) { // 检查通道是否仍然活跃
                    channel.writeAndFlush(new TextWebSocketFrame("xsData:" + jsonProject));
                }
            }

        }
    }

4.创建WebsocketServer启动类

public class WebsocketServer {
    public static void main(String[] args) throws InterruptedException {
        initWebsocket();
    }

      public static void initWebsocket() throws InterruptedException {
            EventLoopGroup bossGroup = new NioEventLoopGroup();
            EventLoopGroup workerGroup = new NioEventLoopGroup();
            try {
                ServerBootstrap b = new ServerBootstrap();
                b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel ch) {
                    System.out.println("初始化WebsocketServer");
                        ChannelPipeline p = ch.pipeline();
                        p.addLast(new HttpServerCodec());
                        p.addLast(new HttpObjectAggregator(65536));
                        p.addLast(new ChunkedWriteHandler());
                        p.addLast(new WebSocketServerProtocolHandler("/screen"));
                        p.addLast(new WebsocketHandler());
                    }
                });
                ChannelFuture f = b.bind(8084).sync();
                f.channel().closeFuture().sync();
            } finally {
                workerGroup.shutdownGracefully();
                bossGroup.shutdownGracefully();
            }
       }

}

5.页面上的发送数据

connectWebSocket() {
				this.socket = new WebSocket('ws://' + window.location.hostname + ':8084/screen');
				this.socket.addEventListener('open', (event) => {
					console.log('WebSocket connection opened--学生');
				});
				this.socket.addEventListener('message', (event) => {
					console.log(event);
				});
				this.socket.addEventListener('error', (event) => {
					console.error('WebSocket error:', event);
				});
				this.socket.addEventListener('close', (event) => {
					console.log('WebSocket connection closed');
				});
			}

///--------------------------------------------------这是scoket
							let sendData = {
								projectId: this.projectId,
								leafId: this.leafId,
								institutionId: JSON.parse(localStorage.getItem('user')).institutionId
							};
							console.log(sendData)
							// 将数据对象转化为JSON字符串
							let jsonData = JSON.stringify(sendData);
							let prefixedData = 'xsData:' + jsonData;
							this.socket.send(prefixedData);
							///----------------------------------------------------------------

6.页面上接收数据

initWebSocket() {
				this.socket = new WebSocket(`ws://${window.location.hostname}:8084/screen`);
				this.socket.addEventListener('open', (event) => {
					console.log('WebSocket connection opened');
				});
				this.socket.addEventListener('message', (event) => {
					const data = event.data;
					if (data.startsWith('xsData:')) {
						const jsonData = data.substring(7);
						const vo = JSON.parse(jsonData);
						if (vo.schoolId == JSON.parse(localStorage.getItem('user')).institutionId &&
							vo.projectId == this.projectId && vo.leafId == this.leafId
						) {
							this.getQd();
						} else {
							console.log("无效信息")
						}
					}
				});
				this.socket.addEventListener('error', (event) => {
					console.error('WebSocket error:', event);
				});

				this.socket.addEventListener('close', (event) => {
					console.log('WebSocket connection closed');
				});
			},

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1898939.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C++中的引用——引用的注意事项

1.引用必须初始化 2.引用在初始化后不可以改变 示例&#xff1a; 运行结果&#xff1a;

03:EDA的进阶使用

使用EDA设计一个38译码器电路和245放大电路 1、38译码器1.1、查看74HC138芯片数据1.2、电路设计 2、245放大电路2.1、查看数据手册2.2、设计电路 3、绘制PCB3.1、导入3.2、放置3.3、飞线3.4、特殊方式连接GND3.5、泪滴3.6、配置丝印和划分区域3.7、添加typc接口供电 1、38译码器…

案例精选 | 聚铭网络助力南京市玄武区教育局构建内网日志审计合规体系

南京市玄武区教育局作为江苏省教育领域的先锋机构&#xff0c;其工作重点涵盖了教育政策的实施、教育现代化与信息化的融合、教育资源的优化、教育质量的提升以及教育公平的促进。在这一背景下&#xff0c;网络安全管理成为了确保教育信息化顺利推进的关键环节之一。 根据玄武…

【CV炼丹师勇闯力扣训练营 Day24:§7 回溯3】

CV炼丹师勇闯力扣训练营 代码随想录算法训练营第24天 93 复原IP地址 有效 IP 地址 正好由四个整数&#xff08;每个整数位于 0 到 255 之间组成&#xff0c;且不能含有前导 0&#xff09;&#xff0c;整数之间用 ‘.’ 分隔。 例如&#xff1a;“0.1.2.201” 和 “192.168.…

tensorboard安装失败,怎么办?

标题tensorboard未安装报错&#xff0c;如下图所示&#xff1a; 解决方法尝试&#xff1a; 这些方法都可以试一下&#xff0c;因为每个人的情况可能不同&#xff0c;成功的方法也不同。 1、在pycharm中Pip失败 2、 在pycharm中Conda 失败 3、在Pycharm中换清华源失败 4、直接…

软件是什么?一个软件到底是哪些部分组成的-软件到底有哪些分支呢?

https://doc.youyacao.com/117/2163 软件是什么&#xff1f;一个软件到底是哪些部分组成的-软件到底有哪些分支呢&#xff1f; 何为软件 软件定义 的本质是通过软件编程实现硬件资源的虚拟化、灵活、多样和定制化功能&#xff0c;以最大化系统运行效率和能量效率。它基于硬…

面试题-Spring家族与SpringIOC

1.spring家族的介绍 Spring简单图&#xff1a; 2.IOC原理 IOC就是原先代码里需要开发者实现对象的创建和关系依赖&#xff0c;反转交给SpringIOC容器管理对象的生命周期和对象之间的依赖关系。 依赖注入的方式&#xff1a; Setter&#xff1a;实现特定属性的public sette…

资源监视器 查看写入磁盘的文件

"Win R" 组合键来打开运行对话框&#xff0c;然后输入 "resmon" 并按下回车键&#xff0c;或者在开始菜单中搜索 "资源监视器" 并打开它。 可以查看时哪个服务在往盘里写日志或者文件

pytest-rerunfailures:优化测试稳定性的失败重试工具

笔者在执行自动化测试用例时&#xff0c;会发现有时候用例失败并非代码问题&#xff0c;而是由于服务正在发版&#xff0c;导致请求失败&#xff0c;从而降低了自动化用例的稳定性&#xff0c;最后还要花时间定位到底是自身case的原因还是业务逻辑问题&#xff0c;还是其他原因…

vue单独部署到宝塔教程

配置反向代理 注意:如果目标网站是https则写https否则写http 2.关于解决部署后无法刷新,直接报错404 location / { try_files $uri $uri/ /index.html; }

记某大学智慧云平台存在弱口令爆破水平越权信息泄露Wx_SessionKey篡改 任意用户登录漏洞

扫码获取网安教程 0x1 前言 本篇文章是记录最近给一所大学做渗透测试时该学校存在的漏洞&#xff08;目前已经修复&#xff09;。我是先找该学校的微信小程序的资产&#xff0c;因为各位佬们也知道&#xff0c;微信小程序相对于web应用服务端来讲维护较少&#xff0c;所有漏洞…

【JavaWeb程序设计】Web基础-JavaScript

目录 一、函数与事件的使用 1. 编写一个html页面&#xff0c;使用Javascript完成数字的平方计算。 1.1 运行截图 1.2 JS代码 1.3 HTML代码 2. 要求文本框中只能输入字母 2.1 运行截图 2.2 下载jquery-3.4.1并引用 2.3 JS代码 2.4 HTML代码 3. 在文本框分别输入两个…

使用 mongo2neo4j 和 SemSpect 通过各种方式进行图探索

用于可视化和探索每个 MEAN 堆栈背后的数据图的 ETL 您是否正在努力回答有关 MEANS Web 服务数据的紧急问题&#xff1f;哪里有 BI 可以快速回答“上个季度哪些亚洲的artisan.plus 用户触发了订单&#xff1f;”这个问题&#xff0c;而无需编写查询&#xff1f;使用 mongo2neo4…

通过 Parallels Desktop 虚拟机安装运行 macOS 15 Sequoia

在 Apple 的 WWDC 24 大会上&#xff0c;macOS Sequoia 15 成为全场热议的焦点。 作为科技爱好者和开发者&#xff0c;我们都迫不及待想要体验这些最新功能。但如果直接把整个 Mac 升级到测试版&#xff0c;可能不太现实&#xff0c;特别是当你需要保持主系统稳定的时候。 幸…

速刷edurank(1)

python安全开发 python安全开发 python安全开发前言一、平台edu二、使用步骤1.引入库2.功能**完整代码**完整代码 总结 前言 目的&#xff1a;想快速的搜集edu的域名 一、平台edu https://src.sjtu.edu.cn/rank/firm/0/?page2 二、使用步骤 1.引入库 代码如下&#xff08…

序列化Serializable

一、传输对象的方式 将对象从内存传输到磁盘进行保存&#xff0c;或者进行网络传输&#xff0c;有两种方式&#xff1a; 实现Serializable接口&#xff0c;直接传输对象转成json字符串后&#xff0c;进行字符串传输 二、直接传输对象 implements Serializable Data Equal…

50岁单身女人的中等生活标准是什么?

对女人来说&#xff0c;50岁正是更年期&#xff0c;可以说是已经进入老龄行列&#xff0c;情绪难免不稳定。面对社会上对中老年人的看法&#xff0c;心中难免会有些失落。那么50岁以后的女人&#xff0c;一般希望拥有一个什么样的生活呢&#xff1f; 首先是财务独立&#xff0c…

Day44:LeedCode 188.买卖股票的最佳时机IV 309.最佳买卖股票时机含冷冻期 714.买卖股票的最佳时机含手续费

188. 买卖股票的最佳时机 IV 给你一个整数数组 prices 和一个整数 k &#xff0c;其中 prices[i] 是某支给定的股票在第 i 天的价格。 设计一个算法来计算你所能获取的最大利润。你最多可以完成 k 笔交易。也就是说&#xff0c;你最多可以买 k 次&#xff0c;卖 k 次。 注意&…

【数据分享】2002-2020年全球逐日地表土壤水分栅格数据(免费获取)

土壤水分是陆地水循环中的重要状态变量&#xff0c;在陆-气相互作用研究、区域水文过程及水资源管理等研究领域具有重要作用&#xff0c;该数据被广泛应用于各项研究。 本次我们分享的是2002-2020年全球范围的36km分辨率逐日地表土壤水分栅格数据&#xff01;数据来源于国家青…

c++习题05-斐波那契数列

目录 一&#xff0c;问题 二&#xff0c;思路 三&#xff0c;代码 一&#xff0c;问题 二&#xff0c;思路 根据题目&#xff0c;可以自己列出斐波那契数列&#xff08;前四个&#xff09;如下&#xff1a; 通过列出来的值&#xff0c;可以发现&#xff0c;前两个都是1&…