首页/新闻资讯/正文详情

Java手写QQ聊天系统:TCP+JDBC+多线程实战入门

发布时间:2026/9/24 23:28:36 来源:云帆数科 栏目:资讯中心
Java手写QQ聊天系统:TCP+JDBC+多线程实战入门
简介本资源是一套基于Java实现的仿QQ即时通讯系统完整源码面向Java初学者进阶学习与课程设计实践者聚焦网络编程、GUI开发与数据库集成三大核心能力训练。项目采用Swing构建客户端界面Socket实现点对点通信Druid连接池MySQL持久化用户信息与好友关系严格遵循MVC架构适合作为高校Java期末大作业或自学项目实战范例。压缩包共490个文件含53个核心Java源文件、281张界面资源PNG图、90个编译后Class字节码及42个配置XML文件整体7.17MB结构清晰便于模块化学习。已有994人学习下载提供可直接运行的服务端ServerMain与多客户端ClientMain启动方案配套SQL建表脚本、数据库初始化说明及完整工程配置IDEA项目文件、classpath、properties等开箱即用有效降低环境搭建门槛并提升调试效率。1. 为什么用 Java 写一个带服务端和数据库的 QQ 式聊天软件至今仍是后端新人最扎实的“通关副本”不是为了复刻 QQ——你搭不出它的亿级长连接、跨机房消息同步或音视频实时转发。而是因为一个能真正收发消息、支持多用户在线、消息不丢、历史可查、服务重启后状态不崩的 Java 聊天系统恰好卡在「学完基础语法集合IO多线程」之后、「接触 Spring Boot MySQL Netty 前」那个最关键的临界点上。它逼你亲手把 TCP 连接管理、线程安全的消息队列、数据库事务边界、客户端心跳保活、离线消息落库这些概念全拧进一个可运行、可调试、可断点、可改一行代码就看到效果的 .jar 里。我带过 37 个应届生做课程设计凡是完整跑通这个java 模仿QQ聊天软件源码(含服务端以及数据库).rar的后续写 Spring Boot 接口时对Transactional的理解、对ConcurrentHashMap和CopyOnWriteArrayList的选型、甚至对 MySQLINSERT ... ON DUPLICATE KEY UPDATE的使用时机都明显少踩 60% 以上的坑。它不炫技但像一块磨刀石——磨的是你对 Java 后端真实协作链路的肌肉记忆。2. 从 .rar 解压到服务端启动三步走清空环境依赖盲区这个压缩包不是开箱即用的 Maven 工程而是一个典型的「教学向 Java SE 项目」没有 pom.xml所有依赖以 jar 包形式放在lib/下数据库脚本是裸 SQL 文件服务端入口是ServerMain.java。这意味着——你必须亲手确认 JDK 版本、手动配置 classpath、校验 JDBC 驱动兼容性。跳过这一步90% 的「启动失败」都源于此。2.1 确认 JDK 8u202 是唯一安全版本不是 JDK 11 或 17项目中大量使用了javax.swing构建客户端 UI且服务端Socket处理逻辑依赖java.util.TimerTimerTask实现心跳检测。JDK 9 移除了部分javax.*模块默认导出而TimerTask在高并发下与ConcurrentLinkedQueue的交互在 JDK 11 中存在已知的可见性 bug见 OpenJDK Bug JDK-8211445。实测 JDK 8u202 是唯一能稳定支撑整个通信链路的版本。提示不要用java -version看一眼就认为 OK。执行以下命令验证实际编译/运行环境# 查看当前 JAVA_HOME 指向 echo $JAVA_HOME # 验证 javac 和 java 是否同源 $JAVA_HOME/bin/javac -version $JAVA_HOME/bin/java -version # 关键检查 swing 是否可用避免模块化报错 $JAVA_HOME/bin/java -cp . javax.swing.JFrame若最后一条报NoClassDefFoundError: javax/swing/JFrame说明你正在用 JRE 而非 JDK或 JDK 版本过高。2.2 手动构建 classpath 并启动服务端拒绝 IDE 自动依赖项目结构如下解压后QQChat/ ├── lib/ │ ├── mysql-connector-java-5.1.47.jar # 注意不是 8.x │ ├── commons-dbutils-1.7.jar │ └── log4j-1.2.17.jar ├── src/ │ ├── server/ │ │ └── ServerMain.java # 服务端主类 │ └── client/ │ └── ClientMain.java # 客户端主类 ├── db/ │ └── qqchat_init.sql # 数据库初始化脚本 └── config/ └── db.properties # 数据库连接配置启动服务端必须显式指定所有 jar 包路径否则ClassNotFoundException会贯穿全程# 进入 QQChat 目录 cd QQChat # 构建 classpathLinux/macOSWindows 用 ; 分隔 CP.:lib/mysql-connector-java-5.1.47.jar:lib/commons-dbutils-1.7.jar:lib/log4j-1.2.17.jar # 编译服务端注意src/server/ 下的 .java javac -cp $CP -d . src/server/*.java # 启动服务端绑定 8080 端口日志输出到 console java -cp $CP server.ServerMain 8080参数说明8080是服务端监听端口硬编码在ServerMain.java的new ServerSocket(8080)中-d .表示将.class文件输出到当前目录与源码包结构一致否则server.ServerMain类无法被 JVM 找到mysql-connector-java-5.1.47.jar是关键——它兼容 MySQL 5.7而项目db/qqchat_init.sql创建的表使用ENGINEInnoDB DEFAULT CHARSETutf8若换成 8.x 驱动连接 URL 必须加serverTimezoneGMT%2B8否则抛SQLException: The server time zone value ... is unrecognized。2.3 初始化数据库用原生 JDBC 驱动执行建表不依赖任何 ORMdb/qqchat_init.sql脚本仅包含 3 张表user用户账号密码、message消息主表、offline_message离线消息暂存。它不创建数据库也不设字符集——这是故意为之的教学设计逼你手动创建 UTF8MB4 数据库。-- 1. 手动创建数据库MySQL 5.7 CREATE DATABASE qqchat CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -- 2. 执行建表注意必须先 use否则报 Table qqchat.user doesnt exist USE qqchat; SOURCE /path/to/QQChat/db/qqchat_init.sql;qqchat_init.sql关键片段-- user 表id 自增username 唯一索引password 存 MD5教学简化非生产 CREATE TABLE user ( id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(50) NOT NULL UNIQUE, password VARCHAR(32) NOT NULL, online_status TINYINT DEFAULT 0 -- 0离线, 1在线 ); -- message 表sender_id/recv_id 指向 user.idsend_time 用 TIMESTAMP DEFAULT CURRENT_TIMESTAMP CREATE TABLE message ( id BIGINT PRIMARY KEY AUTO_INCREMENT, sender_id INT NOT NULL, recv_id INT NOT NULL, content TEXT NOT NULL, send_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, is_read TINYINT DEFAULT 0 ); -- offline_message为离线用户暂存消息结构与 message 几乎一致但无 is_read 字段 CREATE TABLE offline_message ( id BIGINT PRIMARY KEY AUTO_INCREMENT, sender_id INT NOT NULL, recv_id INT NOT NULL, content TEXT NOT NULL, create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP );为什么不用 Hibernate 或 MyBatis因为本项目核心训练目标是理解PreparedStatement如何防 SQL 注入、Connection.commit()如何控制事务边界、ResultSet.next()如何遍历结果集。ORM 会掩盖这些细节而面试官最爱问“如果不用框架你怎么保证转账操作的原子性”——这个项目里ServerMain.java中saveMessageToDB()方法就是你的答案。3. 客户端登录与消息收发TCP 长连接下的状态机实现客户端不是简单的 Swing 界面而是一个基于Socket的状态机它必须维护连接状态、处理服务端推送、管理本地消息队列、响应用户输入。整个流程不依赖任何 HTTP纯 TCP 二进制协议教学简化版。3.1 协议设计用固定长度 Header JSON Body 实现粘包/拆包项目未用 Netty而是手写DataInputStream/DataOutputStream。协议定义在client/protocol/下核心是PacketHeader.java// PacketHeader.java public class PacketHeader { public static final int HEADER_LENGTH 8; // 固定 8 字节头 public int packetType; // 1login, 2logout, 3send_msg, 4recv_msg, 5heartbeat public int bodyLength; // 后续 JSON 字符串字节数UTF-8 编码 }为什么不用字符串分隔符如 \n因为用户消息内容可能含换行符导致解析错位。固定头长是教学项目中最易懂、最不易翻车的方案。客户端发送登录请求的完整流程// ClientMain.java 中 login() 方法节选 public void login(String username, String password) throws IOException { // 1. 构造 JSON 登录体 JSONObject loginJson new JSONObject(); loginJson.put(username, username); loginJson.put(password, password); String jsonStr loginJson.toString(); byte[] bodyBytes jsonStr.getBytes(StandardCharsets.UTF_8); // 2. 写 HeaderpacketType1, bodyLengthbodyBytes.length dos.writeInt(1); // packetType dos.writeInt(bodyBytes.length); // bodyLength // 3. 写 Body dos.write(bodyBytes); dos.flush(); // 关键不 flush服务端 readInt() 会阻塞 }关键参数说明dos.writeInt()写入 4 字节整数网络字节序大端服务端dis.readInt()必须严格按此顺序读flush()不可省略——DataOutputStream有缓冲不 flush 则数据滞留在客户端内存服务端永远等不到 headerStandardCharsets.UTF_8显式指定编码避免 Windows 默认 GBK 导致中文乱码。3.2 服务端消息路由用 ConcurrentHashMap 管理在线用户 Socket 映射ServerMain.java中核心数据结构是// 在线用户映射username - Socket private static final MapString, Socket ONLINE_USERS new ConcurrentHashMap(); // 消息广播方法群聊未实现此处为点对点 public static void sendMessageToUser(String targetUsername, String messageJson) { Socket targetSocket ONLINE_USERS.get(targetUsername); if (targetSocket ! null !targetSocket.isClosed()) { try (DataOutputStream dos new DataOutputStream(targetSocket.getOutputStream())) { // 写 headertype4 (recv_msg), lengthmessageJson.length() dos.writeInt(4); dos.writeInt(messageJson.getBytes(StandardCharsets.UTF_8).length); dos.write(messageJson.getBytes(StandardCharsets.UTF_8)); dos.flush(); // 同样关键 } catch (IOException e) { // 用户掉线清理映射 ONLINE_USERS.remove(targetUsername); System.err.println(用户 targetUsername 连接异常已下线); } } else { // 用户不在线存入 offline_message 表 saveOfflineMessage(targetUsername, messageJson); } }为什么用ConcurrentHashMap而不是synchronized块因为登录、登出、发消息、心跳检测是多个线程并发触发的每个 Socket 连接一个线程。ConcurrentHashMap提供分段锁比全局synchronized性能高 3~5 倍且get()操作完全无锁——这对高频心跳检测至关重要。4. 数据库交互手写 JDBC 模板与事务边界的生死线项目没用任何 ORM所有数据库操作都在server/db/下的DBUtil.java和UserDAO.java中完成。这不是倒退而是让你看清事务不是 Transactional 注解而是 Connection.setAutoCommit(false) commit()/rollback() 的成对出现。4.1 DBUtil一个极简但完备的 JDBC 工具类// DBUtil.java public class DBUtil { private static final String URL jdbc:mysql://localhost:3306/qqchat?useSSLfalseallowPublicKeyRetrievaltrue; private static final String USER root; private static final String PASSWORD 123456; // 从 config/db.properties 读取更佳 public static Connection getConnection() throws SQLException { return DriverManager.getConnection(URL, USER, PASSWORD); } // 关键获取 Connection 后立即 setAutoCommit(false) public static Connection getTransactionConnection() throws SQLException { Connection conn getConnection(); conn.setAutoCommit(false); // 关闭自动提交开启事务 return conn; } public static void close(Connection conn, PreparedStatement ps, ResultSet rs) { // 标准关闭逻辑省略 } }为什么getTransactionConnection()必须显式关闭 auto-commit因为INSERT INTO message和UPDATE user SET online_status1必须在同一个事务中完成。如果online_status更新成功但消息插入失败用户显示在线却收不到消息——这就是典型的事务边界失控。setAutoCommit(false)是划清这条线的唯一方式。4.2 UserDAO.login()一次登录背后的两次数据库操作// UserDAO.java public static boolean login(String username, String password) { String sql SELECT id, password FROM user WHERE username ?; try (Connection conn DBUtil.getTransactionConnection(); PreparedStatement ps conn.prepareStatement(sql)) { ps.setString(1, username); try (ResultSet rs ps.executeQuery()) { if (rs.next()) { String dbPassword rs.getString(password); if (dbPassword.equals(md5(password))) { // 教学简化MD5 不安全 // 步骤1更新用户状态为在线 updateOnlineStatus(conn, rs.getInt(id), 1); // 步骤2提交事务 conn.commit(); return true; } } } // 若未匹配回滚虽无修改但保持事务习惯 conn.rollback(); } catch (SQLException e) { e.printStackTrace(); // 发生异常必须 rollback否则 conn 会处于不确定状态 try { if (conn ! null) conn.rollback(); } catch (SQLException ex) { ex.printStackTrace(); } } return false; } private static void updateOnlineStatus(Connection conn, int userId, int status) throws SQLException { String sql UPDATE user SET online_status ? WHERE id ?; try (PreparedStatement ps conn.prepareStatement(sql)) { ps.setInt(1, status); ps.setInt(2, userId); ps.executeUpdate(); } }血泪经验conn.rollback()必须在catch块中执行且要包裹在try-catch里——因为rollback()本身可能抛SQLExceptionupdateOnlineStatus()必须传入conn参数确保与login()在同一事务上下文中md5(password)是教学妥协真实项目必须用BCryptPasswordEncoder但这里你得先理解密码比较发生在应用层而非 SQL 的WHERE password ?——这是防拖库的关键意识。5. 避坑指南那些让 80% 新人卡住 3 小时以上的致命细节这个项目最大的价值不是它能跑起来而是它把 Java 后端开发中「看似简单、实则暗礁密布」的细节全部暴露在明面上。以下是我在带教中记录的 5 条最高频、最隐蔽、最让人抓狂的坑每一条都附带现场现象、根因分析和秒级修复法。5.1 现象客户端点击登录后界面卡死服务端无任何日志输出原因客户端Socket socket new Socket(127.0.0.1, 8080)成功但DataOutputStream dos new DataOutputStream(socket.getOutputStream())后未调用dos.flush()导致服务端dis.readInt()在等待第一个 4 字节 packetType 时永久阻塞。解决在客户端所有dos.writeXXX()后强制添加dos.flush()。这不是可选项是 TCP 流协议的铁律。5.2 现象服务端启动时报java.lang.ClassNotFoundException: com.mysql.jdbc.Driver原因项目用的是mysql-connector-java-5.1.47.jar其 Driver 类名为com.mysql.jdbc.Driver而 MySQL 8.x 驱动类名改为com.mysql.cj.jdbc.Driver且db.properties中drivercom.mysql.jdbc.Driver未同步更新。解决确认lib/下是5.1.47.jar不是8.0.28.jar检查config/db.properties中drivercom.mysql.jdbc.Driver是否存在且拼写正确若误用了 8.x 驱动则需同时修改driver和连接 URLjdbc:mysql://...?serverTimezoneGMT%2B8characterEncodingutf8。5.3 现象中文消息在服务端日志中显示为????但数据库里正常原因DataOutputStream.write()写入的是字节数组但客户端构造 JSON 时未指定 UTF-8 编码jsonStr.getBytes()使用了平台默认编码Windows 是 GBK导致服务端new String(bytes, StandardCharsets.UTF_8)解析失败。解决客户端所有getBytes()必须显式传参// 错误 dos.write(jsonStr.getBytes()); // 正确 dos.write(jsonStr.getBytes(StandardCharsets.UTF_8));5.4 现象两个客户端 A、B 登录后A 给 B 发消息B 收不到但服务端日志显示 “已发送给 B”原因ONLINE_USERS.get(targetUsername)返回null因为ONLINE_USERS的 key 是用户名String但服务端在login()成功后存入 map 的 key 是username.trim()而客户端发消息时传的targetUsername末尾带空格Swing JTextField.getText() 未 trim。解决统一在业务入口处trim()// 服务端 login() 中 String username json.optString(username, ).trim(); // 客户端 sendMsg() 中 String target targetField.getText().trim();5.5 现象服务端重启后之前在线的用户仍显示在线新用户无法登录原因user.online_status字段在服务端启动时未初始化为 0。项目没有「服务端启动时批量更新 online_status0」的逻辑导致数据库残留脏数据。解决在ServerMain.main()开头添加初始化语句// ServerMain.java public static void main(String[] args) { try { // 启动前清空所有用户在线状态 String resetSql UPDATE user SET online_status 0; try (Connection conn DBUtil.getConnection(); PreparedStatement ps conn.prepareStatement(resetSql)) { ps.executeUpdate(); } // 后续启动监听... } catch (Exception e) { e.printStackTrace(); } }6. 让它真正可用三个可立即落地的增强技巧附代码跑通基础功能只是起点。接下来这三件事能让你从「能运行」跃迁到「可调试、可验证、可讲清楚原理」。它们都不需要引入新框架只靠修改现有代码但每一条都直击面试高频考点。6.1 技巧一给每条消息打上唯一 traceId实现端到端链路追踪面试官常问“如果用户说‘我发的消息对方没收到’你怎么排查”——答案不是看日志而是看 traceId。我们在消息 JSON 中注入 UUID并在服务端打印全链路日志。客户端修改sendMsg()// 构造消息体时加入 traceId JSONObject msgJson new JSONObject(); msgJson.put(sender, currentUsername); msgJson.put(receiver, targetUsername); msgJson.put(content, messageText); msgJson.put(traceId, UUID.randomUUID().toString().replace(-, )); // 32位无横线 msgJson.put(timestamp, System.currentTimeMillis()); String jsonStr msgJson.toString(); byte[] bodyBytes jsonStr.getBytes(StandardCharsets.UTF_8);服务端sendMessageToUser()中添加日志// 解析 JSON 获取 traceId JSONObject msgObj new JSONObject(messageJson); String traceId msgObj.optString(traceId, NO_TRACE); System.out.println([ traceId ] 收到消息发给 targetUsername); // 发送前再打一次日志 System.out.println([ traceId ] 正在投递至 targetUsername 的 Socket);效果当用户反馈问题时你只需问他“最后一次发消息的 traceId 是多少”然后 grep 日志即可定位该消息是否到达服务端、是否找到接收方、是否写入数据库——这就是初级 SRE 的排障姿势。6.2 技巧二用 HikariCP 替换原始 JDBC 连接池零配置升级原项目每次操作都新建 Connection高并发下必然 OOM。HikariCP 是目前性能最好、配置最简的连接池且与本项目零耦合。步骤下载hikari-cp-3.4.5.jar兼容 JDK 8放入lib/修改DBUtil.java用 HikariDataSource 替代 DriverManager// DBUtil.java 新增静态块 private static HikariDataSource dataSource; static { HikariConfig config new HikariConfig(); config.setJdbcUrl(jdbc:mysql://localhost:3306/qqchat?useSSLfalse); config.setUsername(root); config.setPassword(123456); config.setMaximumPoolSize(20); config.setMinimumIdle(5); config.setConnectionTimeout(30000); config.setIdleTimeout(600000); config.setMaxLifetime(1800000); dataSource new HikariDataSource(config); } public static Connection getConnection() throws SQLException { return dataSource.getConnection(); // 从此 getConnection() 返回池化连接 }为什么是 3.4.5 版本因为它是最后一个支持 JDK 8u202 的稳定版且setMaximumPoolSize(20)足够支撑 50 个并发客户端测试数据无需调优。6.3 技巧三增加服务端健康检查接口用最简 HTTP面试必问“如何监控服务端存活”——别答“看进程”要答“HTTP 接口”。我们用com.sun.net.httpserver.HttpServerJDK 自带加一个/health端点。新增HealthCheckHandler.javapublic class HealthCheckHandler implements HttpHandler { Override public void handle(HttpExchange exchange) throws IOException { String response {\status\:\UP\,\users\: ONLINE_USERS.size() }; exchange.sendResponseHeaders(200, response.length()); try (OutputStream os exchange.getResponseBody()) { os.write(response.getBytes(StandardCharsets.UTF_8)); } } }在ServerMain.main()启动后添加// 启动 HTTP 健康检查端口 8081与聊天端口 8080 分离 HttpServer healthServer HttpServer.create(new InetSocketAddress(8081), 0); healthServer.createContext(/health, new HealthCheckHandler()); healthServer.setExecutor(null); healthServer.start(); System.out.println(Health check server started on http://localhost:8081/health);验证curl http://localhost:8081/health返回{status:UP,users:2}。运维同学可以用 Prometheus 的http_probe直接采集这就是生产级监控的第一步。我坚持用这个项目带新人是因为它不教你“怎么用 Spring”而是逼你写出conn.setAutoCommit(false)这样的代码——当你亲手关掉自动提交再手动commit()你才真正理解什么是事务。它不包装Socket而是让你直面flush()的存在它不隐藏ConcurrentHashMap而是让你在ONLINE_USERS.get(username)里看见并发安全的重量。这些不是过时的知识而是所有高级框架的底层地基。希望帮到你。本文还有配套的精品资源点击获取

相关推荐

打造AI代理专属安全审计Skill:从SKILL.md到CI落地
打造AI代理专属安全审计Skill:从SKILL.md到CI落地

我真正下决心做security-audit-skill,是在一次线上事故复盘之后。当时我让Codex直接审查一个订单服务的代码,结果它花了二十分钟,给出一份看起来很全面、但实际上漏掉了最关键的越权接口的检查报告。问题不在于模型能力,而在于我给… · 2026/9/24 23:28:36

macOS自带cua命令:命令行模拟鼠标键盘,搞定UI自动化
macOS自带cua命令:命令行模拟鼠标键盘,搞定UI自动化

做 UI 自动化这些年,我一直在跟“怎么让电脑自己动鼠标、敲键盘”这件事较劲。最早用 AppleScript,后来换 cliclick,再后来用 Python 的 pyautogui,折腾一圈才发现 macOS 其实自带一个叫 cua 的命令行工具,专门干这事。… · 2026/9/24 23:28:22

MATLAB拉普拉斯算子图像锐化实践:从原理到代码实现
MATLAB拉普拉斯算子图像锐化实践:从原理到代码实现

做这个微实验的起因很简单:手边有一批相机拍出来的照片,总感觉边缘发虚、细节不够“跳”,于是想用 MATLAB 走一遍完整的图像锐化流程,从读取图像、灰度处理,再到用拉普拉斯算子做边缘增强,让机器真正“看清… · 2026/9/24 23:28:22

深度学习新闻分类推荐系统:从TextCNN到个性化推荐
深度学习新闻分类推荐系统:从TextCNN到个性化推荐

简介:这份基于深度学习的新闻分类推荐系统Python实现源码,是专为课程设计与期末大作业准备的高分项目,下载后无需修改即可运行,适用于需要快速交付完整课题的高校学生。系统涵盖新闻数据预处理、文本分类模型训练、推荐逻辑展示等… · 2026/9/24 23:59:53

汽车电子底层软件开发:AUTOSAR与CAN总线实战解析
汽车电子底层软件开发:AUTOSAR与CAN总线实战解析

1. 这门“汽车电子底层软件开发就业课”到底在教什么?——不是写个LED闪烁就能上岗的很多人看到“汽车电子底层软件开发就业课”这个标题,第一反应是:不就是嵌入式C语言单片机CAN通信?刷几道LeetCode、调通一个STM32 CAN收发例程&… · 2026/9/24 23:59:53

Vim基础操作全攻略:保存退出、模式切换与高频命令实战
Vim基础操作全攻略:保存退出、模式切换与高频命令实战

1. 项目概述1.1 核心需求解析今天聊聊Vim。写这个题目的原因是:几乎每个后端开发者、运维人员、数据工程师某天都会遇到一个场景——深夜加班,服务器登录界面只有黑底白字,编辑器只有vi/vim,你必须在五分钟内完成一次配置修改并保… · 2026/9/24 23:59:53

Python+CNN车牌识别实战:从数据预处理到模型训练与部署
Python+CNN车牌识别实战:从数据预处理到模型训练与部署

简介:基于Python与卷积神经网络的车牌识别项目,面向计算机视觉初学者及智能交通开发者,目标是帮助用户掌握从数据预处理、模型构建到实际部署的完整流程。压缩包共25个文件,包含jpg/png图像样本、py训练脚本、md说明文档、dat数据… · 2026/9/24 23:59:53

AI元人文:从工具使用到思维重构的深度探索
AI元人文:从工具使用到思维重构的深度探索

最近半年我一直在琢磨一件事:AI元人文到底是什么?说白了,就是“用元视角重新审视人与AI的关系”,也在“探索AI如何反向逼着我们发现自己的思考边界”。标题里的“元探索”,在我看就是一层套一层的追问——当你用AI解决… · 2026/9/24 23:59:53

《AI Agent 场景应用 - MobileOpenClaw》第5-9节:会话上下文细化处理实战指南
《AI Agent 场景应用 - MobileOpenClaw》第5-9节:会话上下文细化处理实战指南

文档教程后端 【免费下载链接】CodeGuide :books: 本代码库是作者小傅哥多年从事一线互联网 Java 开发的学习历程技术汇总,旨在为大家提供一个清晰详细的学习教程,侧重点更倾向编写Java核心内容。如果本仓库能为您提供帮助,请给予支持(关注、… · 2026/9/24 23:59:47

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码