news 2026/9/24 20:22:03

Java+MySQL图书管理系统课程设计与源码实战:从环境部署到答辩指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Java+MySQL图书管理系统课程设计与源码实战:从环境部署到答辩指南

简介:一份基于Java与MySQL的图书管理系统项目,面向计算机相关专业正在完成课程设计、期末大作业的学生,也适合需要练习Swing+JDBC开发的入门学习者。项目经过严格调试,源码和数据库脚本配套完整,下载后可直接导入Eclipse/IDEA运行,配合附带的运行截图即可快速核对功能,省去从零搭建和排错的时间。压缩包内共133个文件,主要包含16个Java源码文件、1个SQL建库脚本、项目工程配置文件、54个class编译文件,以及58张PNG界面截图,整体大小仅3.38MB,轻量且目录清晰。从内容预览看,系统已实现登录窗口、主界面、图书类型管理、图书添加、图书查询及数据访问层等模块,覆盖典型图书管理业务,分层结构便于理解。目前已有227人学习下载,对需要快速交付课设或提升Java数据库编程能力的读者,是一份高性价比的直接参考。

1. 图书管理系统大作业的开箱体验:Java+MySQL为什么是课设常青树

如果你是计算机专业的学生,正在为Java课程设计或数据库期末大作业发愁,这套基于Java+MySQL的图书管理系统源码值得打开看一眼。它覆盖了登录、图书管理、图书类型管理、分页搜索这些课设必考功能,压缩包里既有源码也有数据库脚本,配置好环境就能直接跑。和那些前后端分离的SpringBoot工程不同,这是经典的Swing+JDBC+MySQL组合,代码量适中、逻辑直观,正好踩在课程设计的评分点上,给到95分以上不奇怪。它适合两类人:做课程设计想参考设计思路的学生,以及刚学完JDBC需要一个完整项目练手的学习者。先别急着双击运行,我们把结构拆开、环境配上、流程跑通,最后再聊答辩怎么准备。

2. 源码结构拆解:从类名反推系统的三个业务分层

2.1 压缩包里的class与java源码:先分清哪份是你需要的

拿到压缩包第一件事不是双击运行,而是先看目录结构。这个项目解压后,你大概率会看到两类文件并存:以.java结尾的源码文件,以及以.class结尾的编译产物。为什么会有.class?因为作者在交付前在IDE里编译运行过,IDE顺手把字节码输出到了源码目录里。对课程设计来说,.java才是要交给老师、写进报告、贴进答辩PPT的东西,.class直接忽略即可。不过换个角度想,.class能存在,说明这套代码至少在作者机器上编译通过过一次,对你来说是个好消息。

真正需要关注的类名都在项目正文里列出来了:LogOnFrm、MainFrm、BookManageInterfrm、BookTypeManageInterFrm、BookAddInterFrm、BookTypeAddInterFrm、BookPageSearchFrm、BookDao、JavaInterFrm。命名规律非常明显:以Frm结尾的是带边框的独立窗口,以Interfrm结尾的是嵌在窗口内部的面板或标签页。这种命名方式在老式Swing课设里非常常见,一眼就能看出哪个类是入口、哪个类是功能面板、哪个类是数据操作层。

2.2 类名到功能的映射:一张表看懂系统边界

对照类名和这类课设的通用实现,我梳理了下面这张职责对照表:

类名类型职责
LogOnFrm窗口类登录界面,系统唯一入口
MainFrm窗口类登录成功后的主界面,承载菜单与面板切换
BookManageInterfrm内部面板图书列表展示、编辑、删除操作入口
BookTypeManageInterFrm内部面板图书类型列表展示与维护入口
BookAddInterFrm内部面板新增图书表单面板
BookTypeAddInterFrm内部面板新增图书类型表单面板
BookPageSearchFrm窗口或面板分页搜索与结果展示
BookDao数据访问类图书相关所有SQL操作与结果集封装
JavaInterFrm内部面板按图书类别筛选或附加功能页

这张表传达了两个关键信息。第一,系统虽然功能不多,但界面类和逻辑类是分离的:所有Frm/Interfrm只负责事件监听、界面布局和数据展示,不直接写SQL;SQL全部收拢在BookDao里。第二,命名上Interfrm和Frm的区别意味着主窗口MainFrm很可能是用标签页或卡片布局把多个Interfrm面板组合起来的,这比一个窗口堆所有按钮的做法清爽得多。

课程设计评分老师看的就是这个。同样功能的两个项目,一个把所有代码写在JFrame里,另一个分了界面层、数据访问层、实体类层,分数差距往往在十分以上。别觉得分层是形式主义,老师看中的是你有没有工程化思维——哪怕只是一个只有几千行的课设,分层清楚就意味着后续加功能时不用大改,这就是软件工程课里反复强调的"低耦合"。

2.3 BookDao的核心写码方式:JDBC查询如何变成对象列表

BookDao是这套系统里含金量最高的一个类。它负责把MySQL里的图书表数据查出来,转换成Java对象,再交给界面层展示。先看一个典型的查询方法,这类课设的BookDao基本都是这个写法:

// BookDao.java:查询全部图书,带图书类型名称 public List<Book> findAll() { List<Book> list = new ArrayList<>(); String sql = "SELECT b.id, b.bookName, b.author, b.price, t.typeName " + "FROM t_book b LEFT JOIN t_booktype t ON b.typeId = t.id"; try (Connection conn = DBHelper.getConnection(); PreparedStatement ps = conn.prepareStatement(sql); ResultSet rs = ps.executeQuery()) { while (rs.next()) { Book book = new Book(); book.setId(rs.getInt("id")); book.setBookName(rs.getString("bookName")); book.setAuthor(rs.getString("author")); book.setPrice(rs.getDouble("price")); book.setTypeName(rs.getString("typeName")); list.add(book); } } catch (SQLException e) { e.printStackTrace(); } return list; }

代码逻辑拆开看并不复杂:先用LEFT JOIN把图书表和图书类型表关联起来,一条SQL同时拿到图书字段和类型名称;然后通过PreparedStatement执行查询,从ResultSet结果集里逐行取值,封装成Book对象;最后把多个Book对象放进List集合返回给界面层。这里有两个细节值得注意:一是用了try-with-resources写法,Connection、PreparedStatement、ResultSet三个资源在try结束时自动关闭,省去了手写finally关闭的样板代码;二是用了LEFT JOIN而不是INNER JOIN,这样即使某本书没有关联类型,查询结果也不会丢记录。

参数上,getInt、getString、getDouble分别对应数据库的int、varchar、double类型字段,顺序无所谓,只要列名写对就行。界面层拿到List<Book>之后,直接丢给JTable的TableModel做展示,这就是BookManageInterfrm里最核心的一段数据流。理解了BookDao,后面不管是改查询条件还是加分页功能,思路都会顺很多。

3. 环境部署与数据库导入:让SQL脚本在你机器上跑通的完整流程

3.1 环境版本怎么选:JDK 8加MySQL 5.7是课设最稳组合

很多同学卡在第一步不是代码问题,而是环境版本不对。这套系统和大多数Java课设一样,用的是老一套JDBC驱动逻辑。我建议的组合是JDK 8配上MySQL 5.7,这两个版本搭配最省心:驱动类名用com.mysql.jdbc.Driver就能直接识别,不需要处理新版驱动的一堆时区、SSL参数。

如果你机器上装的是MySQL 8.0,问题也不大,但要注意两个变化:驱动类名要改成com.mysql.cj.jdbc.Driver,连接URL要额外加上serverTimezone=Asia/Shanghai,否则会报时区错误。这里我把两种版本的关键差异整理成一条对比:

版本驱动类名URL中的附加参数
MySQL 5.xcom.mysql.jdbc.Driver一般不需要
MySQL 8.0+com.mysql.cj.jdbc.DriverserverTimezone=Asia/Shanghai&useSSL=false

JDK建议直接用8,别一上来就上17或21。不是说新版不行,而是Swing课设里依赖的老库(比如某些版本的MySQL Connector/J)在更高JDK下会碰到模块化限制,报一些你听都没听过的错误。课设要的是稳定交付,不是追新版本。

3.2 导入数据库:命令行与Navicat两条路都走一遍

数据库脚本一般在压缩包里的.sql文件中。导入前先建一个空库,再把脚本导进去。命令行方式是最直接的,打开终端进入MySQL命令后执行:

CREATE DATABASE IF NOT EXISTS book_db DEFAULT CHARSET utf8 COLLATE utf8_general_ci; USE book_db; SOURCE /your/path/book_db.sql;

上面这段做了三件事:建一个名为book_db的数据库,字符集指定成utf8;切换到该库;执行外部SQL脚本文件。SOURCE后面要写你本机解压后book_db.sql文件的绝对路径,路径中有空格就用双引号包起来。执行成功后,用SHOW TABLES;应该能看到t_book、t_booktype、t_user这类表。

用Navicat导入更直观:左侧右键连接选新建数据库,名字和字符集填好;然后选中新建的数据库,右键选择"运行SQL文件",选到book_db.sql执行就行。导入完成后注意点开表看看数据行数,图书表里应该有几条作者预置的测试数据,登录表里也应该有默认用户名和密码。如果表是空的,说明脚本没执行完整,重新导入一次,或者检查脚本里是否有DROP TABLE语句把数据清掉了。

3.3 修改连接配置:DBHelper类里的四个参数

代码运行前必须改数据库连接配置,这个配置几乎都写在一个DBHelper或DBUtil类里,也可能直接写在每个Dao类的static块中。项目里的BookDao要连接MySQL,连接参数就藏在这个工具类里。常见的写法长这样:

// DBHelper.java:数据库连接工具类 public class DBHelper { private static final String DRIVER = "com.mysql.jdbc.Driver"; private static final String URL = "jdbc:mysql://localhost:3306/book_db" + "?useUnicode=true&characterEncoding=utf8"; private static final String USER = "root"; private static final String PASSWORD = "123456"; static { try { Class.forName(DRIVER); } catch (ClassNotFoundException e) { e.printStackTrace(); } } public static Connection getConnection() throws SQLException { return DriverManager.getConnection(URL, USER, PASSWORD); } }

改动主要集中在四个地方:第一是URL里的端口号3306,如果你MySQL改过端口,这里要同步;第二是URL路径里的book_db,必须和3.2节建的库名一致;第三是USER,默认root;第四是PASSWORD,要填你自己MySQL的密码。URL中间还有一段useUnicode=true&characterEncoding=utf8,这是控制中文不乱码的关键参数,建议保留。

改完之后先在IDE里写个简单的main方法测一下连接:

public static void main(String[] args) { try { Connection conn = DBHelper.getConnection(); System.out.println("数据库连接成功:" + conn); conn.close(); } catch (SQLException e) { e.printStackTrace(); } }

能打印出连接对象说明配置没问题。这一步值得做,它能把"环境问题"和"代码问题"快速切开,后面跑不起来时你不用东猜西猜。

3.4 IDE导入项目与入口类启动顺序

Eclipse和IDEA的导入方式略有不同:Eclipse是File→Import→General→Existing Projects into Workspace,选中解压后的项目根目录;IDEA是File→New→Project from Existing Sources,同样指向项目目录,然后选Import project from external model,用Eclipse方式导入。导入后先做一件事:确认项目里有没有MySQL驱动jar包,也就是mysql-connector-java那一系列jar。如果Build Path里没有,去Maven仓库下载匹配版本的jar,放到项目里并Add to Build Path。没有驱动包,第2.3节里的Class.forName("com.mysql.jdbc.Driver")第一行就报错。

入口类很明确:运行LogOnFrm,不是MainFrm。我见过有人直接右键MainFrm启动,结果弹了个空窗口或者报了一堆空指针异常。原因很简单:MainFrm主界面依赖当前登录用户信息,这些信息是在登录成功后写入内存的,绕过登录直接打开主界面,很多初始化变量还没赋值,自然就崩了。正确顺序是运行LogOnFrm,登录成功后由它来打开MainFrm并把当前用户传过去。

启动之后,界面弹出窗口说明系统已经在跑了。用预置的管理员账号登录,如果提示用户名或密码错误,先回MySQL确认t_user表里的数据,大概率是密码加密方式或明文差异的问题,这类课设一般都用明文比对,改一下表里的密码即可。

4. 核心模块实现细节:登录、图书增删和分页搜索的写码思路

4.1 登录模块:LogOnFrm的主流程与两个安全细节

登录是整个系统的门面,也是评卷老师大概率会试的第一个功能。LogOnFrm的逻辑不复杂:用户在界面上输入用户名和密码,点击登录按钮后,系统从输入框取值,调用Dao层方法去数据库比对,比对成功就打开MainFrm,失败就在当前窗口弹提示。核心校验代码的骨架一般是这样的:

// 登录按钮的事件监听器内部 String username = txtUsername.getText().trim(); String password = new String(txtPassword.getPassword()); boolean ok = bookDao.checkLogin(username, password); if (ok) { new MainFrm(username).setVisible(true); dispose(); } else { JOptionPane.showMessageDialog(this, "用户名或密码错误"); }

这里有两个细节值得注意,也是能拿来答辩时讲的点。第一,密码框用的是getPassword()方法而不是getText(),前者返回的是char数组,可以通过手动清空数组内容来避免密码字符串滞留在内存中,这是Swing里密码输入的标准做法。第二,getText()后面跟了trim(),去掉用户误输入的首尾空格,防止"admin "和"admin"比对不上这种低级问题。

对应的Dao层SQL就是一个简单的等值查询,用COUNT判断记录数是否大于0:

// BookDao中的登录校验方法 public boolean checkLogin(String username, String password) { String sql = "SELECT COUNT(*) FROM t_user WHERE username = ? AND password = ?"; try (Connection conn = DBHelper.getConnection(); PreparedStatement ps = conn.prepareStatement(sql)) { ps.setString(1, username); ps.setString(2, password); try (ResultSet rs = ps.executeQuery()) { if (rs.next()) { return rs.getInt(1) > 0; } } } catch (SQLException e) { e.printStackTrace(); } return false; }

这里用了PreparedStatement而不是直接拼接字符串,原因是防SQL注入。用占位符?先把SQL骨架固定,再将用户输入作为参数传进去,MySQL驱动会自动转义特殊字符。答辩时如果老师问"你为什么用PreparedStatement不用Statement",这个回答既准确又能体现你上课听讲了。

4.2 图书新增与类型管理:表单数据落到MySQL的完整链路

BookAddInterFrm负责收集新书信息,界面一般有书名字段、作者字段、价格字段、类型下拉框。用户点保存后,界面层收集数据,组装成Book对象,传给BookDao的insert方法。类型下拉框的数据则来自BookTypeManageInterFrm管理的那张类型表。新增图书的核心SQL就是一条INSERT:

// BookDao中的新增方法 public boolean addBook(Book book) { String sql = "INSERT INTO t_book (bookName, author, price, typeId) VALUES (?, ?, ?, ?)"; try (Connection conn = DBHelper.getConnection(); PreparedStatement ps = conn.prepareStatement(sql)) { ps.setString(1, book.getBookName()); ps.setString(2, book.getAuthor()); ps.setDouble(3, book.getPrice()); ps.setInt(4, book.getTypeId()); return ps.executeUpdate() > 0; } catch (SQLException e) { e.printStackTrace(); } return false; }

executeUpdate()返回的是受影响的行数,插入成功返回1,失败返回0或抛异常。这里有一个常见问题:如果图书表还有一个ISBN字段且设置了唯一约束,同一个ISBN插入两次就会抛DuplicateKeyException,代码里如果没有捕获这个异常并提示用户,用户体验就是点按钮没反应。规范的写法是单独捕获这个异常,弹窗提示"该书编号已存在"。

图书类型管理(BookTypeAddInterFrm)的逻辑几乎一模一样,只是SQL从操作图书表换成操作类型表。需要注意类型表和图书表之间存在外键关联,如果试图删除一个已被图书引用的类型,数据库会因外键约束而删除失败。代码里应该先查该类型下有没有图书,有就提示用户先处理图书。很多课设没有处理这个细节,答辩时老师一旦删一个关联类型,当场翻车。

4.3 分页搜索:LIMIT、偏移量、总记录数三者怎么配合

分页是这套系统里最能体现功力的模块,也是BookPageSearchFrm存在的意义。搜索的核心由两部分组成:查询当前页数据,以及查询满足条件的总条数。先看查询当前页数据的方法:

// BookDao中的分页搜索方法 public List<Book> searchBooks(String keyword, int pageNum, int pageSize) { List<Book> list = new ArrayList<>(); int offset = (pageNum - 1) * pageSize; String sql = "SELECT b.id, b.bookName, b.author, b.price, t.typeName " + "FROM t_book b LEFT JOIN t_booktype t ON b.typeId = t.id " + "WHERE b.bookName LIKE ? LIMIT ?, ?"; try (Connection conn = DBHelper.getConnection(); PreparedStatement ps = conn.prepareStatement(sql)) { ps.setString(1, "%" + keyword + "%"); ps.setInt(2, offset); ps.setInt(3, pageSize); try (ResultSet rs = ps.executeQuery()) { while (rs.next()) { Book book = new Book(); book.setId(rs.getInt("id")); book.setBookName(rs.getString("bookName")); book.setAuthor(rs.getString("author")); book.setPrice(rs.getDouble("price")); book.setTypeName(rs.getString("typeName")); list.add(book); } } } catch (SQLException e) { e.printStackTrace(); } return list; }

LIMIT后面跟两个参数:第一个是偏移量offset,即从第几条记录开始取;第二个是pageSize,即取几条。偏移量计算公式是(pageNum - 1) * pageSize,比如每页10条,第一页偏移0,第二页偏移10,第三页偏移20。这个公式几乎每次都会被问到,写死在注释里。

光有当前页数据不够,分页组件还需要知道总条数才能算出总页数。所以需要配合一个COUNT查询:

// 获取符合搜索条件的总记录数 public int getSearchCount(String keyword) { String sql = "SELECT COUNT(*) FROM t_book WHERE bookName LIKE ?"; try (Connection conn = DBHelper.getConnection(); PreparedStatement ps = conn.prepareStatement(sql)) { ps.setString(1, "%" + keyword + "%"); try (ResultSet rs = ps.executeQuery()) { if (rs.next()) { return rs.getInt(1); } } } catch (SQLException e) { e.printStackTrace(); } return 0; }

拿到总记录数后,总页数=(总条数+pageSize-1)/pageSize,这个向上取整的算法也要能解释。还有两个边界情况要处理好:关键词为空时LIKE '%'会匹配全部数据,这不算错,但最好在SQL里做空值判断;页码小于1时强制置为1,超过最大页数时回到最后一页,否则用户乱点页码程序就崩了。

5. 高频率踩坑排查:驱动、连接、乱码与界面显示的六个问题

5.1 问题:运行报ClassNotFoundException: com.mysql.jdbc.Driver

现象:程序一启动,控制台第一行异常就是找不到驱动类。原因:MySQL驱动jar包没有导入项目,或者导入的版本驱动类名不对。解决:下载mysql-connector-java并放到IDE的构建路径里;如果用的是MySQL 8.0,把驱动类名从com.mysql.jdbc.Driver改成com.mysql.cj.jdbc.Driver。

5.2 问题:报错Communications link failure或者Connection refused

现象:程序启动后,只要一操作数据就弹出连接失败,错误信息里能看到localhost和3306。原因:MySQL服务没启动,或者3306端口被占用,或者密码与代码里DBHelper配置不一致。解决:先在命令行执行netstat -ano | findstr 3306确认端口监听状态;再用命令行工具mysql -u root -p手动连接一次,能连上就说明服务正常,问题在代码配置,重点核对用户名和密码;连不上就去Windows服务里启动MySQL服务。

5.3 问题:数据库里的中文全部变成问号

现象:界面上显示的中文正常,但打开Navicat看表,中文全是????或者乱码。原因:建库时字符集不是utf8,或者连接URL里没加characterEncoding参数。解决:如果还没导入数据,回到3.2节把建库语句改成DEFAULT CHARSET utf8 COLLATE utf8_general_ci重新建库;如果已有数据,用ALTER DATABASE book_db CHARACTER SET utf8调整,再确认每个表也是utf8。同时检查DBHelper里URL是否带上了useUnicode=true&characterEncoding=utf8,这三个条件缺一个都会乱码。

5.4 问题:报错Unknown database或Table 'book_db.t_book' doesn't exist

现象:连接成功但执行SQL时报表或库不存在。原因:数据库没导入成功,或者导错库了,或者连接URL里的库名和实际建的库名不一致。解决:反复确认URL里写的库名和Navicat左侧的库名一字不差;然后执行SHOW TABLES;看看表在不在。很多这种错误其实是3.2节导SQL时选错了数据库,把脚本导到了系统库里。

5.5 问题:不通过登录直接运行MainFrm,窗口空白或报空指针

现象:MainFrm能弹出来,但面板是空的,按钮点击没反应,控制台一堆NullPointerException。原因:主界面依赖登录用户的上下文信息,直接跨过LogOnFrm后,很多变量还没初始化。解决:一律从LogOnFrm启动。如果非要从MainFrm调试,就在MainFrm构造方法里临时写死一个默认用户对象,但交付前要删掉。

5.6 问题:界面按钮错位、窗口显示不全

现象:窗口超出屏幕范围,或者按钮挤压在一起。原因:不同的屏幕分辨率下,Swing的绝对布局不会自适应,这是所有Swing课设的通病。解决:先调整窗口尺寸setSize的初始值,给主窗口设一个合理大小并setLocationRelativeTo(null)居中;如果按钮错位严重,考虑用GridBagLayout或BorderLayout替换绝对布局。答辩机器分辨率一般不会太极端,设成1024x768最稳。

6. 课设答辩准备:演示脚本、边界输入验证与两个加分扩展

很多同学代码跑通了就觉得万事大吉,结果答辩现场演示时手忙脚乱:先打开系统,再打开数据库,然后开始一顿乱点,老师还没看清功能就已经点到下一个页面了。我建议按这个顺序走一遍演示脚本,熟练后控制在一分半钟以内。

第一步,启动LogOnFrm,故意输入一次错误密码,展示错误提示,然后输入正确密码登录。这一步同时验证了登录功能和容错能力。第二步,进入MainFrm,先打开BookTypeManageInterFrm,新增一个类型,比如"计算机"或"文学",然后回到图书添加界面,用刚建的类型添加一本测试书。第三步,切到BookManageInterfrm或分页搜索页面,用书名关键字搜索刚才添加的书,展示分页效果,多翻两页看看页码变化。第四步,选中一条记录执行编辑或删除操作,展示数据同步变化。最后正常退出系统。

演示的同时主动说边界输入验证:空用户名登录会怎样、密码错误会怎样、搜索一个不存在的书会怎样、价格填负数会不会被拒。这些细节老师不一定会试,但你先说出来,印象分会明显不一样。

两个加分扩展我建议做任何一个都好讲:第一,加一个借阅记录表,新建t_borrow表记录图书借出和归还时间,在图书详情里显示"在馆/已借出"状态。这是从单表操作跨到多表事务的第一步,技术上只多了一个Dao和一个面板,但业务完整性上了一个台阶,能顺理成章讲外键和JOIN查询。第二,在图书列表上加一个"导出Excel"按钮,用POI把当前展示的数据写成一个.xls文件,代码量不大,但视觉效果很直观,老师会觉得你不只是会CRUD,还考虑到了实际使用场景。

演示前有一个习惯我从那次课设之后就一直在坚持:拿到任何一套源码,先花十分钟把Dao层的SQL逐条读一遍,确认每张表的字段和代码里的getString参数能对上,再动手运行。数据库字段和Java代码不一致是这类项目最隐蔽的翻车点,提前排掉它,后续不会踩进黑匣子。希望帮到你。

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/24 20:21:47

MySQL备份表的四种方式,从命令细节到选型建议一次讲清

做 MySQL 开发和运维这些年&#xff0c;备份表应该是我碰得最多的操作之一。前两天还有朋友问我&#xff0c;线上有一张大表要做单独备份&#xff0c;既要能随时回滚&#xff0c;又不想影响业务&#xff0c;到底该用哪种方式。这个问题听起来基础&#xff0c;但真往下想&#x…

作者头像 李华
网站建设 2026/9/24 20:18:49

Mac 安装 Homebrew 全指南:包管理器原理、镜像加速与常见报错排查

如果你在 Mac 上写过两年代码&#xff0c;或者只是频繁折腾软件&#xff0c;应该绕不开 brew 这个名字。它是 macOS 上最主流的软件包管理工具&#xff0c;官方名字叫 Homebrew&#xff0c;平时大家直接叫 brew。简单说&#xff0c;brew 就像一个“应用商店”&#xff0c;不过它…

作者头像 李华
网站建设 2026/9/24 20:14:25

麒麟V10安装openGauss全记录:兼容性排查与源码编译实战

下午四点多&#xff0c;我接手一台刚装好银河麒麟 V10 的服务器&#xff0c;任务很明确&#xff1a;把 openGauss 跑起来。当时我心里想的是&#xff0c;数据库安装这种事&#xff0c;最多半小时搞定。结果从下午一直折腾到晚上&#xff0c;中间踩的坑一个接一个&#xff0c;最…

作者头像 李华
网站建设 2026/9/24 20:13:54

2026年多步骤办公自动化工具实战选型指南

1. 这不是“AI办公助手”排行榜&#xff0c;而是2026年真实可用的多步骤任务自动化工具实战图谱你搜“2026年AI办公工具排名”&#xff0c;页面跳出一堆带“权威发布”“十大榜单”字样的软文&#xff0c;点开全是厂商通稿、参数罗列、截图堆砌——用了一周发现&#xff1a;它根…

作者头像 李华
网站建设 2026/9/24 20:13:25

CNN遥感影像地物分类实战:Landsat数据处理与Python源码详解

简介&#xff1a;一套基于PyTorch的CNN深度学习遥感影像地物分类项目源码&#xff0c;面向人工智能、遥感、自动化、电子信息等专业的高校师生与从业者&#xff0c;适用于毕业设计、课程设计或项目初期演示。代码经严格测试可正常运行&#xff0c;包含数据切块、模型训练、新影…

作者头像 李华