Java桌面IM实战:Socket+Swing+MySQL实现私聊群聊与消息持久化
简介本资源是一个基于Java实现的仿QQ即时通讯系统完整项目面向Java初学者与GUI/网络编程学习者聚焦于多线程聊天、Socket通信、Swing界面开发及基础数据库交互等核心实践能力训练。项目涵盖用户登录、好友管理、私聊与群聊、表情消息、状态同步等典型功能模块代码结构清晰含20个.class字节码文件、10个.java源文件、1个MySQL建表脚本qq.sql及1个JDBC驱动jar包配合27个GIF表情资源与23张界面截图如登录页、主面板、聊天窗口等直观呈现UI设计逻辑压缩包共85个文件大小仅1MB轻量易部署。目前已有196人学习下载适合用于课程设计、毕业设计参考或Java综合实训项目复现——可直接运行调试快速理解客户端-服务器通信机制、事件驱动响应流程与分层架构组织方式。1. 这不是玩具 Demo一个能跑通私聊群聊消息持久化的 Java 桌面 IM 实战项目你手头这个Java-QQ.zip不是网上泛滥的「Swing 做个登录框就叫仿 QQ」的半成品。它真正在本地跑起来后能完成用户登录 → 好友列表加载 → 点击私聊弹窗 → 发送文字/表情/图片 → 消息实时回显 → 群聊创建与加入 → 多人消息广播 → 所有聊天记录写入 MySQL 并在重启后自动恢复——整套链路闭环且代码结构清晰、分层明确server/dao/entity/util/gui连图标资源.gif/.jpg都按功能归类好了。它不依赖 Spring Boot 或任何现代框架纯 JDK 8 JDBC Socket Swing 实现适合想夯实 Java 网络编程、多线程协同、GUI 事件驱动和数据库 CRUD 四大硬核能力的中级开发者。如果你正被「学了 Java 却写不出完整项目」卡住或者面试前急需一个能讲清技术选型、线程分工、消息序列化策略的实战案例这个包就是你该拆的第一份「血肉级」源码——它没用 Netty没上 Redis但每行代码都在回答「为什么这里必须用 synchronized」「为什么 DAO 层要单独抽 interface」「为什么 GUI 更新必须走 EventQueue.invokeLater」。2. 从解压到启动环境准备与核心模块定位2.1 JDK 版本与 IDE 兼容性确认别让 .classpath 拖垮你的第一次运行这个项目.classpath文件里明确写着classpathentry kindcon pathorg.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6/但实际运行时你会发现JDK 1.6 启动会报Unsupported major.minor version 52.0。原因很实在——项目里混用了 JDK 7 编译的mysql-connector-java-5.1.15-bin.jar该 jar 编译于 JDK 6但部分 class 已升级。正确做法是统一用 JDK 8u202 或更高版本推荐 8u333并手动修正.project中的 build path提示Eclipse 导入时若提示「JRE System Library is not compatible」右键项目 → Properties → Java Build Path → Libraries → RemoveJRE System Library→ Add Library → JRE System Library → Execution environment →JavaSE-1.8→ Finish。验证是否成功java -version # 必须输出 1.8.x javac -version # 同步验证2.2 数据库初始化qq.sql不是摆设它定义了整个消息生命周期项目根目录下的qq.sql是真实可用的建表脚本不是示意代码。它包含 4 张核心表user存储用户名、密码明文仅用于教学生产需加盐哈希friend记录好友关系user_id,friend_id,group_namegroup_info群基本信息group_id,group_name,creator_idmessage_record最关键——所有私聊/群聊消息落库字段为(id, sender_id, receiver_id, group_id, msg_content, msg_type, send_time)其中receiver_id和group_id互斥私聊填前者群聊填后者msg_type区分文本/表情/图片值为 0/1/2。执行步骤-- 在 MySQL 5.7 创建数据库 CREATE DATABASE qq_im CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -- 导入脚本注意路径 source /path/to/your/Java-QQ/qq.sql;注意qq.sql中message_record.send_time类型为DATETIME但 Java 代码里用的是new Date()需确保 JDBC URL 加上serverTimezoneGMT%2B8否则时间戳会偏移 8 小时。修改dao/DBUtil.java中的连接字符串private static final String URL jdbc:mysql://localhost:3306/qq_im?useSSLfalseserverTimezoneGMT%2B8characterEncodingutf8;2.3 启动顺序与进程分工Server 和 Client 必须严格分离这个项目采用C/S 架构非 P2P。启动流程不可颠倒先启动 Server 端运行src/server/ServerMain.java主类控制台输出服务器已启动等待客户端连接...即成功再启动 Client 端运行src/gui/LoginFrame.java注意不是Main.java项目无统一入口GUI 启动点在登录窗Server 必须常驻关闭 Server 后 Client 仍可操作 UI但点击发送按钮会抛java.net.SocketException: Connection reset—— 这是设计使然不是 Bug。关键逻辑在server/ServerThread.java每个 Client 连接由独立线程处理run()方法内循环读取ObjectInputStream根据消息类型MessageType.LOGIN/MessageType.PRIVATE_CHAT/MessageType.GROUP_CHAT分发到对应 handler。这不是简单 echo server而是带状态管理的真实服务端。3. 私聊与群聊的消息流转从点击按钮到数据库落盘的全链路解析3.1 私聊消息双线程 双队列 GUI 安全线程更新当你在好友列表双击张三触发FriendListPanel.java的mouseClicked事件// FriendListPanel.java 第 127 行 private void openChatWindow(User user) { ChatWindow chatWindow new ChatWindow(currentUser, user); // 创建新窗口 chatWindow.setVisible(true); chatWindow.startReceiveThread(); // 启动接收线程 }此时ChatWindow构造器中做了三件事初始化JTextArea显示区只读绑定发送按钮ActionListener调用sendMessage()关键startReceiveThread()启动一个Thread持续监听ObjectInputStream来自 Server 的响应流。sendMessage()流程获取输入框文本 → 封装为Message对象含senderId,receiverId,content,type0调用clientSocket.getOutputStream().writeObject(msg)发送给 Server立即本地追加到聊天框chatArea.append(...)实现「发送即显示」Server 收到后查receiverId对应的在线 socketwriteObject()推送消息。Client 接收线程捕获后必须用SwingUtilities.invokeLater()更新 UI// ChatWindow.java 第 215 行 SwingUtilities.invokeLater(() - { chatArea.append([对方] msg.getContent() \n); chatArea.setCaretPosition(chatArea.getDocument().getLength()); });为什么必须invokeLater因为 Swing 组件非线程安全直接在接收线程调用append()会导致IllegalStateException或 UI 冻结。这是 Java GUI 开发的铁律也是本项目唯一一处显式使用SwingUtilities的地方——它暴露了作者对线程模型的真实理解。3.2 群聊消息广播机制与群成员状态同步群聊入口在MainFrame.java的「创建群聊」按钮// MainFrame.java 第 189 行 createGroupBtn.addActionListener(e - { String groupName JOptionPane.showInputDialog(请输入群名称); if (groupName ! null !groupName.trim().isEmpty()) { Message msg new Message(); msg.setType(MessageType.CREATE_GROUP); msg.setSender(currentUser.getId()); msg.setContent(groupName); try { clientSocket.getOutputStream().writeObject(msg); } catch (IOException ex) { ex.printStackTrace(); } } });Server 端GroupHandler.java处理CREATE_GROUP插入group_info表返回GroupInfo对象给创建者不主动推送给其他人——群聊成员需手动「加入群聊」。真正广播发生在GROUP_CHAT类型消息Client 发送消息时Message.groupId非空receiverId为 0Server 查询group_member表项目未显式建此表但dao/GroupDao.java有getGroupMembers(groupId)方法实际查friend表中group_name匹配的记录遍历每个成员 socketwriteObject()推送注意不是 multicast是单播循环。关键细节群消息在message_record表中receiver_id0group_idxxx查询历史时WHERE group_id ?。这比用receiver_id存群 ID 更规范避免 ID 冲突。3.3 消息持久化DAO 层如何保证「发一条存一条」不丢不重所有消息写库动作集中在dao/MessageDao.javapublic boolean saveMessage(Message message) { String sql INSERT INTO message_record (sender_id, receiver_id, group_id, msg_content, msg_type, send_time) VALUES (?, ?, ?, ?, ?, ?); return executeUpdate(sql, message.getSenderId(), message.getReceiverId(), message.getGroupId(), message.getContent(), message.getType(), new Timestamp(message.getSendTime().getTime())) 0; }但注意这个方法被调用的位置只有两处ServerThread.java处理完私聊/群聊消息后messageDao.saveMessage(msg)LoginFrame.java登录成功后loadHistory()加载历史消息只读不写。也就是说消息只在 Server 端落库Client 不写库。这是合理设计——避免多客户端并发写导致脏数据。Server 收到消息 → 校验 → 广播 → 落库原子性由 JDBC 事务保障虽然项目没显式开启 transaction但单条 INSERT 默认 auto-commit。4. 避坑那些让你调试到凌晨三点的真实问题与解法4.1 现象登录成功后好友列表为空但数据库friend表明明有数据原因dao/FriendDao.java的loadFriends(int userId)方法中 SQL 拼接错误// 错误写法原文本 String sql SELECT * FROM friend WHERE user_id userId; // 没加引号当userId1时生成WHERE user_id 1正确但若user_id是字符串如U001则 SQL 变成WHERE user_id U001MySQL 报错Unknown column U001 in where clauseDAO 返回空集合。解决改为预编译参数String sql SELECT * FROM friend WHERE user_id ?; return executeQuery(sql, userId);4.2 现象发送表情后对方看到乱码或空白但文字消息正常原因表情资源路径硬编码在gui/ChatWindow.java// 第 342 行错误 ImageIcon icon new ImageIcon(images/ fileName);而项目中表情文件名含中文如消息记录.JPGWindows 系统默认 GBK 编码读取路径失败。解决改用ClassLoader获取资源流URL imgUrl getClass().getClassLoader().getResource(images/ fileName); if (imgUrl ! null) { ImageIcon icon new ImageIcon(imgUrl); // ...后续处理 }4.3 现象群聊消息发送后部分成员收不到重启 Server 才恢复原因ServerThread.java中群成员 socket 存储在ArrayListSocket但未做线程安全保护。当 A 用户退出群聊removeFromGroup时遍历 list 移除 socket同时 B 用户正发消息遍历同一 list ——ConcurrentModificationException导致广播中断。解决将ArrayList替换为CopyOnWriteArrayList并在GroupHandler.java中声明private static CopyOnWriteArrayListSocket groupSockets new CopyOnWriteArrayList();血泪经验CopyOnWriteArrayList适合读多写少场景群成员变动频率低但消息广播高频这是最优解。别用synchronized(list)会锁死整个广播流程。4.4 现象MySQL 连接频繁断开日志报Communications link failure原因DBUtil.java的getConnection()每次都新建连接且未关闭。项目中大量 DAO 方法调用后未显式close()连接池耗尽。解决在DBUtil.java添加连接池轻量级 HikariCP// 新增静态变量 private static HikariDataSource dataSource; static { HikariConfig config new HikariConfig(); config.setJdbcUrl(jdbc:mysql://localhost:3306/qq_im?...); config.setUsername(root); config.setPassword(123456); config.setMaximumPoolSize(10); config.setMinimumIdle(2); config.setConnectionTimeout(30000); dataSource new HikariDataSource(config); } public static Connection getConnection() throws SQLException { return dataSource.getConnection(); }然后所有executeQuery/executeUpdate方法末尾加finally { conn.close(); }。4.5 现象双击好友头像无反应控制台无报错原因FriendListPanel.java的MouseListener绑定在JPanel上但JLabel头像覆盖了点击区域事件被 JLabel 拦截。解决给每个头像 JLabel 设置setOpaque(false)和setContentAreaFilled(false)并添加addMouseListener到 JLabel 本身JLabel avatarLabel new JLabel(new ImageIcon(avatarPath)); avatarLabel.addMouseListener(new MouseAdapter() { Override public void mouseClicked(MouseEvent e) { openChatWindow(friendUser); } });5. 表情与图片消息二进制传输的底层实现与边界处理5.1 表情消息不是 Base64 字符串而是序列化后的 File 对象项目中表情发送逻辑藏在ChatWindow.java的sendEmotion()方法private void sendEmotion(String emotionFileName) { try { File file new File(images/ emotionFileName); FileInputStream fis new FileInputStream(file); byte[] data new byte[(int) file.length()]; fis.read(data); fis.close(); Message msg new Message(); msg.setType(MessageType.EMOTION); msg.setSenderId(currentUser.getId()); msg.setReceiverId(targetUser.getId()); msg.setContent(emotionFileName); // 仅传文件名 msg.setBinaryData(data); // 关键二进制数据存这里 clientSocket.getOutputStream().writeObject(msg); } catch (Exception e) { e.printStackTrace(); } }重点msg.setBinaryData(data)将字节数组存入Message对象的byte[] binaryData字段而Message类实现了Serializable。这意味着Server 收到Message对象后msg.getBinaryData()可直接获取字节数组但 Server不保存二进制数据到数据库message_record.msg_content只存文件名而是将binaryData透传给接收方接收方ChatWindow的receiveMessage()方法中根据msg.getType() MessageType.EMOTION用msg.getBinaryData()创建ImageIcon并插入聊天框。这种设计节省数据库空间不用存 blob但要求所有客户端images/目录下必须有同名文件。生产环境应改为 CDN URL 或数据库 blob 存储。5.2 图片消息FileInputStream的陷阱与内存溢出防护图片发送复用同一套逻辑但FileInputStream读取大图5MB时会 OOM。原代码无校验File file new File(images/ fileName); byte[] data new byte[(int) file.length()]; // 危险 fis.read(data);改进方案添加大小限制与分块读取long fileSize file.length(); if (fileSize 5 * 1024 * 1024) { // 5MB 限制 JOptionPane.showMessageDialog(this, 图片过大请选择小于5MB的文件); return; } ByteArrayOutputStream baos new ByteArrayOutputStream(); byte[] buffer new byte[8192]; int len; while ((len fis.read(buffer)) ! -1) { baos.write(buffer, 0, len); } byte[] data baos.toByteArray();5.3 消息类型枚举MessageType的扩展性设计与反序列化安全entity/MessageType.java定义了 7 种类型类型值用途LOGIN1用户登录认证LOGOUT2用户登出通知PRIVATE_CHAT3私聊消息GROUP_CHAT4群聊消息CREATE_GROUP5创建群聊请求EMOTION6表情消息含 binaryDataFILE_TRANSFER7文件传输预留未实现关键设计Message类的readObject()方法中defaultReadObject()后立即校验type是否在合法范围内private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); if (type 1 || type 7) { throw new InvalidClassException(Invalid message type: type); } }这是反序列化安全的最小实践。如果没有此校验攻击者可构造恶意type999触发后续 switch-case 的default分支造成未定义行为。Java 序列化漏洞频发这种白名单校验是低成本高收益的防御。6. 从「能跑」到「能讲」用三个验证技巧把项目变成你的技术名片6.1 验证消息一致性用 Wireshark 抓包对比 Socket 流与数据库记录很多开发者只测 UI却不知消息是否真被 Server 处理。最硬核的验证方式是抓包启动 Server 和两个 ClientA/B在 A 的聊天窗发送「测试123」立即打开 Wireshark过滤tcp.port8888Server 默认端口查看 TCP Stream确认 A 发送的ObjectStream中msg_content测试123同时查 MySQLSELECT * FROM message_record WHERE msg_content LIKE %测试123%;若 Wireshark 有、DB 没有 → Server 落库失败检查MessageDao.saveMessage()是否被调用若 DB 有、Wireshark 没有 → Client 未真正发送检查clientSocket.getOutputStream().writeObject()是否执行两者都有但内容不一致 → 序列化/反序列化出错检查Message类字段是否transient或static。我从那以后每次重构网络模块都强制走一遍 Wireshark DB 对照。它比断点调试更接近真相——因为你能看到字节流本身而不是 JVM 解析后的对象。6.2 验证线程安全性用 jstack 分析 ServerThread 的锁竞争当群聊人数 50 时Server 可能变慢。用jstack查看线程状态# 查找 Server 进程 PID jps -l | grep ServerMain # 导出线程栈 jstack PID server_threads.txt重点关注ServerThread线程是否处于BLOCKED状态。常见瓶颈点GroupHandler.getGroupMembers()查询数据库未加索引 → 在friend.group_name字段建索引MessageDao.saveMessage()的 JDBC 连接未池化 → 如前文所述引入 HikariCPServerThread.run()中synchronized(socket)块过长 → 将消息解析、业务处理、落库拆分为异步任务。6.3 验证 GUI 响应性用 VisualVM 监控 Event Dispatch ThreadSwing 卡顿往往因 EDTEvent Dispatch Thread被阻塞。启动 VisualVM连接 Client 进程切换到「Sampler」→ 「CPU」→ 「Record」在聊天窗疯狂点击发送按钮停止采样后查看热点方法若ChatWindow.sendMessage()占比 80%说明业务逻辑如 IO在 EDT 中执行修复将clientSocket.getOutputStream().writeObject(msg)移到新线程new Thread(() - { try { clientSocket.getOutputStream().writeObject(msg); } catch (IOException e) { e.printStackTrace(); } }).start();从那以后我每次写 Swing 项目都强制在ActionListener里加一行System.out.println(EDT: EventQueue.isDispatchThread());。如果输出 false立刻重构——因为 GUI 线程不是你的试验田它是用户眼中的「世界是否卡住」的唯一标尺。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

英文版Linux的真相与安装切换指南:从镜像选择到locale管理

英文版Linux的真相与安装切换指南:从镜像选择到locale管理

有朋友问我:“Linux有没有英文版?给我个下载地址。”我愣了一下,细想才明白他其实想问的是——装出来的系统怎么界面是英文的,能不能一步到位直接装成英文的。这个问题我一年能遇到好几回,尤其是刚接触Linux的人&#…

2026/10/8 14:49:12 阅读更多 →
VSCode+SFTP+WSL免密远程开发:SSH密钥配置与实战排坑全指南

VSCode+SFTP+WSL免密远程开发:SSH密钥配置与实战排坑全指南

最近因为要给一台远程开发机配一套顺手的工作环境,我把 VSCode SFTP WSL 这套无密码远程开发流程从头到尾踩了一遍,今天把关键操作和坑一次性写清楚。标题里的三件事——vscode、sftp、秘钥(WSL 版)——其实是同一件事的三个环节…

2026/10/10 12:31:21 阅读更多 →
WSL2+OpenClaw+飞书机器人:从零部署AI助理全攻略

WSL2+OpenClaw+飞书机器人:从零部署AI助理全攻略

最近OpenClaw在AI圈子里热度确实高,很多人想把它跑起来当个人助理,结果翻官方文档发现主要是Linux和macOS的玩法,Windows用户只能绕路。我主力机就是Windows,最后选择WSL2装Ubuntu,把OpenClaw装好、飞书机器人接入也一…

2026/10/8 14:49:11 阅读更多 →

最新新闻

ADT下ABAP Unit高效测试:Quick Actions与高亮工作流

ADT下ABAP Unit高效测试:Quick Actions与高亮工作流

做了这么多年 ABAP 开发,我前前后后在 SE80、SE24、Eclipse ADT 之间横跳了不少次。真正让我下决心彻底切到 ADT 的,倒不是编辑器多好看,而是 ABAP Unit 测试这件事——以前在 SE24 里写测试、跑测试、看覆盖率,每一步都像是把车停…

2026/10/10 23:13:49 阅读更多 →
Elasticsearch调优实战:JVM堆内存、分片规划与Windows避坑指南

Elasticsearch调优实战:JVM堆内存、分片规划与Windows避坑指南

说实话,Elasticsearch 这个调优话题,网上教程已经多到泛滥了。但你随便翻十篇帖子,八篇都在让你改indices.query.bool.max_clause_count、调refresh_interval,改完就扔给你一个“性能提升十倍”的结论。我见过太多人按这种教程改完…

2026/10/10 23:12:48 阅读更多 →
从“一个人整理分支“到“给 Agent 立法“:Worktrunk 爆火暴露了工作流工具的重心迁移

从“一个人整理分支“到“给 Agent 立法“:Worktrunk 爆火暴露了工作流工具的重心迁移

从"一个人整理分支"到"给 Agent 立法":Worktrunk 爆火暴露了工作流工具的重心迁移 【免费下载链接】worktrunk Worktrunk is a CLI for Git worktree management, designed for parallel AI agent workflows 项目地址: https://gitcode.com/G…

2026/10/10 23:12:48 阅读更多 →
蓝桥杯省赛真题怎么刷?第十六届真题解析与备赛策略

蓝桥杯省赛真题怎么刷?第十六届真题解析与备赛策略

每一届蓝桥杯省赛结束之后,都有大量同学来找我聊同一个问题:“真题到底该怎么刷?我现在开始备赛,是先做题库还是先做真题?”我的答案一直没变过:真题永远是效率最高的切入点。第十六届省赛题目我也在持续整…

2026/10/10 23:12:48 阅读更多 →
没有显卡也能跑:GLiNER2.5-Decide CPU 部署全流程,含批量请求与长文档处理

没有显卡也能跑:GLiNER2.5-Decide CPU 部署全流程,含批量请求与长文档处理

没有显卡也能跑:GLiNER2.5-Decide CPU 部署全流程,含批量请求与长文档处理 【免费下载链接】GLiNER2.5-Decide 项目地址: https://ai.gitcode.com/hf_mirrors/fastino/GLiNER2.5-Decide 当一个 340M 参数、基于 DeBERTa-v3-large 的英文分类模型…

2026/10/10 23:12:48 阅读更多 →
验证码识别全链路实战:从数据清洗到CRNN部署

验证码识别全链路实战:从数据清洗到CRNN部署

简介:本资源是一套面向深度学习初学者与图像识别实践者的字符型数字验证码识别完整实现方案,聚焦网络安全中验证码攻防场景下的模型训练与部署实战。资源包含1210个文件,主体为978张PNG与202张JPG格式的验证码样本图像,辅以17个核…

2026/10/10 23:11:47 阅读更多 →

日新闻

卫星轨道分类全解析:从LEO到GEO的选型逻辑与工程实践

卫星轨道分类全解析:从LEO到GEO的选型逻辑与工程实践

1. 从“卫星轨道分类”这个标题说起:为什么值得花时间搞懂第一次接触“卫星轨道分类”这个概念,很多人会觉得它离自己很远——不就是天上的星星怎么转吗?但如果你正在做航天任务规划、遥感数据接收、星座设计,甚至只是准备一场航天…

2026/10/10 0:00:39 阅读更多 →
Spring AOP 核心原理与实战:从概念到日志切面落地

Spring AOP 核心原理与实战:从概念到日志切面落地

1. 从一个真实痛点说起:为什么你的代码里到处都是重复逻辑刚入行那会儿,我写过一个用户管理模块,注册、登录、改密码、注销四个接口。每个接口里都塞了几乎一样的日志打印、参数校验、事务开启和提交。当时觉得没什么,能跑就行。直…

2026/10/10 0:00:40 阅读更多 →
Python招聘数据采集与分析可视化:从采集清洗到薪资技能城市可视化全链路

Python招聘数据采集与分析可视化:从采集清洗到薪资技能城市可视化全链路

简介:这是一套面向计算机相关专业学生与项目实战学习者的Python数据采集与分析可视化完整项目,以Boss直聘岗位数据为对象,适合用作毕业设计、课程设计或期末大作业。资源包共38个文件,约246KB,以13个py源码文件为核心&…

2026/10/10 0:00:40 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 11:14:25 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 1:36:08 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 11:14:58 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 5:23:50 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 21:32:20 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 10:38:42 阅读更多 →