当前位置: 首页 > news >正文

【学习笔记】手写 Tomcat 八

目录

一、NIO

1. 创建 Tomcat NIO 类

2. 启动 Tomcat

3. 测试

二、解析请求信息

三、响应数据

创建响应类

修改调用的响应类

四、完整代码

五、测试

六、总结

七、获取全部用户的功能

POJO

生成 POJO

1. 在 Dao 层定义接口

2. 获取用户数据

3. 在 Service 层定义接口

4. Service 层的实现方法

5. 创建 Servlet

6. 测试

八、作业

优化NIO


一、NIO

Non-Blocking I/O,非阻塞IO。我们之前使用的是 BIO 阻塞IO

NIO 是同步非阻塞的,服务器的实现模式是一个线程处理多个连接 

关于 NIO ,可以看看这位博主写的文章 Java NIO 详解-CSDN博客 

1. 创建 Tomcat NIO 类

package com.shao.net;import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.URLDecoder;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;public class TomcatNIO {public TomcatNIO() {// 1. 创建通信管道try {ServerSocketChannel ssc = ServerSocketChannel.open();// 2. 绑定端口ssc.bind(new InetSocketAddress(8080));// 3. 配置非阻塞通信管道ssc.configureBlocking(false);// 4. 创建一个选择器Selector selector = Selector.open();// 5. 将通信管道注册到选择器上,监听客户端连接请求的事件ssc.register(selector, SelectionKey.OP_ACCEPT);// 循环监听客户端请求并处理相应事件while (true) {System.out.println("等待连接...");// 6. 从 selectors 中选择并返回已就绪的通道数int number = selector.select();if (number == 0) continue;// 7. 这些 SelectionKey 对象代表了就绪的通道及其相应的注册事件。Iterator<SelectionKey> it = selector.selectedKeys().iterator();while (it.hasNext()) {SelectionKey key = it.next();// 8. 判断就绪事件类型if (key.isAcceptable()) {System.out.println("有客户端连接了...");// 1. 接受新的客户端连接SocketChannel sc = ssc.accept();// 2. 设置连接的通道为非阻塞模式sc.configureBlocking(false);// 3. 将新连接的通道注册到选择器上,监听读事件sc.register(selector, SelectionKey.OP_READ);System.out.println("客户端连接成功");} else if (key.isReadable()) {// 读事件// 1. 创建缓冲区ByteBuffer buffer = ByteBuffer.allocate(1024);// 2. 将 key 关联的通道 (channel) 转换为 SocketChannel 类型。转换后的 socketChannel 可用于进行网络读写操作。SocketChannel socketChannel = (SocketChannel) key.channel();// 3. 读取数据到缓冲区int read = socketChannel.read(buffer);if (read > 0) {// 获取缓冲区的数据byte[] array = buffer.array();// 转成字符串String msg = new String(array, 0, read);// 将请求信息进行 URL 解码,然后使用 UTF-8 进行编码String message = URLDecoder.decode(msg, "UTF-8");System.out.println("客户端发送了:" + message);// 清空缓冲区buffer.clear();// 响应数据String content = "OK";String HttpResponse = "HTTP/1.1 200 OK\r\n" +"Content-Type: text/html;charset=utf-8\r\n" +"Content-Length: " + content.getBytes().length + "\r\n" +"\r\n" +content;// 写入到缓冲区buffer.put(HttpResponse.getBytes());// 将缓冲区的界限设置为当前位置,然后再把当前位置重置为0buffer.flip();// 响应数据到客户端socketChannel.write(buffer);} else if (read == -1) {// 关闭通道socketChannel.close();// 取消 key 关联的通道在 selector 上的注册key.cancel();}}// 移除已经处理的 SelectionKey,防止下次循环再处理这个键it.remove();}}} catch (IOException e) {e.printStackTrace();}}
}

2. 启动 Tomcat

在入口类启动 NIO 的 Tomcat

3. 测试

二、解析请求信息

因为请求信息和之前是一样的,所以可以使用 HttpRequest 解析类

三、响应数据

创建响应类

因为响应数据的方式不一样,所以需要创建一个 NIO 方式的响应类

package com.shao.net;import com.shao.Servlet.BaseServlet;
import com.shao.Utils.ServletByAnnoUtil;import java.io.FileInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;public class HttpResponseNIO {/*** 连接的通道*/private SocketChannel sc;/*** 缓冲区*/private ByteBuffer buffer;/*** 解析类的对象*/private HttpRequest httpRequest;public HttpResponseNIO(SocketChannel sc, ByteBuffer buffer, HttpRequest httpRequest) {this.sc = sc;this.buffer = buffer;this.httpRequest = httpRequest;}public void response(String filePath) {//判断请求的是否为静态文件if (StaticResourceHandler.isLikelyStaticResource(httpRequest.getRequestModule())) {// 获取静态资源一般是 GET 请求方法if (httpRequest.getRequestMethod().equals("GET")) {// 响应静态资源responseStaticResource(filePath);}} else {// 处理动态请求System.out.println("请求动态资源");// 获取 Servlet 对象,参数是请求的模块名BaseServlet servlet = ServletByAnnoUtil.getServletClass(httpRequest.getRequestModule());// 如果没有找到对应的 Servlet ,返回 404if (servlet == null) {responseStaticResource("webs/pages/not_Found404.html");return;}// 调用 service 方法servlet.service(httpRequest, this);}}/*** 响应静态资源*/private void responseStaticResource(String filePath) {// 读取文件byte[] fileContents = StaticResourceHandler.getFileContents(filePath);// 判断文件是否存在,不存在则返回 404 的页面if (fileContents == null) {try {FileInputStream fis = new FileInputStream("webs/pages/not_Found404.html");fileContents = new byte[fis.available()];fis.read(fileContents);fis.close();} catch (Exception e) {e.printStackTrace();}}// 响应协议String protocol = httpRequest.getRequestProtocol();// 文件媒体类型String fileMimeType = StaticResourceHandler.getFileMimeType(filePath);// 清空缓冲区buffer.clear();// 写入数据到缓冲区buffer.put((protocol + " 200 OK\r\n").getBytes());buffer.put(("Content-Type: " + fileMimeType + "\r\n").getBytes());buffer.put(("Content-Length: " + fileContents.length + "\r\n").getBytes());buffer.put(("\r\n").getBytes());buffer.put(fileContents);// 将缓冲区的界限设置为当前位置,然后再把当前位置重置为0buffer.flip();try {// 响应数据到客户端sc.write(buffer);System.out.println("响应成功");} catch (IOException e) {e.printStackTrace();}}public void send(byte[] content) {// 获取请求协议String protocol = httpRequest.getRequestProtocol();// 清空缓冲区buffer.clear();// 往缓冲区写入数据buffer.put((protocol + " 200 OK\r\n").getBytes());buffer.put(("Content-Type: text/html;charset=utf-8\r\n").getBytes());buffer.put(("Content-Length: " + content.length + "\r\n").getBytes());buffer.put("\r\n".getBytes());buffer.put(content);// 设置缓冲区的界限为当前指针的位置,然后把指针指向缓冲区的起始位置buffer.flip();try {// 响应数据sc.write(buffer);System.out.println("响应成功");} catch (IOException e) {e.printStackTrace();}}
}

修改调用的响应类

四、完整代码

package com.shao.net;import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.URLDecoder;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;public class TomcatNIO {public TomcatNIO() {// 1. 创建通信管道try {ServerSocketChannel ssc = ServerSocketChannel.open();// 2. 绑定端口ssc.bind(new InetSocketAddress(8080));// 3. 配置非阻塞通信管道ssc.configureBlocking(false);// 4. 创建一个选择器Selector selector = Selector.open();// 5. 将通信管道注册到选择器上,监听客户端连接请求的事件ssc.register(selector, SelectionKey.OP_ACCEPT);// 循环监听客户端请求并处理相应事件while (true) {System.out.println("等待连接...");// 6. 从 selectors 中选择并返回已就绪的通道数int number = selector.select();if (number == 0) continue;// 7. 这些 SelectionKey 对象代表了就绪的通道及其相应的注册事件。Iterator<SelectionKey> it = selector.selectedKeys().iterator();while (it.hasNext()) {SelectionKey key = it.next();// 8. 判断就绪事件类型if (key.isAcceptable()) {System.out.println("有客户端连接了...");// 1. 接受新的客户端连接SocketChannel sc = ssc.accept();// 2. 设置连接的通道为非阻塞模式sc.configureBlocking(false);// 3. 将新连接的通道注册到选择器上,监听读事件sc.register(selector, SelectionKey.OP_READ);System.out.println("客户端连接成功");} else if (key.isReadable()) {// 读事件// 1. 创建缓冲区ByteBuffer buffer = ByteBuffer.allocate(1024);// 2. 将 key 关联的通道 (channel) 转换为 SocketChannel 类型。转换后的 socketChannel 可用于进行网络读写操作。SocketChannel socketChannel = (SocketChannel) key.channel();// 3. 读取数据到缓冲区int read = socketChannel.read(buffer);if (read > 0) {// 获取缓冲区的数据byte[] array = buffer.array();// 转成字符串String msg = new String(array, 0, read);// 将请求信息进行 URL 解码,然后使用 UTF-8 进行编码String message = URLDecoder.decode(msg, "UTF-8");// 调用 HttpRequest 类解析请求信息HttpRequest httpRequest = new HttpRequest(message);// 拼接请求的静态资源的路径String filePath = "/webs" + httpRequest.getRequestModule();// 创建响应对象HttpResponseNIO httpResponseNIO = new HttpResponseNIO(socketChannel, buffer, httpRequest);// 响应数据到客户端httpResponseNIO.response(filePath);} else if (read == -1) {// 关闭通信通道socketChannel.close();// 取消 key 关联的通道在 selector 上的注册key.cancel();}}// 9. 移除已经处理的 SelectionKey,防止下次循环再处理这个键it.remove();}}} catch (IOException e) {e.printStackTrace();}}
}

五、测试

六、总结

七、获取全部用户的功能

POJO

因为获取的用户数据需要封装,需要一个类和数据库的字段一一对应,这就是 对象关系映射(ORM) ,这个类可以称为 POJO

生成 POJO

1. 在 Dao 层定义接口

2. 获取用户数据

public ArrayList<Users> GetAllUser() {Connection connection = null;PreparedStatement pstmt = null;ResultSet resultSet = null;ArrayList<Users> users = new ArrayList<>();try {// 3. 从连接池获取一个数据库连接connection = DBConnectPool.getInstance().getConnection();// 4. 获取可执行对象// 定义 SQL 语句String SQL = "select id, account, name, password, money from train.users";pstmt = connection.prepareStatement(SQL);// 5. 执行sql语句,获取结果集resultSet = pstmt.executeQuery();// 6. 结果处理while (resultSet.next()) {// 获取一行数据,封装到对象中Users user = new Users();user.setId(resultSet.getLong("id"));user.setAccount(resultSet.getString("account"));user.setName(resultSet.getString("name"));user.setPassword(resultSet.getString("password"));user.setMoney(resultSet.getDouble("money"));// 添加到集合中users.add(user);}} catch (SQLException e) {e.printStackTrace();} finally {DBConnectPool.getInstance().releaseConnection(connection);DBConnectUtil.releaseSource(pstmt, resultSet);}return users;}

3. 在 Service 层定义接口

4. Service 层的实现方法

    public responseDTO GetAllUser() {// 调用 Dao 层获取数据ArrayList<Users> users = userDao.GetAllUser();return new responseDTO(200, users, "获取成功", users.size());}

5. 创建 Servlet

package com.shao.Servlet;import com.alibaba.fastjson2.JSON;
import com.shao.Annotation.MyServlet;
import com.shao.Service.ServiceFactory;
import com.shao.Service.UserService;
import com.shao.Utils.responseDTO;
import com.shao.net.HttpRequest;
import com.shao.net.HttpResponseNIO;@MyServlet("/GetAllUser")
public class GetAllUserServlet extends BaseServlet {responseDTO responseDTO = null;@Overridevoid doGet(HttpRequest httpRequest, HttpResponseNIO httpResponse) {// 获取实例UserService userService = ServiceFactory.getUserService();// 调用获取所有用户的方法responseDTO = userService.GetAllUser();// 响应数据httpResponse.send(JSON.toJSONBytes(responseDTO));}@Overridevoid doPost(HttpRequest httpRequest, HttpResponseNIO httpResponse) {responseDTO = new responseDTO(400, null, "不支持POST提交方法");httpResponse.send(JSON.toJSONBytes(responseDTO));}
}

6. 测试

八、作业

优化NIO

高并发的场景下,现在的NIO配置无法及时处理,如何解决?

如果客户端发送的数据很多,如何分批次读取数据?

到目前为止,我们学习了 BIO和NIO网络通信模块、HttpRequest、HttpResponse、线程池、任务队列、线程任务对象、Servlet、业务逻辑处理 Service 、Dao 、数据库连接池、POJO、DTO、注解等。这些内容组合起来就是一个简单的框架

相关文章:

【学习笔记】手写 Tomcat 八

目录 一、NIO 1. 创建 Tomcat NIO 类 2. 启动 Tomcat 3. 测试 二、解析请求信息 三、响应数据 创建响应类 修改调用的响应类 四、完整代码 五、测试 六、总结 七、获取全部用户的功能 POJO 生成 POJO 1. 在 Dao 层定义接口 2. 获取用户数据 3. 在 Service 层定…...

24年九月份生活随笔

九月份最后一天&#xff0c;烈士纪念日。 上午看了一会儿直播&#xff0c;庄重的仪式&#xff0c;铭记先辈为新中国抛头颅洒热血&#xff0c;当今盛世&#xff0c;如您所愿。 郑州马拉松官方通告&#xff0c;今天十点公布直通&#xff0c;中签&#xff0c;候补结果。 看完直…...

[含文档+PPT+源码等]精品大数据项目-基于Django实现的高校图书馆智能推送系统的设计与实现

大数据项目——基于Django实现的高校图书馆智能推送系统的设计与实现背景&#xff0c;可以从以下几个方面进行详细阐述&#xff1a; 一、信息技术的发展背景 随着信息技术的飞速发展和互联网的广泛普及&#xff0c;大数据已经成为现代社会的重要资源。在大数据背景下&#xf…...

Leecode刷题之路第七天之整数反转

题目出处 07-整数反转 题目描述 个人解法 思路&#xff1a; 1.将整数转换为字符串 2.倒序输出字符串 3.兼容负数case 代码示例&#xff1a;&#xff08;Java&#xff09; public int reverse(int x) {Integer integer new Integer(x);String s integer.toString();Strin…...

SpringBoot项目 | 瑞吉外卖 | 短信发送验证码功能改为免费的邮箱发送验证码功能 | 代码实现

0.前情提要 之前的po已经说了单独的邮箱验证码发送功能怎么实现&#xff1a; https://blog.csdn.net/qq_61551948/article/details/142641495 这篇说下如何把该功能整合到瑞吉项目里面&#xff0c;也就是把原先项目里的短信发送验证码的功能改掉&#xff0c;改为邮箱发送验证…...

Windows暂停更新

目录 前言注册表设定参考 前言 不想Windows自动更新&#xff0c;同时不想造成Windows商店不可用&#xff0c;可以采用暂停更新的方案。 但是通过这里设定的时间太短了&#xff0c;所以我们去注册表设定。 注册表设定 win r 输入 regedit进入注册表 HKEY_LOCAL_MACHINE\SOFT…...

alpine安装docker踩坑记

文章目录 前言错误场景正确操作最后 前言 你好&#xff0c;我是醉墨居士&#xff0c;最近使用alpine操作系统上docker遇到了一些错误&#xff0c;尝试解决之后就准备输出一篇博客&#xff0c;帮助有需要的后人能够少踩坑&#xff0c;因为淋过雨所以想给别人撑伞 错误场景 我…...

使用openpyxl轻松操控Excel文件

目录 1. openpyxl 简介2. 安装与快速入门2.1 安装 openpyxl2.2 快速创建一个 Excel 文件2.3 读取 Excel 文件 3. openpyxl 的核心概念3.1 工作簿&#xff08;Workbook&#xff09;3.2 工作表&#xff08;Worksheet&#xff09;3.3 单元格&#xff08;Cell&#xff09;3.4 行与列…...

指定PDF或图片多个识别区域,识别区域文字,并批量对PDF或图片文件改名

常见场景 用户有大量图片/PDF文件&#xff0c;期望能按照图片/PDF中的某些文字对图片/PDF文件重命名。期望工具可以批量处理、离线识别&#xff08;保证数据安全性&#xff09;。手工操作麻烦。具体场景&#xff1a;用户有工程现场照片&#xff0c;订单&#xff0c;简历等PDF或…...

Web3中的跨链技术:实现无缝连接的挑战

Web3的到来为互联网带来了去中心化的愿景&#xff0c;而跨链技术则是实现这一愿景的关键。跨链技术旨在解决不同区块链之间的互操作性问题&#xff0c;使得用户和应用能够在多个区块链网络之间无缝地传输数据和价值。尽管这一技术具有广阔的前景&#xff0c;但在实现过程中仍面…...

词袋(Bag of Words, BoW)

词袋&#xff08;Bag of Words, BoW&#xff09;模型详解 词袋&#xff08;BoW&#xff09;是一种用于文本处理的特征提取方法&#xff0c;常用于自然语言处理&#xff08;NLP&#xff09;任务中。在BoW模型中&#xff0c;文本被表示为一个词的无序集合&#xff0c;而忽略了词…...

HTTP Status 404 - /brand-demo/selectAllServlet错误解决原因-Servlet/JavaWeb/IDEA

检查xml文件的包名有无错误检查html文件的url有无写错&#xff0c;是否与Servlet的urlPatterns一致检查Servlet的urlpattern有没有写错(如写成name),检查doPost、doGet是否正常运行 注&#xff1a;IDEA新建Servlet时&#xff0c;默认的WebServlet注解中name需要改urlPatterns&…...

宁夏众智科技OA办公系统存在SQL注入漏洞

漏洞描述 宁夏众智科技OA办公系统存在SQL注入漏洞 漏洞复现 POC POST /Account/Login?ACTIndex&CLRHome HTTP/1.1 Host: Content-Length: 45 Cache-Control: max-age0 Origin: http://39.105.48.206 Content-Type: application/x-www-form-urlencoded Upgrade-Insecur…...

Spring邮件发送:配置与发送邮件详细步骤?

Spring邮件发送教程指南&#xff1f;怎么用Spring邮件发送服务&#xff1f; Spring框架提供了强大的邮件发送支持&#xff0c;使得开发者能够轻松地在应用程序中集成邮件发送功能。AokSend将详细介绍如何在Spring应用中配置和发送邮件&#xff0c;帮助开发者快速掌握这一关键技…...

iPhone/iPad技巧:如何解锁锁定的 iPhone 或 iPad

“在我更新 iPhone 上的软件后&#xff0c;最近我遇到了iPhone 被锁定到所有者的消息&#xff0c;该如何解决&#xff1f;” 根据我们的研究&#xff0c;许多用户在 iOS 18 更新或恢复出厂设置后都会遇到同样的问题。只要出现问题&#xff0c;您就无法使用 iPhone 或 第 1 部分…...

无源码实现免登录功能

因项目要求需要对一个没有源代码的老旧系统实现免登录功能&#xff0c;系统采用前后端分离的方式部署&#xff0c;登录时前端调用后台的认证接口&#xff0c;认证接口返回token信息&#xff0c;然后将token以json的方式存储到cookie中&#xff0c;格式如下&#xff1a; 这里有…...

大数据毕业设计选题推荐-民族服饰数据分析系统-Python数据可视化-Hive-Hadoop-Spark

✨作者主页&#xff1a;IT研究室✨ 个人简介&#xff1a;曾从事计算机专业培训教学&#xff0c;擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Python…...

疾风大模型气象,基于气象数据打造可视化平台

引言 随着气象数据的广泛应用&#xff0c;越来越多的行业依赖天气预报与气候分析来做出决策。从农业、航空、能源到物流&#xff0c;气象信息无时不刻影响着各行各业的运作。然而&#xff0c;气象数据本身复杂且多样&#xff0c;如何将这些数据转化为直观、易于理解的图形和信…...

PHP安装后Apache无法运行的问题

问题 按照网上教程php安装点击跳转教程&#xff0c;然后修改Apache的httpd.conf文件&#xff0c;本来可以运行的Apache&#xff0c;无法运行了 然后在"C:\httpd-2.4.62-240904-win64-VS17\Apache24\logs\error.log"&#xff08;就是我下载Apache的目录下的logs中&am…...

[论文精读]Multi-Channel Graph Neural Network for Entity Alignment

论文网址&#xff1a;Multi-Channel Graph Neural Network for Entity Alignment (aclanthology.org) 论文代码&#xff1a;https:// github.com/thunlp/MuGNN 英文是纯手打的&#xff01;论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误&a…...

XCTF-web-easyupload

试了试php&#xff0c;php7&#xff0c;pht&#xff0c;phtml等&#xff0c;都没有用 尝试.user.ini 抓包修改将.user.ini修改为jpg图片 在上传一个123.jpg 用蚁剑连接&#xff0c;得到flag...

手游刚开服就被攻击怎么办?如何防御DDoS?

开服初期是手游最脆弱的阶段&#xff0c;极易成为DDoS攻击的目标。一旦遭遇攻击&#xff0c;可能导致服务器瘫痪、玩家流失&#xff0c;甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案&#xff0c;帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...

iOS 26 携众系统重磅更新,但“苹果智能”仍与国行无缘

美国西海岸的夏天&#xff0c;再次被苹果点燃。一年一度的全球开发者大会 WWDC25 如期而至&#xff0c;这不仅是开发者的盛宴&#xff0c;更是全球数亿苹果用户翘首以盼的科技春晚。今年&#xff0c;苹果依旧为我们带来了全家桶式的系统更新&#xff0c;包括 iOS 26、iPadOS 26…...

MongoDB学习和应用(高效的非关系型数据库)

一丶 MongoDB简介 对于社交类软件的功能&#xff0c;我们需要对它的功能特点进行分析&#xff1a; 数据量会随着用户数增大而增大读多写少价值较低非好友看不到其动态信息地理位置的查询… 针对以上特点进行分析各大存储工具&#xff1a; mysql&#xff1a;关系型数据库&am…...

使用 SymPy 进行向量和矩阵的高级操作

在科学计算和工程领域&#xff0c;向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能&#xff0c;能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作&#xff0c;并通过具体…...

ABAP设计模式之---“简单设计原则(Simple Design)”

“Simple Design”&#xff08;简单设计&#xff09;是软件开发中的一个重要理念&#xff0c;倡导以最简单的方式实现软件功能&#xff0c;以确保代码清晰易懂、易维护&#xff0c;并在项目需求变化时能够快速适应。 其核心目标是避免复杂和过度设计&#xff0c;遵循“让事情保…...

招商蛇口 | 执笔CID,启幕低密生活新境

作为中国城市生长的力量&#xff0c;招商蛇口以“美好生活承载者”为使命&#xff0c;深耕全球111座城市&#xff0c;以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子&#xff0c;招商蛇口始终与城市发展同频共振&#xff0c;以建筑诠释对土地与生活的…...

现有的 Redis 分布式锁库(如 Redisson)提供了哪些便利?

现有的 Redis 分布式锁库&#xff08;如 Redisson&#xff09;相比于开发者自己基于 Redis 命令&#xff08;如 SETNX, EXPIRE, DEL&#xff09;手动实现分布式锁&#xff0c;提供了巨大的便利性和健壮性。主要体现在以下几个方面&#xff1a; 原子性保证 (Atomicity)&#xff…...

根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的----NTFS源代码分析--重要

根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的 第一部分&#xff1a; 0: kd> g Breakpoint 9 hit Ntfs!ReadIndexBuffer: f7173886 55 push ebp 0: kd> kc # 00 Ntfs!ReadIndexBuffer 01 Ntfs!FindFirstIndexEntry 02 Ntfs!NtfsUpda…...

HubSpot推出与ChatGPT的深度集成引发兴奋与担忧

上周三&#xff0c;HubSpot宣布已构建与ChatGPT的深度集成&#xff0c;这一消息在HubSpot用户和营销技术观察者中引发了极大的兴奋&#xff0c;但同时也存在一些关于数据安全的担忧。 许多网络声音声称&#xff0c;这对SaaS应用程序和人工智能而言是一场范式转变。 但向任何技…...