IO/NIO交互模拟及渐进式实现
IO
IO Server
public class SocketServer {public static void main(String[] args) {//server编号和client编号对应,优缺点注释在server端//server1();//server2();server3();}/*** server1的缺点:* 1、accept()方法阻塞了线程,要等客户端连接后才能继续处理(一个客户端连接,对应一个服务端处理线程)* 2、当客户端与服务端完成一次交互后,程序就结束了* 3、流关闭代码比较臃肿、BufferedWriter的内容需要在末尾加'\n'* 4、交互的内容写死,不可以通过控制台输入* 5、端口号固定、ip固定、readLine读取一行等等*/public static void server1() {ServerSocket serverSocket = null;BufferedReader bufferedReader = null;BufferedWriter bufferedWriter = null;try {serverSocket = new ServerSocket(8999);//阻塞至客户端连接成功Socket socket = serverSocket.accept();bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));//readLine会阻塞String s = bufferedReader.readLine();System.out.println("服务端接收到客户端的消息:" + s);bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));bufferedWriter.write("服务端发送消息给客户端\n");bufferedWriter.flush();} catch (IOException e) {throw new RuntimeException(e);} finally {//各个try catch 必须分开写,聚合成一个会导致一个流关闭异常,无法进入其他流的关闭流程if(serverSocket != null) {try {serverSocket.close();} catch (IOException e) {throw new RuntimeException(e);}}if(bufferedWriter != null) {try {bufferedWriter.close();} catch (IOException e) {throw new RuntimeException(e);}}//只需要关闭外层的缓冲区,其close方法内部关闭了了传入的流//如果不关闭,只是等待jvm兜底finally,会在不确定的时间内对资源造成占用(如果是文件读写会对文件描述符fd的占用)if (bufferedReader != null) {try {bufferedReader.close();} catch (IOException e) {throw new RuntimeException(e);}}}}/*** server2优点:* 1、服务端和客户端可以任意次交互,可以连续发送消息* 2、优化了流关闭的写法** server2的缺点:* 1、accept()方法阻塞了线程,要等客户端连接后才能继续处理(一个客户端连接,对应一个服务端处理线程)* 2、cpu空转* 3、ip固定等等* 4、一个服务端只能和一个客户端交互*/public static void server2() {System.out.println("请输入端口号,并等待客户端连接...");try (BufferedReader consoleReader = new BufferedReader(new InputStreamReader(System.in));ServerSocket serverSocket = new ServerSocket(Integer.valueOf(consoleReader.readLine()));Socket socket = serverSocket.accept();BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));PrintWriter printWriter = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));){System.out.println("客户端已连接,开始和客户端交互...");//这个循环保证可以连续发送或者接收多条消息while (true) {if (bufferedReader.ready()) {System.out.println("收到客户端的消息:" + bufferedReader.readLine());}if (consoleReader.ready()) {printWriter.println(consoleReader.readLine());printWriter.flush();}}//只能发一次接收一次
// while (true) {
// System.out.println("收到客户端的消息:" + bufferedReader.readLine());
//
// printWriter.println(consoleReader.readLine());
// printWriter.flush();
// }} catch (IOException e) {throw new RuntimeException(e);}}/*** server3优点:* 一个服务端可以和一个客户端交互* 加上了线程池** server3的缺点:* 1、accept()方法阻塞了线程,要等客户端连接后才能继续处理(一个客户端连接,对应一个服务端处理线程)* 2、cpu空转* 3、ip固定等等* 4、如果开启多个客户端,因System.in被服务端共享,所以服务端发送消息后,客户端会随机接收其中个别消息*/public static void server3() {ThreadPoolExecutor pool = new ThreadPoolExecutor(0, Runtime.getRuntime().availableProcessors() * 2,60L, TimeUnit.SECONDS,new SynchronousQueue<Runnable>());System.out.println("请输入端口号,并等待客户端连接...");try (BufferedReader consoleReader = new BufferedReader(new InputStreamReader(System.in));ServerSocket serverSocket = new ServerSocket(Integer.valueOf(consoleReader.readLine()));){//这个循环保证多个客户端连接while (true) {Thread.sleep(1000);Socket socket = serverSocket.accept();System.out.println("客户端已连接,开始和客户端交互...");pool.submit(new Thread(()->{try(BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));PrintWriter printWriter = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));) {while (true) {Thread.sleep(1000);if(bufferedReader.ready()) {System.out.println("收到客户端"+ Thread.currentThread() +"的消息:" + bufferedReader.readLine());}if (consoleReader.ready()) {printWriter.println(consoleReader.readLine());printWriter.flush();}}} catch (IOException e) {throw new RuntimeException(e);} catch (InterruptedException e) {throw new RuntimeException(e);} finally {if(socket != null) {try {socket.close();} catch (IOException e) {throw new RuntimeException(e);}}}}));}} catch (IOException e) {throw new RuntimeException(e);} catch (InterruptedException e) {throw new RuntimeException(e);}}
}
IO Client
public class SocketClient {public static void main(String[] args) {//client1();//client2();client3();}public static void client1() {Socket socket = null;BufferedReader bufferedReader = null;BufferedWriter bufferedWriter = null;try {socket = new Socket("127.0.0.1", 8999);bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));//换行符必不可少,不然服务端readLine()无法判断一行已经写完bufferedWriter.write("客户端发送消息给服务端\n");bufferedWriter.flush();bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));String s = bufferedReader.readLine();System.out.println("客户端接收到服务端的消息:" + s);} catch (IOException e) {throw new RuntimeException(e);} finally {if(socket != null) {try {socket.close();} catch (IOException e) {throw new RuntimeException(e);}}if(bufferedWriter != null) {try {bufferedWriter.close();} catch (IOException e) {throw new RuntimeException(e);}}if (bufferedReader != null) {try {bufferedReader.close();} catch (IOException e) {throw new RuntimeException(e);}}}}public static void client2() {System.out.println("请输入端口号:");try (BufferedReader consoleReader = new BufferedReader(new InputStreamReader(System.in));Socket socket = new Socket("127.0.0.1", Integer.valueOf(consoleReader.readLine()));PrintWriter printWriter = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));){System.out.println("连接成功,开始和服务端交互");//可以连续发送或者接收多条消息while (true) {Thread.sleep(1000);if (bufferedReader.ready()) {System.out.println("收到服务端的消息:" + bufferedReader.readLine());}if (consoleReader.ready()) {printWriter.println(consoleReader.readLine());printWriter.flush();}}//只能发一次接收一次
// while (true) {
// printWriter.println(consoleReader.readLine());
// printWriter.flush();
//
// System.out.println("收到服务端的消息:" + bufferedReader.readLine());
// }} catch (IOException e) {throw new RuntimeException(e);} catch (InterruptedException e) {throw new RuntimeException(e);}}public static void client3() {System.out.println("请输入端口号:");try (BufferedReader consoleReader = new BufferedReader(new InputStreamReader(System.in));Socket socket = new Socket("127.0.0.1", Integer.valueOf(consoleReader.readLine()));PrintWriter printWriter = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));){System.out.println("连接成功,开始和服务端交互");//可以连续发送或者接收多条消息while (true) {if (bufferedReader.ready()) {System.out.println("收到服务端的消息:" + bufferedReader.readLine());}if (consoleReader.ready()) {printWriter.println(consoleReader.readLine());printWriter.flush();}}} catch (IOException e) {throw new RuntimeException(e);}}
}
NIO
NIO Server
public class SocketServer {public static void main(String[] args) {//server1();//server2();//server3();//server4();server5();}/*** 优点:NIO非阻塞方式,连接不会阻塞、读写不会阻塞* 缺点:* 1、当客户端与服务端完成一次交互后,程序就结束了* 2、交互的内容写死,不可以通过控制台输入* 3、cpu空转* 4、未使用selector多路复用器,其编程其实还是类似与BIO形式(服务端还是每个线程对应一个客户端)*/private static void server1() {try (ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();){serverSocketChannel.socket().bind(new InetSocketAddress(9999));serverSocketChannel.configureBlocking(false);//accept设置了非阻塞,因此需要放置在循环中使用,否则程序直接结束了while (true) {Thread.sleep(1000);SocketChannel socketChannel = serverSocketChannel.accept();if(socketChannel != null) {System.out.println("客户端已连接,开始和客户端交互...");socketChannel.configureBlocking(false);ByteBuffer readBuffer = ByteBuffer.allocate(1024);socketChannel.read(readBuffer);readBuffer.clear();System.out.println("接收到客户端消息: " + new String(readBuffer.array(), "utf-8").trim());ByteBuffer writeBuffer = ByteBuffer.wrap("发送消息给客户端".getBytes());socketChannel.write(writeBuffer);}}} catch (IOException e) {throw new RuntimeException(e);} catch (InterruptedException e) {throw new RuntimeException(e);}}/*** 改良:* 1、支持客户端和服务端一对一交互,多发* 缺点:* 1、不支持一个客户端对多个服务端* 2、如果开启多个客户端,因System.in被服务端共享,所以服务端发送消息后,客户端会随机接收其中个别消息* 3、cpu空转* 4、未使用selector多路复用器,其编程其实还是类似与BIO形式(服务端还是每个线程对应一个客户端)*/private static void server2() {try (ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();BufferedReader consoleReader = new BufferedReader(new InputStreamReader(System.in));){serverSocketChannel.socket().bind(new InetSocketAddress(9999));serverSocketChannel.configureBlocking(false);//accept设置了非阻塞,因此需要放置在循环中使用,否则程序直接结束了while (true) {Thread.sleep(1000);SocketChannel socketChannel = serverSocketChannel.accept();if(socketChannel != null) {System.out.println("客户端已连接,开始和客户端交互...");socketChannel.configureBlocking(false);ByteBuffer readBuffer = ByteBuffer.allocate(1024);while (true) {if(socketChannel.read(readBuffer) > 0) {System.out.println("接收到客户端消息: " + new String(readBuffer.array(), "utf-8").trim());readBuffer.clear();}if (consoleReader.ready()) {ByteBuffer writeBuffer = ByteBuffer.wrap(consoleReader.readLine().getBytes());socketChannel.write(writeBuffer);writeBuffer.clear();}Thread.sleep(1000);}}}} catch (IOException e) {throw new RuntimeException(e);} catch (InterruptedException e) {throw new RuntimeException(e);}}/*** 改良:* 1、支持一个客户端对多个服务端* 缺点:* 1、cpu空转* 2、未使用selector多路复用器,其编程其实还是类似与BIO形式(服务端还是每个线程对应一个客户端)*/private static void server3() {try (ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();BufferedReader consoleReader = new BufferedReader(new InputStreamReader(System.in));) {serverSocketChannel.socket().bind(new InetSocketAddress(9999));serverSocketChannel.configureBlocking(false);List<SocketChannel> socketChannels = new ArrayList<>();//accept设置了非阻塞,因此需要放置在循环中使用,否则程序直接结束了while (true) {Thread.sleep(1000);boolean ready = consoleReader.ready();byte[] bytes = null;if (ready) {bytes = consoleReader.readLine().getBytes();}//调用一次accept再次使用会变成成null,除非有新的客户端连接SocketChannel socketChannel = serverSocketChannel.accept();if (socketChannel != null) {socketChannels.add(socketChannel);socketChannel.configureBlocking(false);System.out.println("客户端已连接,开始和客户端交互...");}for (SocketChannel channel : socketChannels) {ByteBuffer readBuffer = ByteBuffer.allocate(1024);if (channel.read(readBuffer) > 0) {System.out.println("接收到客户端消息: " + new String(readBuffer.array(), "utf-8").trim());readBuffer.clear();}if (ready) {ByteBuffer writeBuffer = ByteBuffer.wrap(bytes);channel.write(writeBuffer);writeBuffer.clear();}}}} catch (IOException e) {throw new RuntimeException(e);} catch (InterruptedException e) {throw new RuntimeException(e);}}/*** 改良:* 1、支持一个客户端对多个服务端 (服务端发送消息,客户端都能收到,所有客户端发送消息服务端都能收到)* 2、相对与server3多线程方式,服务端只需要启动一个主线程即可与所有客户端交互,* 缺点:* 1、cpu空转* 2、未使用selector多路复用器,其编程其实还是类似与BIO形式(服务端还是每个线程对应一个客户端)*/static final List<SocketChannel> socketChannels4 = new CopyOnWriteArrayList<>();private static void server4() {try (ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();BufferedReader consoleReader = new BufferedReader(new InputStreamReader(System.in));) {serverSocketChannel.socket().bind(new InetSocketAddress(9999));serverSocketChannel.configureBlocking(false);//accept设置了非阻塞,因此需要放置在循环中使用,否则程序直接结束了while (true) {SocketChannel socketChannel = serverSocketChannel.accept();if (socketChannel != null) {System.out.println("客户端已连接,开始和客户端交互...");socketChannel.configureBlocking(false);socketChannels4.add(socketChannel);}Iterator<SocketChannel> iterator = socketChannels4.iterator();boolean ready = consoleReader.ready();byte[] writeBytes = null;if (ready) {writeBytes = consoleReader.readLine().getBytes();}while (iterator.hasNext()) {ByteBuffer readBuffer = ByteBuffer.allocate(1024);SocketChannel channel = iterator.next();if (channel.read(readBuffer) > 0) {System.out.println("接收到客户端消息: " + new String(readBuffer.array(), "utf-8").trim());readBuffer.clear();}if (ready) {ByteBuffer writeBuffer = ByteBuffer.wrap(writeBytes);channel.write(writeBuffer);writeBuffer.clear();}}Thread.sleep(1000);}} catch (IOException | InterruptedException e) {throw new RuntimeException(e);}}/*** 改良:* 1、支持一个客户端对多个服务端 (服务端发送消息,客户端都能收到,所有客户端发送消息服务端都能收到)* 2、相对与server3多线程方式,服务端只需要启动一个主线程即可与所有客户端交互,* 缺点:* 1、cpu空转* 2、未使用selector多路复用器,其编程其实还是类似与BIO形式(服务端还是每个线程对应一个客户端)*/private static void server5() {try (ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();Selector selector = Selector.open();BufferedReader consoleReader = new BufferedReader(new InputStreamReader(System.in));) {serverSocketChannel.socket().bind(new InetSocketAddress(9999));serverSocketChannel.configureBlocking(false);//将serverSocketChannel注册到selector, 并监听accept事件serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);List<SocketChannel> socketChannels = new ArrayList<>();while (true) {//非阻塞selector.select(1000);Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();while (iterator.hasNext()) {SelectionKey selectionKey = iterator.next();if(selectionKey.isAcceptable()) {SocketChannel socketChannel = serverSocketChannel.accept();System.out.println("客户端已连接,开始和客户端交互...");socketChannel.configureBlocking(false);socketChannel.register(selector, SelectionKey.OP_READ);socketChannels.add(socketChannel);} else if(selectionKey.isReadable()) {SocketChannel socketChannel = (SocketChannel)selectionKey.channel();ByteBuffer readBuffer = ByteBuffer.allocate(1024);if (socketChannel.read(readBuffer) > 0) {System.out.println("接收到客户端消息: " + new String(readBuffer.array(), "utf-8").trim());readBuffer.clear();}}iterator.remove();}if(consoleReader.ready()) {byte[] bytes = consoleReader.readLine().getBytes();for (SocketChannel socketChannel : socketChannels) {ByteBuffer writeBuffer = ByteBuffer.wrap(bytes);socketChannel.write(writeBuffer);writeBuffer.clear();}}}} catch (IOException e) {throw new RuntimeException(e);}}}
NIO Client
public class SocketClient {public static void main(String[] args) {//client1();//client2_3_4();client5();}private static void client1() {try (SocketChannel socketChannel = SocketChannel.open();){socketChannel.configureBlocking(false);socketChannel.connect(new InetSocketAddress("127.0.0.1", 9999));while (!socketChannel.finishConnect()) {Thread.sleep(1000);System.out.println("正在连接客户端...");}ByteBuffer writeBuffer = ByteBuffer.wrap("向服务端发送消息".getBytes());socketChannel.write(writeBuffer);writeBuffer.clear();ByteBuffer readBuffer = ByteBuffer.allocate(1024);while (true) {if(socketChannel.read(readBuffer) > 0) {System.out.println("接收到服务端消息: " + new String(readBuffer.array(), "utf-8").trim());readBuffer.clear();break;}Thread.sleep(1000);}} catch (IOException | InterruptedException e) {throw new RuntimeException(e);}}private static void client2_3_4() {try (SocketChannel socketChannel = SocketChannel.open();BufferedReader consoleReader = new BufferedReader(new InputStreamReader(System.in));){socketChannel.configureBlocking(false);socketChannel.connect(new InetSocketAddress("127.0.0.1", 9999));while (!socketChannel.finishConnect()) {Thread.sleep(1000);System.out.println("正在连接客户端...");}ByteBuffer readBuffer = ByteBuffer.allocate(1024);while (true) {if(socketChannel.read(readBuffer) > 0) {System.out.println("接收到服务端消息: " + new String(readBuffer.array(), "utf-8").trim());readBuffer.clear();}if (consoleReader.ready()) {ByteBuffer writeBuffer = ByteBuffer.wrap(consoleReader.readLine().getBytes());socketChannel.write(writeBuffer);writeBuffer.clear();}Thread.sleep(1000);}} catch (IOException | InterruptedException e) {throw new RuntimeException(e);}}private static void client5() {try (SocketChannel socketChannel = SocketChannel.open(new InetSocketAddress("127.0.0.1", 9999));Selector selector = Selector.open();BufferedReader consoleReader = new BufferedReader(new InputStreamReader(System.in));){socketChannel.configureBlocking(false);socketChannel.register(selector, SelectionKey.OP_READ);while (true) {selector.select(1000);Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();while (iterator.hasNext()) {SelectionKey selectionKey = iterator.next();if (selectionKey.isReadable()) {SocketChannel channel = (SocketChannel) selectionKey.channel();ByteBuffer readBuffer = ByteBuffer.allocate(1024);if(channel.read(readBuffer) > 0) {System.out.println("接收到服务端消息: " + new String(readBuffer.array(), "utf-8").trim());readBuffer.clear();}}iterator.remove();}if (consoleReader.ready()){ByteBuffer writeBuffer = ByteBuffer.wrap(consoleReader.readLine().getBytes());socketChannel.write(writeBuffer);writeBuffer.clear();}}} catch (IOException e) {throw new RuntimeException(e);}}}
相关文章:
IO/NIO交互模拟及渐进式实现
IO IO Server public class SocketServer {public static void main(String[] args) {//server编号和client编号对应,优缺点注释在server端//server1();//server2();server3();}/*** server1的缺点:* 1、accept()方法阻塞了线程,要等客户端…...
springboot+html实现密码重置功能
目录 登录注册: 前端: chnangePssword.html 后端: controller: Mapper层: 逻辑: 登录注册: https://blog.csdn.net/m0_67930426/article/details/133849132 前端: 通过点击忘记密码跳转…...
LeetCode 2525. 根据规则将箱子分类【模拟】1301
本文属于「征服LeetCode」系列文章之一,这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁,本系列将至少持续到刷完所有无锁题之日为止;由于LeetCode还在不断地创建新题,本系列的终止日期可能是永远。在这一系列刷题文章…...
atcoder [Road of the King] 题解(DP好题)
题面 简要题意:有一个 n n n 个点的图,目前一条边都没有。有一个人在 1 1 1 号点要进行 m m m 次移动, 终点不必是 1 1 1 号点。加入第 i i i 次的从 u u u 移动到了 v v v, 那么 u u u 到 v v v 之间出现一条有向边。问…...
CImageList 图像列表
一、CImageList类Create函数参数解析 BOOL Create(int cx,int cy,UINT nFlags,int nInitial,int nGrow ); 1.1) cx,cy:图片的实际像素宽与高; nFlags:创建图像列表的类型,包括4/8/16/24/32/位色; nFlags确定建立图…...
【OpenGL】四、坐标系统和摄像机
坐标转换 文章目录 坐标转换坐标系统的转换局部空间(Local Space)->世界空间(World Space)世界空间(World Space)->观察空间(View Space/View Space)裁剪空间(Clip Space)MVP矩阵 坐标系统的转换 了解坐标系统和空间变换之前需要先了解…...
使用vcpkg管理依赖第三库
文章目录 使用vcpkg管理依赖第三库vcpkg安装vcpkg经典模式使用从仓库列表搜索依赖项从某个基线版本的列表中查询某个依赖项信息安装依赖库 vcpkg清单模式的使用vcpkg清单模式的使用例子说明 使用vcpkg管理依赖第三库 vcpkg 有两种操作模式:经典模式和清单模式。 在…...
Android渲染一个列表的过程,并提供动态改变样式
1、index.xml 布局文件,我省略了其他代码,我们需要recyclerview保证在规定范围内,如果列表元素过多可以滑动 <LinearLayoutandroid:layout_width"match_parent"android:layout_height"match_parent"android:layout_…...
Leetcode—260.只出现一次的数字III【中等】
2023每日刷题(三) Leetcode—260.只出现一次的数字III 借助lowbit的解题思想 参考的灵茶山艾府大神的题解 实现代码 /*** Note: The returned array must be malloced, assume caller calls free().*/ int* singleNumber(int* nums, int numsSize, in…...
Mysql 约束,基本查询,复合查询与函数
文章目录 约束空属性约束默认值约束zerofill主键约束自增长约束唯一键约束外键约束 查询select的执行顺序单表查询排序 updatedelete整张表的拷贝复合语句group by分组查询 函数日期函数字符串函数数学函数其他函数 复合查询合并查询union 约束 空属性约束 两个值:…...
web前端基础CSS------美化页面“footer”部分
一,实验代码 <!DOCTYPE html> <html><head><meta charset"utf-8"><title>关于我们</title><style type"text/css">#footer{margin: 10px 0px;background: #f5f5f5;border: top 1px solid #eee ;}#f…...
在中国,技术到底有多有用?
🙌秋名山码民的主页 😂oi退役选手,Java、大数据、单片机、IoT均有所涉猎,热爱技术,技术无罪 🎉欢迎关注🔎点赞👍收藏⭐️留言📝 获取源码,添加WX 目录 前言1.…...
《动手学深度学习 Pytorch版》 9.2 长短期记忆网络(LSTM)
解决隐变量模型长期信息保存和短期输入缺失问题的最早方法之一是长短期存储器(long short-term memory,LSTM)。它与门控循环单元有许多一样的属性。长短期记忆网络的设计比门控循环单元稍微复杂一些,却比门控循环单元早诞生了近 2…...
计算机操作系统-第十一天
目录 1、进程的状态 创建态与就绪态 运行态 终止态 新建态 结束态 进程状态的转换 进程的组织方式 链接方式(常见) 索引方式(少见) 本节思维导图 1、进程的状态 创建态与就绪态 1、进程正在被创建时,处于…...
Flutter视图原理之StatefulWidget,InheritedWidget
目录 StatefulElement1. 构造函数2. build3. _firstBuild3. didChangeDependencies4. setState InheritedElement1. Element类2. _updateInheritance3. InheritedWidget数据向下传递3.1 dependOnInheritedWidgetOfExactType 4. InheritedWidget的状态绑定4.1. ProxyElement 在f…...
观察者模式-对象间的联动
有个商城小程序,用户希望当有新品上市的时候能通知他们。这样用户就可以不要时刻盯着小程序了。在这个场景中,用户向小程序订阅了一个服务——发送新品短信。小程序在有新品上线时负责向订阅客户发出这个消息。 这就是发布-订阅模式,也称观察…...
Webpack十大缺点:当过度工程化遇上简单的静态页面
🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云…...
新手指南|如何快速参与Moonbeam Ignite
Moonbeam Ignite是社区熟悉的有奖链上交互活动,将有300万枚GLMR作为生态激励注入Moonbeam生态系统,体验MoonbeamMoonbeam生态的应用即可获取相应Token奖励。Beamex/Beamswap、Moonwell和Gamma作为首批参与Moonbeam Ignite的三家项目方,将在活…...
VR航天科普主题公园模拟太空舱体验馆vr航天模拟体验设备
VR航天航空体验馆巡展是一项非常受欢迎的展览活动,可以让公众在现场体验到航天飞行的乐趣。 普乐蛙VR展览组织者会设计一个航天航空主题的VR体验馆,并在馆内设置各种航天航空相关的展示内容,如太空舱、火箭发射、星际航行等。 其次࿰…...
Spring Boot OAuth 2.0整合详解
目录 一、Spring Boot 2.x 示例 1、初始化设置 2、设置重定向URI 3、配置 application.yml 4、启动应用程序 二、Spring Boot 2.x 属性映射 二、CommonOAuth2Provider 三、配置自定义提供者(Provider)属性 四、覆盖 Spring Boot 2.x 的自动配置…...
【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型
摘要 拍照搜题系统采用“三层管道(多模态 OCR → 语义检索 → 答案渲染)、两级检索(倒排 BM25 向量 HNSW)并以大语言模型兜底”的整体框架: 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后,分别用…...
Cursor实现用excel数据填充word模版的方法
cursor主页:https://www.cursor.com/ 任务目标:把excel格式的数据里的单元格,按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例,…...
(十)学生端搭建
本次旨在将之前的已完成的部分功能进行拼装到学生端,同时完善学生端的构建。本次工作主要包括: 1.学生端整体界面布局 2.模拟考场与部分个人画像流程的串联 3.整体学生端逻辑 一、学生端 在主界面可以选择自己的用户角色 选择学生则进入学生登录界面…...
UE5 学习系列(三)创建和移动物体
这篇博客是该系列的第三篇,是在之前两篇博客的基础上展开,主要介绍如何在操作界面中创建和拖动物体,这篇博客跟随的视频链接如下: B 站视频:s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个生活电费的缴纳和查询小程序
一、项目初始化与配置 1. 创建项目 ohpm init harmony/utility-payment-app 2. 配置权限 // module.json5 {"requestPermissions": [{"name": "ohos.permission.INTERNET"},{"name": "ohos.permission.GET_NETWORK_INFO"…...
今日科技热点速览
🔥 今日科技热点速览 🎮 任天堂Switch 2 正式发售 任天堂新一代游戏主机 Switch 2 今日正式上线发售,主打更强图形性能与沉浸式体验,支持多模态交互,受到全球玩家热捧 。 🤖 人工智能持续突破 DeepSeek-R1&…...
代理篇12|深入理解 Vite中的Proxy接口代理配置
在前端开发中,常常会遇到 跨域请求接口 的情况。为了解决这个问题,Vite 和 Webpack 都提供了 proxy 代理功能,用于将本地开发请求转发到后端服务器。 什么是代理(proxy)? 代理是在开发过程中,前端项目通过开发服务器,将指定的请求“转发”到真实的后端服务器,从而绕…...
《C++ 模板》
目录 函数模板 类模板 非类型模板参数 模板特化 函数模板特化 类模板的特化 模板,就像一个模具,里面可以将不同类型的材料做成一个形状,其分为函数模板和类模板。 函数模板 函数模板可以简化函数重载的代码。格式:templa…...
iview框架主题色的应用
1.下载 less要使用3.0.0以下的版本 npm install less2.7.3 npm install less-loader4.0.52./src/config/theme.js文件 module.exports {yellow: {theme-color: #FDCE04},blue: {theme-color: #547CE7} }在sass中使用theme配置的颜色主题,无需引入,直接可…...
android13 app的触摸问题定位分析流程
一、知识点 一般来说,触摸问题都是app层面出问题,我们可以在ViewRootImpl.java添加log的方式定位;如果是touchableRegion的计算问题,就会相对比较麻烦了,需要通过adb shell dumpsys input > input.log指令,且通过打印堆栈的方式,逐步定位问题,并找到修改方案。 问题…...
