引入的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; //学校idprivate Integer projectId; //项目idprivate Integer leafId; //小节idprivate Integer leafTypeId; //小节类型private Integer chapterId; //章节idprivate 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> {// 定义一个全局变量用来保存所有连接的客户端Channelprivate static final Set<Channel> connectedChannels = Collections.newSetFromMap(new ConcurrentHashMap<>());// 当有新的连接时,将Channel添加到集合中public void handlerAdded(ChannelHandlerContext ctx) {connectedChannels.add(ctx.channel());}// 当连接关闭时,从集合中移除该Channelpublic void handlerRemoved(ChannelHandlerContext ctx) {connectedChannels.remove(ctx.channel());}@Overrideprotected 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>() {@Overrideprotected 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');});}
///--------------------------------------------------这是scoketlet 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');});},