
简介这份Java图书管理系统项目包以完整源码与MySQL数据库脚本为核心专为计算机专业学生应对期末大作业或课程设计打造。作为大三阶段经导师指导并通过的高分项目其评审成绩达99分代码经过完整测试可直接运行对初学Java者也比较友好。压缩包共含32个文件包含9个Java源文件与对应编译生成的18个class字节码便于直接运行或对照学习还有1个SQL脚本用于初始化数据库表结构以及.classpath、.project等工程配置文件和一份docx课程设计说明文档覆盖从开发环境搭建到系统演示讲解的全过程。资源整体仅530KB体量轻、结构清晰平均每个文件约17KB方便下载与本地运行。目前已有178人学习适合需要参考真实课设项目模板、练习Java与MySQL整合开发或短期完成期末大作业的学生使用。1. 图书管理系统这个 Java 课程设计包到底值不值得下载来跑很多人下载 java 图书管理系统Java源码 Mysql数据库 这个压缩包都是为了交课程设计或毕业设计但一半人卡在第一步代码解压后能看懂数据库却连不上。这个标题背后是一套很典型的 JavaWeb 三层结构项目JSP 负责页面展示Servlet 做请求路由和业务控制JDBC 直连 MySQL 完成增删改查。它解决的是“从零把一个可交互的管理系统跑起来”这件事适合刚学完 JavaSE 和 SQL 基础、正在走 java 学习路线的新手也适合想拿现成项目套壳改写成自己方案的人。值不值得跑取决于你手头的 JDK、Tomcat 和 MySQL 版本是否匹配以及能不能把 SQL 脚本正确导进去。2. 先把 Mysql 数据库立起来从装库到 SQL 脚本导入的完整路径拿到 zip 后别急着打开代码先把数据库跑通。图书管理系统这类 JavaWeb 项目九成以上的启动失败都不是代码问题而是 MySQL 没准备好库没建、账号密码不对、驱动和数据库版本不匹配。这一章按“拿到 SQL 脚本 → 导入 → 调参数”的顺序走一遍照着做就能把数据层打通。2.1 图书管理系统里的 Mysql 数据库脚本拿到后先看这三件事解压 zip 后在根目录或 sql 文件夹下一般能看到一个 .sql 文件常见命名是 book.sql、library.sql、db_library.sql。不要用记事本双击打开先用 Notepad 或 VS Code 检查右下角编码重点看三件事。第一文件编码。如果显示 UTF-8导入后中文基本正常如果显示 GBK脚本里的中文注释和初始数据导入后大概率乱码。第二有没有建库语句。很多脚本开头只有 CREATE TABLE没有 CREATE DATABASE 和 USE这意味着作者默认你手动建好库再执行。第三表引擎和字符集。出现 ENGINEInnoDB 和 utf8mb4 说明是近几年写的如果全是 MyISAM 和 latin1建议手动改成 utf8mb4否则后面插入中文图书名会直接报错。一个典型的图书管理系统 SQL 脚本开头长这样-- 建库指定 utf8mb4避免中文乱码 CREATE DATABASE IF NOT EXISTS library_db DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; USE library_db; -- 管理员表id 自增username 唯一password 存明文或 MD5 CREATE TABLE admin ( id INT NOT NULL AUTO_INCREMENT, username VARCHAR(50) NOT NULL UNIQUE, password VARCHAR(32) NOT NULL, PRIMARY KEY (id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COLLATEutf8mb4_general_ci; -- 初始管理员账号admin / 123456 INSERT INTO admin (username, password) VALUES (admin, 123456);注意 password 字段长度。如果脚本里 VARCHAR(16)作者默认存明文VARCHAR(32) 一般对应 MD5 加密后的 32 位十六进制字符串。这里还隐含一个坑如果你登录时密码框输入 123456 却登不进去而数据库里存的也是 123456那就说明登录代码对密码做了 MD5 加密你需要在数据库里先把密码改成加密后的值或者临时改成不加密。后面第 6 章会专门讲密码改造。2.2 两种导入 SQL 的方式Navicat 可视化与 mysql 命令行最常见的做法是用 Navicat 导入画面直观适合新手。打开 Navicat新建 MySQL 连接主机填 localhost端口 3306用户名 root填你自己 MySQL 的密码连接成功后右键点击连接名选择“运行 SQL 文件”选中刚才那个 .sql 文件点击开始。跑完刷新一下就能看到 library_db 库和里面的表。这里有一个很多人翻车的细节不要在已经打开的某个数据库里点“查询”然后粘贴脚本。如果脚本里有 CREATE DATABASE 和 USE 语句Navicat 会先切到那个新库再执行建表语句过程没问题但如果脚本里没有 USE你就会把表建到当前选中的库里等源码里的 JDBC 连接指向 library_db 时提示 Unknown database。所以运行 SQL 文件时要右键点击“连接”而不是“数据库”。不想用 Navicat 的可以用 MySQL 自带的命令行客户端免费且不依赖第三方工具。Windows 下打开 cmd先进入 MySQL bin 目录或者把 bin 配进 PATH然后执行mysql -u root -p输入密码进入交互界面后执行SOURCE C:/path/to/library.sql;SOURCE 后面跟绝对路径斜杠用 /不要用反斜杠。如果你的脚本里没有 CREATE DATABASE需要先手动建库再指定库执行mysql -u root -p library_db library.sql这两条命令的区别要看清SOURCE 方式会执行脚本里的所有语句包括建库和切库管道方式则默认你已经建好 library_db如果脚本开头的 USE 指向别的库会产生冲突。Linux 上通过 apt 安装 mysql-server 后mysql 命令一般在 /usr/bin/mysql基本不用配环境变量直接执行上面的命令即可。2.3 建库建表之后必改的 3 个数据库参数脚本导入成功只是第一步还要保证 Java 源码能连上它。图书管理系统这类课程设计项目源码里的数据库配置往往是作者本机的值通常集中在 src 下的 db.properties、jdbc.properties 或 dao 包里的 DBUtil.java。有三个参数最常需要改。第一个是账号密码。源码里写死的 root/123456 和本地实际账号不一致时建议去改源码配置文件而不是改本地 MySQL root 密码。因为改 root 密码会影响你机器上的其他项目改配置文件只影响这一个项目。第二是端口。如果本地 MySQL 因为旧版本残留或者端口冲突跑在 3307JDBC URL 里的 3306 也要跟着改否则报 Connection refused。第三是 MySQL 8 的认证插件。8.0 默认 caching_sha2_password而老项目自带的 mysql-connector-java 5.1.x 驱动不认这个插件会报 Public Key Retrieval is not allowed 或 SSL 连接错误。如果你不想换驱动可以在 MySQL 里把用户认证方式改回兼容模式ALTER USER rootlocalhost IDENTIFIED WITH mysql_native_password BY 123456; FLUSH PRIVILEGES;注意这里的 123456 要换成你本地真实的 root 密码。改完之后 Navicat 和旧驱动就能正常连了。不过我的习惯是直接升级驱动到 8.0.x不然每次重装 MySQL 都要重新改一次用户认证太啰嗦。后面第 3 章会给出驱动和 URL 的具体写法。3. 让 Java 源码在本机跑起来JDK、IDE 与 Tomcat 的三件套配置数据库就绪后开始处理 Java 源码。这个阶段最常见的现象是代码能编译但 Tomcat 启动到一半报错或者启动成功页面却全是 404。原因基本集中在三件事项目本身是 Maven 工程还是传统 Web 工程、JDK 与 Tomcat 版本是否匹配、MySQL 驱动和连接配置有没有同步更新。这一章逐个说清楚。3.1 源码包用 Maven 还是普通 Web 工程决定了你导入的方式解压源码后第一个动作是看根目录有没有 pom.xml。这决定了你在 IDEA 里的导入姿势也决定了依赖 jar 从哪来。有 pom.xml 的用 IDEA 的 Open 直接打开项目根目录IDEA 识别为 Maven 项目后会自动下载依赖。打开后先点右侧 Maven 面板的刷新按钮等进度条跑完再启动 Tomcat。如果网络不好依赖下载失败启动时会报 java.lang.ClassNotFoundException: org.springframework.* 或 mysql 相关类找不到这是 Maven 私服超时导致 jar 没下全重新刷新或换个镜像源即可。没有 pom.xml而是出现 WebContent/ 或 web/ 目录、WEB-INF/web.xml 的是传统 Web 工程。导入时选择 Import Project选中目录后 IDEA 会提示是否作为 Maven 项目选不是然后把它识别为普通 JavaWeb 项目。导入后需要右键 web/WEB-INF/lib 下的 jar 包选择 Add as Library把依赖加进 classpath。这类项目常见的 lib 里有 mysql-connector-java 5.1.x 和 jstl-1.2如果缺失页面里的 JSTL 标签会变成一堆看不懂的 HTML 代码。这里有一个很容易误导人的点源码编译通过不代表运行没问题。编译只需要 JDK运行还依赖 Tomcat 提供的 servlet-api.jar。IDEA 里需要把项目选中右键 Open Module Settings在 Artifacts 里把项目打成 war exploded再把这个 Artifact 部署到 Tomcat。很多人跳过这一步直接点运行IDEA 会提示 No artifacts marked as deployable。3.2 JDK 与 Tomcat 版本不匹配是 JavaWeb 项目最常见的翻车点图书管理系统这类课程设计源码大多数编写于 JDK 8 时代代码里用的是 javax.servlet.* 包。JDK 和 Tomcat 的兼容关系如下表JDK 版本推荐 Tomcat 版本典型表现JDK 1.8Tomcat 8.5 / 9.0编译运行最稳教科书通用配置JDK 11Tomcat 9.0大多能跑少数老依赖反射报错JDK 17Tomcat 10.0javax 变 jakarta老代码类找不到直接 404最稳妥的组合是 JDK 1.8 配 Tomcat 8.5这个组合在绝大多数课程设计源码上都能直接跑通。如果机器上装的是 JDK 17又想跑老项目我不建议去重新编译源码最简单的方法是再装一个 OpenJDK 8IDEA 里切换 Project SDK。JDK 装好后先验证命令行环境。Windows 下打开新的 cmd执行java -version javac -version如果 java -version 有输出javac 提示不是内部或外部命令说明 JRE 正常但 JDK 没配好需要在系统环境变量里加 JAVA_HOME 指向 JDK 安装目录并在 PATH 里加上 %JAVA_HOME%\bin。IDEA 里也要对应设置File - Project Structure - SDK 选 1.8Language Level 选 8确保编译输出字节码版本和 JDK 一致。Tomcat 本身不需要配 CATALINA_HOME除非你坚持用命令行 startup.bat 启动。在 IDEA 里是 Run - Edit Configurations - 左上角加号 - Tomcat Server - Local然后指定 Tomcat 目录即可。配置完在 Deployment 页签里把 war exploded 加进去Application context 改成 /library不要用默认的带下划线的工程名否则后面访问路径都对不上。3.3 源码里的数据库连接配置照着这个模板改就能连上源码里数据库连接配置通常写在两种地方单独的 .properties 文件或者一个叫 DBUtil 的 Java 类。前者适合整体替换后者适合改常量。不管是哪种核心就一段配置。如果你的 zip 包自带的是 5.1.x 驱动而本地是 MySQL 8强烈建议直接换成 8.0.33 并改用下面的 URLjdbc.drivercom.mysql.cj.jdbc.Driver jdbc.urljdbc:mysql://localhost:3306/library_db?useUnicodetruecharacterEncodingutf-8serverTimezoneAsia/ShanghaiuseSSLfalseallowPublicKeyRetrievaltrue jdbc.usernameroot jdbc.password123456这里每个参数都有讲究。driver 类名MySQL 5.x 时代是 com.mysql.jdbc.Driver8.x 改成了 com.mysql.cj.jdbc.Driver两者不通用。serverTimezone 必须指定否则连接时报时区错误那串乱码提示国内新手几乎都见过。useSSLfalse 在本地开发足够生产环境才考虑开 SSL。allowPublicKeyRetrievaltrue 是 MySQL 8 配合 caching_sha2_password 时需要的不加就报 Public Key Retrieval is not allowed。如果源码里的 DBUtil 是 Java 类通常会写成一个静态方法核心逻辑类似这样public class DBUtil { private static final String URL jdbc:mysql://localhost:3306/library_db ?useUnicodetruecharacterEncodingutf-8 serverTimezoneAsia/Shanghai useSSLfalseallowPublicKeyRetrievaltrue; private static final String USER root; private static final String PASSWORD 123456; static { try { Class.forName(com.mysql.cj.jdbc.Driver); } catch (ClassNotFoundException e) { e.printStackTrace(); } } public static Connection getConnection() throws SQLException { return DriverManager.getConnection(URL, USER, PASSWORD); } }注意一个忌讳类路径里不要同时出现 5.1.x 和 8.0.x 两个版本的 mysql 驱动 jarClass.forName 会加载其中一个但其他类加载到的连接器版本不确定排错时会出现玄学问题。只留一个 8.0.33 即可。改完配置后启动 Tomcat能打开登录页并成功登录说明 Java 端和 MySQL 端已经打通。4. 从源码里拆出图书管理系统最核心的三个功能块顺便摸摸技术方案跑通以后别急着交作业。你要能跟答辩老师讲清楚登录是怎么拦截的图书查询为什么不会发生 SQL 注入借书为什么不会出现超借。这三个功能块在图书管理系统里是标配也是面试八股文里那几道高频题的落地场景。这一章按功能拆源码同时给出一套能放进自己项目的写法。4.1 登录与权限Session 过滤器与角色判断的常见写法图书管理系统的权限模型一般分管理员和普通读者。管理员可以修改图书和维护用户读者只能查询和借阅。最简单可靠的实现是 Servlet 过滤器统一拦截用户登录成功后把对象放进 Session每次请求先查 Session。public class LoginFilter implements Filter { Override public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { HttpServletRequest request (HttpServletRequest) req; HttpSession session request.getSession(false); Object admin session null ? null : session.getAttribute(admin); if (admin null) { request.getRequestDispatcher(/login.jsp).forward(request, resp); return; } chain.doFilter(req, resp); } }这段逻辑很直接session 为 null 或取不到 admin 属性就转发到登录页否则放行。值得注意是 getSession(false)这里传 false 很关键表示如果没有会话不要新建一个否则每个未登录请求都会创建空 Session白白浪费内存。过滤器要在 web.xml 里注册才能生效filter filter-nameloginFilter/filter-name filter-classcom.library.filter.LoginFilter/filter-class /filter filter-mapping filter-nameloginFilter/filter-name url-pattern/*/url-pattern /filter-mappingurl-pattern 用 /* 会拦截所有请求包括 CSS、JS、图片。很多人的登录页样式全丢了就是过滤器把静态资源也劫持了。解决做法是在 doFilter 里加一段放行逻辑对以 .css、.js、.png 结尾的路径直接 chain.doFilter。答辩时老师常问“为什么登录状态用 Session 不用 Cookie”标准答法就是Cookie 存在客户端且服务端无法主动失效Session 存服务端配合 setMaxInactiveInterval 可以控制超时时间安全性更高。这一句话就能把你的代码从“能跑”提升到“懂原理”。4.2 图书 CRUD从 JSP 页面到 JDBC 预编译语句的完整链路图书管理系统的核心数据操作就是图书表的增删改查。展示层是 JSP控制层是 Servlet数据层是 DAO。以最常用的模糊查询为例三层调用链是这样走的JSP 页面提交 keyword 参数给 bookServletServlet 调 bookDao.findBooks(keyword)DAO 执行 SQL 返回 List 集合Servlet 把 List 塞进 request 转发回 book-list.jspJSP 用 JSTL 循环输出表格。DAO 层的推荐写法是 PreparedStatement而不是拼字符串的 Statementpublic ListBook findBooks(String keyword) throws SQLException { String sql SELECT * FROM book WHERE name LIKE ? AND status 1 ORDER BY id DESC; ListBook list new ArrayList(); try (Connection conn DBUtil.getConnection(); PreparedStatement ps conn.prepareStatement(sql)) { ps.setString(1, % keyword %); try (ResultSet rs ps.executeQuery()) { while (rs.next()) { Book b new Book(); b.setId(rs.getInt(id)); b.setName(rs.getString(name)); b.setAuthor(rs.getString(author)); b.setStatus(rs.getInt(status)); list.add(b); } } } return list; }这里有两个必须讲明白的点。第一LIKE 的参数化写法。% 通配符要拼在参数值里而不是拼进 SQL 字符串写成 LIKE % keyword % 是很多初学翻车的重灾区一旦输入框里包含单引号SQL 就被截断。PreparedStatement 的 setString 会自动转义单引号从根上避免注入。第二try-with-resources 写法。Connection、PreparedStatement、ResultSet 三个资源只要实现 AutoCloseable就能在 try 块结束后自动关闭不用写连串的 finally close减少连接泄漏。对应 JSP 页面的循环输出一般是c:forEach items${bookList} varbook tr td${book.id}/td td${book.name}/td td${book.author}/td td a hrefbookServlet?actioneditid${book.id}编辑/a a hrefbookServlet?actiondeleteid${book.id}删除/a /td /tr /c:forEach这里 action 参数是 Servlet 里的分支判断依据。如果源码里 Servlet 用 switch(action) 做分发新增功能时只要在 JSP 里加一个链接再在 Servlet 里加一个 case整个流程就通了。注意 ${book.name} 能正常输出依赖 JSTL 标准库 jar 已在 WEB-INF/lib 中否则页面上会直接显示 ${book.name} 原文这属于环境问题而不是代码问题。4.3 借阅与归还事务怎么处理才能避免超借和脏数据借书动作在业务上要同时做两件事在借阅表里插一条记录把图书表的 status 字段改成 1 表示已借出。这两步如果分开执行第二步失败时就会出现日志里多了借阅记录但书的状态没变下次还能被别人借走这就是数据不一致。最直接的解法是手动控制事务把多步写操作包在同一个 Connection 里要么全部提交要么全部回滚public boolean borrowBook(int bookId, int userId) throws SQLException { Connection conn DBUtil.getConnection(); boolean ok false; try { conn.setAutoCommit(false); String checkSql SELECT status FROM book WHERE id ? AND status 0 FOR UPDATE; String insertSql INSERT INTO borrow (book_id, user_id, borrow_date) VALUES (?, ?, NOW()); String updateSql UPDATE book SET status 1 WHERE id ?; try (PreparedStatement ps conn.prepareStatement(checkSql)) { ps.setInt(1, bookId); try (ResultSet rs ps.executeQuery()) { if (!rs.next()) { conn.rollback(); return false; } } } try (PreparedStatement ps conn.prepareStatement(insertSql)) { ps.setInt(1, bookId); ps.setInt(2, userId); ps.executeUpdate(); } try (PreparedStatement ps conn.prepareStatement(updateSql)) { ps.setInt(1, bookId); ps.executeUpdate(); } conn.commit(); ok true; } catch (SQLException e) { conn.rollback(); throw e; } finally { conn.setAutoCommit(true); conn.close(); } return ok; }setAutoCommit(false) 是手动事务的开头告诉数据库先别把每条 SQL 当成独立事务提交。checkSql 里的 FOR UPDATE 是行级锁所在它把 book 表的这一行锁住防止两个读者同时执行到这一步都查到 status0然后都插入借阅记录。最后 finally 里要恢复 setAutoCommit(true)否则连接归还给连接池后下一次使用还是手动事务模式其他方法执行完没提交数据就丢了。归还操作正好相反插入归还记录、把 status 改回 0、计算逾期天数同样要包事务。答辩或面试时如果被问“java 怎么保证数据一致性”把这一节的代码逻辑讲清楚比背概念有用得多。事务边界、锁的范围、连接复用三个点分别对应了为什么、锁谁、坑在哪是一条完整的回答链路。5. 运行图书管理系统必踩的 5 个坑现象、原因与解决这一章的坑全部来自真实复现按出现频率从高到低排列。每条按现象、原因、解决三段写你在跑这个包时如果遇到类似的 404、报错或乱码直接对照这里排查。5.1 Tomcat 8080 端口被占用启动瞬间报 failed to initialize现象IDEA 里点启动 Tomcat控制台秒红提示 Port 8080 was already in use或 failed to initialize。原因本机有另一个进程占用了 8080。常见于以前启动过的 Tomcat 没关干净或者某软件的调试服务占了这个端口。这不是源码问题是环境冲突。解决Windows 下打开 cmd执行 netstat -ano | findstr 8080找到最后一列占用进程的 PID然后 taskkill /PID 进程号 /F 强杀。如果不想杀进程可以在 IDEA 的 Tomcat 配置里把 HTTP port 改成 8081同时把下面两个端口也改掉JMX 端口默认 1099AJP 端口默认 8009。只改 HTTP 端口不改 AJP第二次启动还会报错。改完端口后浏览器访问地址要同步改成 localhost:8081。5.2 老驱动连 MySQL 8报 SSL errors 或 Public Key Retrieval is not allowed现象Tomcat 启动后第一次访问数据库相关页面控制台抛出 Communications link failure错误里有时带 SSLHandshakeException有时带 Public Key Retrieval is not allowed。原因zip 里自带的 lib 是 mysql-connector-java 5.1.xMySQL 8.0 的默认认证插件是 caching_sha2_password旧驱动既不认识新插件又默认尝试 SSL 握手两边协议对不上。解决删掉 lib 下的旧驱动换成 mysql-connector-java 8.0.33同时把 JDBC URL 改成上一章模板里的写法。注意 8.0 驱动的类名是 com.mysql.cj.jdbc.Driver和旧版 com.mysql.jdbc.Driver 不一样源码里 Class.forName 的字符串和 db.properties 都要同步改只换 jar 不换类名仍然报错。这个坑最大的迷惑性在于报错信息指向网络让人去查防火墙实际问题在驱动版本。5.3 JSP 页面中文全部变成问号图书名和个人信息一片乱码现象系统能登录管理员列表、图书列表里的中文全部显示成 ????但英文和数字正常。原因字符集在三个地方没有对齐。JSP 页面编码、MySQL 连接 URL 的 characterEncoding、数据库表的 charset这三处只要有一处不是 utf8 或 utf8mb4中文就会乱码。解决逐项检查。JSP 顶部要写 % page contentTypetext/html; charsetUTF-8 pageEncodingUTF-8%。JDBC URL 里要有 useUnicodetruecharacterEncodingutf-8。MySQL 里执行 SHOW CREATE TABLE book看表的 DEFAULT CHARSET如果不是 utf8mb4执行 ALTER TABLE book CONVERT TO CHARACTER SET utf8mb4。如果三项都对了还乱码检查 SQL 脚本本身是不是 GBK 编码导入时转换后中文变样这种情况需要重新用 UTF-8 保存脚本再导入。乱码问题不要猜按页面、连接、表、脚本四个层面逐层排查二十秒能定位。5.4 提示 Unknown database或发现表建到了错误的库下面现象Tomcat 启动成功访问登录页也正常但输入账号密码点登录后页面报错控制台提示 Unknown database library_db。原因SQL 脚本没有完整执行或者执行到了错误的库里。最常见的是 2.2 节说的那种情况在 Navicat 里右键某个已存在的库执行脚本而脚本开头没有 CREATE DATABASE表被建在了那个库里但 JDBC URL 指向的 library_db 根本不存在。解决命令行执行 SHOW DATABASES确认有没有 library_db。没有就先执行 CREATE DATABASE library_db DEFAULT CHARACTER SET utf8mb4再进入这个库执行建表脚本。有库但表不全的用 SHOW TABLES 对比需要的表清单缺哪张补哪张。注意图书管理系统通常不止管理员和图书两张表一般还有读者表、借阅表、分类表少一张表后面写借阅记录就会报字段不存在。5.5 连接被拒绝或 Linux 下提示 error 2002 (HY000)现象Windows 上报 Connection refused: connectLinux 上执行 mysql -u root -p 时提示 ERROR 2002 (HY000): Cant connect to local MySQL server through socket /tmp/mysql.sock(2)。原因Windows 的 Connection refused 通常是 MySQL 服务没有启动或端口被改过。Linux 的这个报错本质是客户端通过 socket 文件找不到服务端进程说明 mysqld 没在运行或者运行时指定的 socket 路径和客户端默认路径不一致。解决Windows 按 WinR 输入 services.msc找到 MySQL80 服务右键启动并设为自动。Linux 执行 systemctl status mysqld 或 systemctl status mysql 看状态没启动就 systemctl start mysqld并确认 /etc/my.cnf 里没有自定义 socket 路径。如果服务已经在运行仍然报 2002多半是 my.cnf 里 socket 路径被改过客户端连接时用 --socket/自定义路径/mysql.sock 显式指定。这个问题跟 Java 源码无关是数据库服务本身没起来不要在 IDEA 和源码上浪费时间。6. 把图书管理系统从“能跑”改成“能答辩”三个低成本升级技巧如果你还有时间别急着交原版做这三个小改动答辩时的技术分能明显不一样。第一个改动是把管理员密码改成 MD5 存储。原版系统很多直接明文存在 admin 表里答辩时容易被问住。写一个简单的 MD5 工具类登录时把用户输入的密码加密后再去数据库比对同时写段 SQL 把已有明文密码批量更新成密文。这个改动只涉及一个工具类和登录方法但能让你在“密码安全”这个问题上有话可讲。第二个改动是给图书列表加分页。现在很多课程设计是查出一整张表全部渲染数据一多页面直接卡。后端加一个 PageBean接收 page 参数SQL 改成 SELECT * FROM book LIMIT ?, ?前端在表格底部加上一页、下一页链接。分页逻辑是面试高频题你亲手写过一次被问到 offset 怎么算时不会虚。第三个改动是把 DBUtil 里的 DriverManager 换成 HikariCP 连接池。数据库连接每次请求都新建再关闭并发一高就超时这个现象你自己压测一下就能复现。引入 com.zaxxer.hikari.HikariCP 依赖后DBUtil 的 getConnection 改成从连接池拿业务代码一行不用动。连接池的四个核心参数 maximumPoolSize、minimumIdle、connectionTimeout、idleTimeout 提前查好含义答辩时能讲清楚为什么设 10 而不是 100。这三个改动合起来不超过一百行却覆盖了安全、性能、并发三个方向正好是课程设计答辩最爱追问的三个角度。我以前接手别人项目时吃过亏本地跑得好好的拿到老师机器上演示MySQL 8 认证插件不同直接连不上当场翻车。从那以后我养成了一个习惯拿到任何 JavaWeb 源码包第一件事不是运行而是先看 JDK 版本、MySQL 版本、驱动版本三件事对不对齐。环境比代码更爱出幺蛾子先确认环境再谈功能。希望这篇能帮你少走这些弯路。本文还有配套的精品资源点击获取