Java通讯录管理系统课程设计:Swing+JDBC实现增删改查与分层架构

简介:这是一份面向Java初学者与课程设计学习者的通讯录管理系统完整项目源码,对应Java课程设计综合题,要求采用JDBC连接数据库,界面可选Swing GUI或JSP技术实现。系统涵盖用户注册登录、通讯录信息的浏览、查找与增删改维护等核心功能,适合用来练习面向对象编程思想,理解类的设计、继承与多态,并掌握Swing窗体、面板、按钮、文本框等组件的使用及事件处理机制。资源包共5个文件,包含4个java源码文件与1个sql数据库脚本,压缩包约8KB,其中java文件分别对应登录界面、注册界面、通讯录主界面与数据库连接工具类,sql文件用于建库建表,结构清晰便于对照学习。目前已有1562人学习下载。通过这份资源,读者可获得一套可直接运行的课程设计参考方案,学习JDBC连接MySQL、数据库表结构设计及增删改查操作,并体会模块化拆分系统的设计思路,适合作为课程设计起步或期末项目参考。

1. 通讯录管理系统:从课程设计到能跑起来的 Java 项目

很多同学的 Java 课程设计都卡在同一个地方:功能想得挺全,代码一跑就报错,界面和数据库各玩各的。通讯录管理系统就是最典型的例子——看起来只是增删改查,真动手写的时候,联系人字段怎么设计、数据存哪里、界面怎么刷新,每一步都能踩坑。这个项目适合正在做 Java 课程设计、需要一份能直接跑通的参考实现的同学,也适合想拿它当模板改造成图书管理、学生信息管理的开发者。它用 Java 实现,覆盖联系人录入、查询、修改、删除、列表展示这些核心功能,数据持久化方案常见的有两种:文件存储和数据库存储。下面从项目定位、目录结构、核心代码到二次开发,完整拆一遍。

2. 项目定位与技术选型:为什么用 Java 做通讯录

2.1 这个项目到底解决什么问题

通讯录管理系统的本质是一个带持久化的 CRUD 应用。用户打开程序后,能录入联系人信息(姓名、电话、邮箱、分组等),能按姓名或电话搜索,能修改已有记录,能删除不再需要的联系人,退出程序后数据不丢失。听起来简单,但课程设计的要求通常不止于此——老师会看你的代码结构是否清晰、有没有分层、异常处理是否到位、界面是否可用。

这个项目的价值在于:它足够小,小到一个人几天能写完;又足够完整,完整到能体现 Java 面向对象、集合框架、IO 流或 JDBC、Swing 或 JavaFX 界面编程这些核心知识点。很多同学做课程设计时容易贪大,选个电商系统或者社交平台,结果功能没写完,代码一团乱。通讯录管理系统反而是最稳的选择,功能边界清晰,扩展方向也多。

从适用人群来看,如果你是刚学完 Java 基础、正在做课程设计的学生,这个项目能让你把零散的知识点串起来。如果你已经工作,想找个练手项目熟悉某个框架,通讯录管理系统也能当脚手架用。

2.2 技术选型:Swing + JDBC 还是 JavaFX + 文件存储

技术选型直接决定你后面写代码的难度和老师验收时的印象分。常见的组合有两种:

第一种是 Swing + JDBC + MySQL。Swing 是 Java 自带的桌面 GUI 库,不需要额外配置,资料多,遇到问题好搜。JDBC 连 MySQL 是课程设计里最标准的数据库方案,老师一看就知道你学过数据库。缺点是 Swing 界面比较丑,需要自己调布局,MySQL 还要装环境、建库建表。

第二种是 JavaFX + 文件存储(JSON 或 CSV)。JavaFX 界面更现代,Scene Builder 拖拽布局效率高。文件存储省去了装数据库的麻烦,用 Jackson 或 Gson 序列化联系人列表就行。缺点是 JavaFX 在部分 JDK 版本里需要单独引入模块,文件存储的并发和查询性能不如数据库。

我一般会推荐第一种组合,因为课程设计的验收场景通常是老师在你电脑上跑一遍,看功能是否完整、代码是否规范。Swing + JDBC 的代码结构更传统,分层清晰,老师一眼就能看出你用了 MVC 模式。而且数据库操作能体现你对 SQL 的掌握,加分项更多。

下面是一个典型的联系人表结构设计:

CREATE TABLE contact ( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(50) NOT NULL, phone VARCHAR(20) NOT NULL, email VARCHAR(100), group_name VARCHAR(30), remark VARCHAR(200), create_time DATETIME DEFAULT CURRENT_TIMESTAMP );

字段说明:id是自增主键,方便后续修改和删除时定位记录;name和phone设为非空,因为通讯录的核心就是这两项;group_name用来分类,比如“家人”“同事”“客户”;create_time记录创建时间,方便按时间排序。如果老师要求支持多个电话,可以再加一张contact_phone表做一对多关联,但课程设计一般不需要这么复杂。

2.3 分层架构:别把代码全塞进一个类里

很多同学写课程设计时习惯把所有代码写在一个Main类里,按钮事件里直接写 SQL,界面和业务逻辑混在一起。这样写当时爽,后面改一个字段要翻几百行代码,老师一看就皱眉头。

合理的做法是分层。常见的是三层结构:表现层(UI)、业务逻辑层(Service)、数据访问层(DAO)。表现层只负责展示和接收用户输入,业务逻辑层处理校验和流程控制,数据访问层只管和数据库打交道。实体类(Model)单独放一个包,贯穿三层。

这样分的好处是:改界面不影响业务逻辑,换数据库不影响界面。老师问你“如果换成文件存储怎么办”,你可以说“只需要改 DAO 层的实现,Service 和 UI 不用动”。这就是加分项。

3. 目录结构与核心模块拆解:从入口到数据落库

3.1 项目目录结构

一个标准的 Maven 项目结构如下:

contact-manager/ ├── src/ │ ├── main/ │ │ ├── java/ │ │ │ └── com/example/contact/ │ │ │ ├── Main.java // 程序入口 │ │ │ ├── model/ │ │ │ │ └── Contact.java // 联系人实体 │ │ │ ├── dao/ │ │ │ │ ├── ContactDao.java // DAO 接口 │ │ │ │ └── ContactDaoImpl.java // JDBC 实现 │ │ │ ├── service/ │ │ │ │ └── ContactService.java // 业务逻辑 │ │ │ ├── ui/ │ │ │ │ ├── MainFrame.java // 主窗口 │ │ │ │ └── ContactDialog.java // 新增/编辑弹窗 │ │ │ └── util/ │ │ │ └── DBUtil.java // 数据库连接工具 │ │ └── resources/ │ │ └── db.properties // 数据库配置 └── pom.xml

这个结构里,model包放实体类,dao包放数据访问代码,service包放业务逻辑,ui包放界面,util包放工具类。每个包职责单一,找代码的时候直接按包名定位。

3.2 实体类与数据库连接

先看实体类Contact.java:

package com.example.contact.model; public class Contact { private int id; private String name; private String phone; private String email; private String groupName; private String remark; // 无参构造,JDBC 反射需要 public Contact() {} // 新增时用的构造,不需要 id public Contact(String name, String phone, String email, String groupName, String remark) { this.name = name; this.phone = phone; this.email = email; this.groupName = groupName; this.remark = remark; } // getter 和 setter 省略,实际项目里要写全 public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } // ... 其他 getter/setter }

实体类的作用是承载数据。注意这里保留了一个无参构造,因为后面用 JDBC 从ResultSet映射对象时,通常会先new一个空对象再逐个set。如果你用 MyBatis 或 Hibernate,无参构造也是必须的。

再看数据库连接工具DBUtil.java:

package com.example.contact.util; import java.io.InputStream; import java.sql.Connection; import java.sql.DriverManager; import java.util.Properties; public class DBUtil { private static String url; private static String username; private static String password; // 静态块在类加载时读取配置文件 static { try (InputStream in = DBUtil.class.getClassLoader() .getResourceAsStream("db.properties")) { Properties props = new Properties(); props.load(in); url = props.getProperty("db.url"); username = props.getProperty("db.username"); password = props.getProperty("db.password"); Class.forName(props.getProperty("db.driver")); } catch (Exception e) { throw new RuntimeException("数据库配置加载失败", e); } } public static Connection getConnection() throws Exception { return DriverManager.getConnection(url, username, password); } }

这段代码的关键点:配置文件db.properties放在resources目录下,打包后会自动进入 classpath。静态块只执行一次,避免每次获取连接都读文件。Class.forName加载驱动,MySQL 8 以上用com.mysql.cj.jdbc.Driver。连接用完记得关闭,后面 DAO 里会用 try-with-resources 处理。

db.properties内容示例:

db.driver=com.mysql.cj.jdbc.Driver db.url=jdbc:mysql://localhost:3306/contact_db?useSSL=false&serverTimezone=UTC db.username=root db.password=123456

3.3 DAO 层:增删改查的 JDBC 实现

DAO 层是课程设计的核心,老师重点看的就是这里。先定义接口:

package com.example.contact.dao; import com.example.contact.model.Contact; import java.util.List; public interface ContactDao { void insert(Contact contact) throws Exception; void update(Contact contact) throws Exception; void delete(int id) throws Exception; Contact findById(int id) throws Exception; List<Contact> findAll() throws Exception; List<Contact> searchByName(String keyword) throws Exception; }

接口定义好之后,实现类ContactDaoImpl.java里写具体 SQL:

package com.example.contact.dao; import com.example.contact.model.Contact; import com.example.contact.util.DBUtil; import java.sql.*; import java.util.ArrayList; import java.util.List; public class ContactDaoImpl implements ContactDao { @Override public void insert(Contact contact) throws Exception { String sql = "INSERT INTO contact(name, phone, email, group_name, remark) " + "VALUES(?, ?, ?, ?, ?)"; try (Connection conn = DBUtil.getConnection(); PreparedStatement ps = conn.prepareStatement(sql)) { ps.setString(1, contact.getName()); ps.setString(2, contact.getPhone()); ps.setString(3, contact.getEmail()); ps.setString(4, contact.getGroupName()); ps.setString(5, contact.getRemark()); ps.executeUpdate(); } } @Override public List<Contact> findAll() throws Exception { String sql = "SELECT * FROM contact ORDER BY create_time DESC"; List<Contact> list = new ArrayList<>(); try (Connection conn = DBUtil.getConnection(); PreparedStatement ps = conn.prepareStatement(sql); ResultSet rs = ps.executeQuery()) { while (rs.next()) { list.add(mapRow(rs)); } } return list; } @Override public List<Contact> searchByName(String keyword) throws Exception { String sql = "SELECT * FROM contact WHERE name LIKE ? OR phone LIKE ?"; List<Contact> list = new ArrayList<>(); try (Connection conn = DBUtil.getConnection(); PreparedStatement ps = conn.prepareStatement(sql)) { String pattern = "%" + keyword + "%"; ps.setString(1, pattern); ps.setString(2, pattern); try (ResultSet rs = ps.executeQuery()) { while (rs.next()) { list.add(mapRow(rs)); } } } return list; } // 把 ResultSet 当前行映射成 Contact 对象 private Contact mapRow(ResultSet rs) throws SQLException { Contact c = new Contact(); c.setId(rs.getInt("id")); c.setName(rs.getString("name")); c.setPhone(rs.getString("phone")); c.setEmail(rs.getString("email")); c.setGroupName(rs.getString("group_name")); c.setRemark(rs.getString("remark")); return c; } }

这里有几个关键点。第一,用PreparedStatement而不是Statement,防止 SQL 注入,这是课程设计的必查项。第二,try-with-resources自动关闭连接、语句和结果集,避免资源泄漏。第三,mapRow方法把结果集映射抽出来,多个查询方法复用,减少重复代码。第四,搜索用LIKE加%通配符,支持模糊匹配姓名和电话。

update和delete方法结构类似,只是 SQL 不同,这里不再重复贴。注意update的 SQL 要带WHERE id = ?,delete同理。

3.4 Service 层:校验与业务逻辑

Service 层不是简单转发 DAO 调用,它要处理业务规则。比如新增联系人时,姓名和电话不能为空,电话格式要校验,重复电话要提示。这些逻辑放在 Service 里,UI 层只管调用。

package com.example.contact.service; import com.example.contact.dao.ContactDao; import com.example.contact.dao.ContactDaoImpl; import com.example.contact.model.Contact; import java.util.List; public class ContactService { private ContactDao dao = new ContactDaoImpl(); public void addContact(Contact contact) throws Exception { // 校验必填字段 if (contact.getName() == null || contact.getName().trim().isEmpty()) { throw new IllegalArgumentException("姓名不能为空"); } if (contact.getPhone() == null || contact.getPhone().trim().isEmpty()) { throw new IllegalArgumentException("电话不能为空"); } // 校验电话格式,简单用正则 if (!contact.getPhone().matches("\\d{7,15}")) { throw new IllegalArgumentException("电话格式不正确"); } dao.insert(contact); } public List<Contact> listAll() throws Exception { return dao.findAll(); } public List<Contact> search(String keyword) throws Exception { if (keyword == null || keyword.trim().isEmpty()) { return dao.findAll(); } return dao.searchByName(keyword.trim()); } public void deleteContact(int id) throws Exception { dao.delete(id); } }

Service 层的校验逻辑是老师常问的点。为什么不在 UI 层校验?因为 UI 层可能被替换,比如从 Swing 换成 Web 界面,校验逻辑不应该跟着重写。放在 Service 层,任何调用方都能复用同一套规则。

3.5 UI 层:Swing 主窗口与表格刷新

UI 层用 Swing 实现,主窗口包含一个JTable展示联系人列表,顶部有搜索框和按钮,底部有新增、编辑、删除按钮。核心是表格的数据模型和刷新逻辑。

package com.example.contact.ui; import com.example.contact.model.Contact; import com.example.contact.service.ContactService; import javax.swing.*; import javax.swing.table.DefaultTableModel; import java.awt.*; import java.util.List; public class MainFrame extends JFrame { private ContactService service = new ContactService(); private DefaultTableModel tableModel; private JTable table; private JTextField searchField; public MainFrame() { setTitle("通讯录管理系统"); setSize(800, 500); setDefaultCloseOperation(EXIT_ON_CLOSE); setLocationRelativeTo(null); initUI(); refreshTable(); } private void initUI() { // 表格列名 String[] columns = {"ID", "姓名", "电话", "邮箱", "分组", "备注"}; tableModel = new DefaultTableModel(columns, 0) { @Override public boolean isCellEditable(int row, int column) { return false; // 表格只读,编辑走弹窗 } }; table = new JTable(tableModel); // 顶部搜索栏 JPanel topPanel = new JPanel(new FlowLayout(FlowLayout.LEFT)); searchField = new JTextField(15); JButton searchBtn = new JButton("搜索"); searchBtn.addActionListener(e -> doSearch()); topPanel.add(new JLabel("姓名/电话:")); topPanel.add(searchField); topPanel.add(searchBtn); // 底部操作按钮 JPanel bottomPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT)); JButton addBtn = new JButton("新增"); JButton editBtn = new JButton("编辑"); JButton deleteBtn = new JButton("删除"); addBtn.addActionListener(e -> openDialog(null)); editBtn.addActionListener(e -> { int row = table.getSelectedRow(); if (row < 0) { JOptionPane.showMessageDialog(this, "请先选中一行"); return; } int id = (int) tableModel.getValueAt(row, 0); openDialog(id); }); deleteBtn.addActionListener(e -> doDelete()); bottomPanel.add(addBtn); bottomPanel.add(editBtn); bottomPanel.add(deleteBtn); add(topPanel, BorderLayout.NORTH); add(new JScrollPane(table), BorderLayout.CENTER); add(bottomPanel, BorderLayout.SOUTH); } private void refreshTable() { try { List<Contact> list = service.listAll(); tableModel.setRowCount(0); // 清空旧数据 for (Contact c : list) { tableModel.addRow(new Object[]{ c.getId(), c.getName(), c.getPhone(), c.getEmail(), c.getGroupName(), c.getRemark() }); } } catch (Exception ex) { JOptionPane.showMessageDialog(this, "加载失败:" + ex.getMessage()); } } private void doSearch() { try { List<Contact> list = service.search(searchField.getText()); tableModel.setRowCount(0); for (Contact c : list) { tableModel.addRow(new Object[]{ c.getId(), c.getName(), c.getPhone(), c.getEmail(), c.getGroupName(), c.getRemark() }); } } catch (Exception ex) { JOptionPane.showMessageDialog(this, "搜索失败:" + ex.getMessage()); } } private void doDelete() { int row = table.getSelectedRow(); if (row < 0) { JOptionPane.showMessageDialog(this, "请先选中一行"); return; } int id = (int) tableModel.getValueAt(row, 0); int confirm = JOptionPane.showConfirmDialog(this, "确定删除?"); if (confirm == JOptionPane.YES_OPTION) { try { service.deleteContact(id); refreshTable(); } catch (Exception ex) { JOptionPane.showMessageDialog(this, "删除失败:" + ex.getMessage()); } } } private void openDialog(Integer id) { // 打开新增/编辑弹窗,传 null 表示新增 ContactDialog dialog = new ContactDialog(this, id); dialog.setVisible(true); refreshTable(); // 弹窗关闭后刷新表格 } public static void main(String[] args) { SwingUtilities.invokeLater(() -> new MainFrame().setVisible(true)); } }

这段代码里,DefaultTableModel的isCellEditable返回false,让表格只读,避免用户直接在表格里改数据导致状态不一致。refreshTable每次先setRowCount(0)清空再重新填充,这是 Swing 表格刷新的标准做法。搜索和删除操作后都调用刷新,保证界面和数据同步。

ContactDialog是新增/编辑弹窗,里面放JTextField接收输入,点保存时调用service.addContact或service.updateContact。这里不再展开,结构类似。

4. 避坑与常见问题:课程设计里最容易翻车的地方

4.1 数据库连不上,报 ClassNotFoundException

现象:程序启动时报java.lang.ClassNotFoundException: com.mysql.cj.jdbc.Driver。

原因:MySQL 驱动 jar 包没有加到项目依赖里。如果你用 Maven,pom.xml里没写mysql-connector-java依赖;如果是普通项目,WEB-INF/lib或 classpath 里没有驱动 jar。

解决:Maven 项目在pom.xml加依赖:

<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.33</version> </dependency>

普通项目把 jar 包放到lib目录,然后在 IDE 里右键添加到 classpath。注意 MySQL 8 以上驱动类名是com.mysql.cj.jdbc.Driver,不是旧的com.mysql.jdbc.Driver。

4.2 中文乱码,姓名存进去变成问号

现象:联系人姓名是中文,存到数据库后变成???,或者界面显示乱码。

原因:数据库字符集不是utf8mb4,或者 JDBC URL 没指定编码。

解决:建库时指定字符集:

CREATE DATABASE contact_db DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;

JDBC URL 加上useUnicode=true&characterEncoding=utf8:

db.url=jdbc:mysql://localhost:3306/contact_db?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=UTC

如果已经建了库,用ALTER DATABASE contact_db CHARACTER SET utf8mb4;修改。

4.3 表格数据不刷新,改了数据库界面没变

现象:新增联系人后,数据库里有了,但表格还是旧数据。

原因:refreshTable没有在新增/编辑/删除后调用,或者tableModel没有清空旧数据直接追加。

解决:每次数据变更后调用refreshTable(),并且刷新时先tableModel.setRowCount(0)清空。不要用tableModel.fireTableDataChanged()单独触发,因为数据源没变的话界面不会更新。

4.4 关闭连接报错,或者连接数过多

现象:程序运行一段时间后报Too many connections,或者关闭窗口时抛异常。

原因:DAO 里获取的Connection没有关闭,或者关闭顺序不对。

解决:统一用try-with-resources,把Connection、PreparedStatement、ResultSet都放在 try 的括号里,JVM 会自动按相反顺序关闭。不要手动在finally里写close(),容易漏或者顺序错。

4.5 搜索没结果,但数据库里明明有数据

现象:输入姓名搜索,返回空列表。

原因:SQL 里用了=而不是LIKE,或者%拼错了位置。

解决:模糊搜索用LIKE ?,参数拼成"%" + keyword + "%"。如果搜电话,注意电话字段是字符串类型,不要当数字处理。另外检查keyword有没有trim(),用户输入前后空格会导致匹配失败。

5. 二次开发与改造:从通讯录到通用管理系统

5.1 换数据库:从 MySQL 到 SQLite

课程设计验收时,老师可能不想装 MySQL。把数据库换成 SQLite 是最省事的改造。SQLite 不需要服务端,一个文件就是数据库。

改造步骤:第一,pom.xml把 MySQL 驱动换成sqlite-jdbc。第二,db.properties改驱动和 URL:

db.driver=org.sqlite.JDBC db.url=jdbc:sqlite:contact.db db.username= db.password=

第三,建表 SQL 里AUTO_INCREMENT改成AUTOINCREMENT,DATETIME DEFAULT CURRENT_TIMESTAMP改成DEFAULT (datetime('now'))。DAO 层代码几乎不用动,因为 JDBC API 是统一的。这就是分层的好处——换存储只改配置和少量 SQL。

5.2 加功能:分组筛选与导入导出

通讯录管理系统最容易扩展的方向是分组和导入导出。分组筛选只需要在 Service 层加一个listByGroup(String group)方法,DAO 里加WHERE group_name = ?查询,UI 顶部加一个下拉框选择分组。

导入导出用 CSV 格式最方便。导出时遍历List<Contact>,每行拼成name,phone,email,group,remark写入文件。导入时用BufferedReader逐行读取,按逗号拆分,调用service.addContact。注意 CSV 里如果字段本身含逗号,要用双引号包裹,简单做法是导出前把逗号替换成中文逗号。

// 导出 CSV 的核心逻辑 public void exportToCsv(List<Contact> list, String filePath) throws Exception { try (BufferedWriter writer = new BufferedWriter( new OutputStreamWriter(new FileOutputStream(filePath), "UTF-8"))) { writer.write("姓名,电话,邮箱,分组,备注\n"); for (Contact c : list) { writer.write(String.join(",", c.getName(), c.getPhone(), c.getEmail(), c.getGroupName(), c.getRemark()) + "\n"); } } }

5.3 改造验证:怎么确认改完没坏

每次改造后,按这个顺序验证:先跑findAll看列表能不能加载,再跑insert看新增后表格是否刷新,然后跑search看模糊匹配是否正常,最后跑delete看删除后数据是否消失。如果换了数据库,重点验证建表语句和自增主键是否兼容。如果加了导入功能,用一个包含中文和特殊字符的 CSV 测试,确认编码没问题。

我一般会在改造前把原始版本跑一遍,记下每个功能的预期结果,改完后逐项对比。这样即使出了问题,也能快速定位是哪一步改坏了。

5.4 一个实用技巧:用接口隔离变化

如果你打算把这个项目写进简历,或者作为毕业设计的起点,建议把 DAO 层设计成可替换的。定义一个ContactRepository接口,然后分别写JdbcContactRepository和FileContactRepository两个实现。Service 层依赖接口而不是具体实现,通过工厂或依赖注入决定用哪个。

public interface ContactRepository { void save(Contact contact) throws Exception; List<Contact> findAll() throws Exception; // ... 其他方法 } public class RepositoryFactory { public static ContactRepository create(String type) { if ("file".equals(type)) { return new FileContactRepository(); } return new JdbcContactRepository(); } }

这样老师问你“如果不用数据库怎么办”,你可以直接切换实现,代码不用大改。这个技巧在课程设计答辩时很加分,因为它体现了你对面向接口编程的理解。

从那以后我每次做课程设计,都会先把接口定好再写实现,哪怕功能再简单也强制走一遍。这样后面加功能或者换方案的时候,不会因为牵一发动全身而翻车。希望帮到你。

本文还有配套的精品资源,点击获取

相关新闻

齿轮箱故障数据实战:从振动信号到诊断模型的完整链路

齿轮箱故障数据实战:从振动信号到诊断模型的完整链路

简介&#xff1a;齿轮箱故障数据.zip 面向从事机械故障诊断、信号处理与机器学习的研究生、工程师及算法爱好者&#xff0c;提供一套可直接用于实验与建模的齿轮箱运行数据集&#xff0c;帮助解决早期故障检测与预防性维护中的样本获取难题。压缩包共15个文件&#xff0c;约5.9…

2026/10/20 2:26:29 阅读更多 →
VLAN基本原理:802.1Q标签、Trunk与PVID排错实践

VLAN基本原理:802.1Q标签、Trunk与PVID排错实践

这是我网络学习日志的第13篇&#xff0c;主题锁定在VLAN基本原理。之所以把这么基础的东西单独拎出来写一篇&#xff0c;是因为前阵子在模拟项目X里搭实验时被它狠狠教育了一回&#xff1a;两台交换机的配置看起来没毛病&#xff0c;Access、Trunk都设了&#xff0c;但还是出现…

2026/10/20 2:26:29 阅读更多 →
上线 10 小时冲进 ModelScope 前十:DeepSeek 视觉实验版的开源速度战

上线 10 小时冲进 ModelScope 前十:DeepSeek 视觉实验版的开源速度战

上线 10 小时冲进 ModelScope 前十&#xff1a;DeepSeek 视觉实验版的开源速度战 【免费下载链接】DeepSeek-V4-Flash-Vision-Exp 项目地址: https://ai.gitcode.com/hf_mirrors/deepseek-ai/DeepSeek-V4-Flash-Vision-Exp 8 月底的这十天&#xff0c;AI 圈发生了两件事…

2026/10/20 2:26:29 阅读更多 →

最新新闻

企业信息收集一步到位:ENScan_GO 备案、APP、公众号聚合实战指南

企业信息收集一步到位:ENScan_GO 备案、APP、公众号聚合实战指南

企业信息收集一步到位&#xff1a;ENScan_GO 备案、APP、公众号聚合实战指南 【免费下载链接】ENScan_GO 一款基于各大企业信息API的工具&#xff0c;解决在遇到的各种针对国内企业信息收集难题。一键收集控股公司ICP备案、APP、小程序、微信公众号等信息聚合导出。支持MCP接入…

2026/10/20 19:21:40 阅读更多 →
风扇选型软件:从P-Q曲线到工作点计算与批量筛选

风扇选型软件:从P-Q曲线到工作点计算与批量筛选

简介&#xff1a;Optimiser风扇选型软件是Multi-Wing官方推出的一款轴流风扇选型工具&#xff0c;面向暖通空调、工业通风、冷却散热等领域的工程师与设备选型人员。使用者只需输入应用所需的风量、压力与能耗等参数&#xff0c;软件即可自动匹配莫迪温风扇型号&#xff0c;帮助…

2026/10/20 19:21:40 阅读更多 →
AI辅助项目管理实操:用CodeBuddy打造可对话的“活档案”

AI辅助项目管理实操:用CodeBuddy打造可对话的“活档案”

说实话&#xff0c;以前我对“用AI做项目管理”这事挺抵触的。项目管理讲究的是人对人的协作、决策和沟通&#xff0c;AI能插得上什么手&#xff1f;直到我连续带了三周迭代&#xff0c;发现自己一半精力被会议、同步、验收这些琐事磨掉了&#xff0c;才下定决心让CodeBuddy进项…

2026/10/20 19:21:40 阅读更多 →
免费开源 3D 打印切片软件 Bambu Studio:3 步出件,自动支撑、多色打印一次配齐

免费开源 3D 打印切片软件 Bambu Studio:3 步出件,自动支撑、多色打印一次配齐

免费开源 3D 打印切片软件 Bambu Studio&#xff1a;3 步出件&#xff0c;自动支撑、多色打印一次配齐 【免费下载链接】BambuStudio PC Software for BambuLab and other 3D printers 项目地址: https://gitcode.com/GitHub_Trending/ba/BambuStudio Bambu Studio 是一…

2026/10/20 19:21:40 阅读更多 →
SodaDownloader:汽水音乐链接解密提取FLAC/M4A的完整教程

SodaDownloader:汽水音乐链接解密提取FLAC/M4A的完整教程

简介&#xff1a;SodaDownloader是一款面向汽水音乐平台用户的便捷下载工具&#xff0c;只需复制分享链接即可解析歌曲信息&#xff0c;并支持FLAC无损音频和M4A高质量格式的解密与下载&#xff0c;让用户不进入平台也能获取高品质音乐文件。该源码工程压缩包共26个文件、仅72K…

2026/10/20 19:21:40 阅读更多 →
pandas动态时间窗口实现多周期销量统计

pandas动态时间窗口实现多周期销量统计

1. 项目概述&#xff1a;为什么“近X天销量统计”是业务分析的起点而非终点在某电商公司做数据支持的那两年&#xff0c;我每天早上八点准时打开BI看板&#xff0c;第一眼不是看总GMV&#xff0c;而是盯着“近7天销量趋势”那个小卡片——它像血压计一样&#xff0c;能快速判断…

2026/10/20 19:20:37 阅读更多 →

日新闻

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

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

2026/10/20 1:01:30 阅读更多 →
ESP32舵机控制指南:原理、多路驱动与避坑实战

ESP32舵机控制指南:原理、多路驱动与避坑实战

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

2026/10/20 1:01:30 阅读更多 →
位移法实现一阶低通滤波:单片机ADC采样降噪实战

位移法实现一阶低通滤波:单片机ADC采样降噪实战

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

2026/10/20 1:01:30 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型&#xff08;GMM&#xff09;的语音识别系统&#xff0c;很多人第一反应就是一堆数学公式&#xff0c;觉得门槛很高。但如果你真的在MATLAB里把它落地跑通&#xff0c;会发现核心其实就是三件事&#xff1a;把声音变成特征向量&#xff0c;用GMM给每个类别…

2026/10/20 10:02:13 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人&#xff0c;但落到具体操作上&#xff0c;无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程&#xff1a;对图像做反白、改调色板、彩色转灰度&#xff0c;最后把像素数据导出成txt文件。单看每一…

2026/10/19 17:32:41 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词&#xff0c;你会发现一个很有意思的现象&#xff1a;每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型&#xff0c;有人指的是运动控制系统&#xff0c;还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/20 2:50:50 阅读更多 →

月新闻

我发现了一个新思路:用 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/20 10:02:08 阅读更多 →
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/20 9:50:17 阅读更多 →
黑夜航拍船只数据集训练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/20 9:50:45 阅读更多 →