ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

JSP+JDBC+MySQL+Servlet图书管理项目实战:从源码到部署全解析

JSP+JDBC+MySQL+Servlet图书管理项目实战:从源码到部署全解析 简介面向Java Web初学者的完整图书管理项目源码基于JSP、JDBC、MySQL与Servlet技术栈实现了图书信息的新增、修改、删除和查询功能适合课程设计或毕业设计参考。压缩包共包含九十五个文件包括十七个Java类与Servlet处理逻辑、十三个HTML页面、十一个CSS样式表、五个XML配置项、一个SQL数据库脚本以及数十张页面截图整体大小约一点七兆目录结构清晰便于按模块对照学习。目前已有两百七十五人学习作为入门级Java Web项目具有不错的参考价值。通过分析源码可以深入理解JSP负责视图展示、Servlet承担请求控制、JDBC连接MySQL执行数据操作的分层思路掌握从数据库设计到页面渲染的完整流程同时借助数据库脚本与配置文件快速搭建运行环境结合截图素材验证界面效果对巩固Java Web开发技能和实践MVC模式都很有帮助。1. JSPJDBCMySQLServlet 图书管理项目先搞清楚这套源码到底能给你什么如果你是计算机相关专业的学生大概率在课程设计或毕业设计里见过这个标题。一个用 JSP 做页面、Servlet 做控制器、JDBC 操作 MySQL 的图书管理项目几乎是 JavaWeb 方向最经典的起步组合也是一代代学生“从 Hello World 走向完整项目”的第一道坎。这套源码能让你看到前端页面和后端逻辑是怎么通过 HTTP 请求串联起来的也能让你理解表结构设计、连接池配置、增删改查这些基本功在实际项目里怎么落。但很多人拿到源码后第一个困惑是这玩意儿到底怎么跑起来Tomcat 版本、JDK 版本、MySQL 版本、驱动 jar 包任何一个不匹配都会让项目在启动阶段就翻车。这个项目本身的技术栈虽然老但它把 JavaWeb 最核心的“请求—处理—响应”链路完整走了一遍非常适合用来补课。如果你正被“项目跑不起来”卡住或者想拿它改一个能过答辩的课设本章先帮你把整体框架拆清楚。2. 源码目录与服务端技术栈为什么 JSP 是视图、Servlet 是控制器、JDBC 是数据通道2.1 解压后先看目录命令与结构判断拿到 zip 包第一件事不是急着导入 IDE而是先把压缩包解压看清目录结构再决定用 Eclipse 还是 IDEA 打开以及是否要转成 Maven 工程。老式 JavaWeb 项目和 Maven 项目的目录差异非常大判断错了后面全是坑。unzip jspjdbcmysqlservlet图书管理项目源码.zip -d book-manager cd book-manager find . -type f | head -50解压命令执行完后重点看有没有pom.xml。有它说明是 Maven 工程依赖由中央仓库统一管理没有说明是纯 lib 目录放 jar 包的传统 Web 工程。早期课程设计绝大多数是后者lib文件夹里直接躺着 mysql-connector-java 的 jar 包src目录下按com.xxx.dao、com.xxx.servlet、com.xxx.entity分包。看目录只是第一步真正的技术栈判断还得看web.xml。WEB-INF/web.xml里的配置能告诉你几件关键事Servlet 版本决定了 Tomcat 版本下限项目欢迎页指向哪个 JSP以及有没有配置统一编码过滤器。常见配置是欢迎页指向login.jsp或index.jspServlet 版本 3.0 或 3.1对应 Tomcat 7/8。如果你电脑装的是 Tomcat 9 或 10Servlet 3.1 的工程理论上能跑但验证头请求头校验和包名变化会引来不必要的麻烦建议优先换 Tomcat 8.5。这个项目里JSP 负责直接渲染 HTML 并嵌入 Java 代码片段即服务端页面Servlet 负责接收浏览器请求、调用 DAO 层、把结果转发回 JSPJDBC 是 Java 连接 MySQL 的唯一官方通道。它的调用链是浏览器发起 HTTP 请求 → Tomcat 根据web.xml里的映射规则找到对应的 Servlet → Servlet 调用 DAO → DAO 通过 JDBC 执行 SQL → 结果返回 Servlet → Servlet 转发或用重定向交给 JSP 渲染成页面。理解不了这条链路后面你一调就报 404 或 500。2.2 前端 JSP 页面到底在做什么动态数据渲染与表单提交的常见写法JSP 在这个项目里的作用非常大它同时干了展示和接收参数两件事。很多人在读代码时最不舒服的地方就是 JSP 里频繁插入% %与% %但恰恰是这个不舒服能让你看清服务端渲染的完整过程。% ListBook bookList (ListBook) request.getAttribute(bookList); for (Book book : bookList) { % tr td% book.getName() %/td td% book.getPrice() %/td tda hrefBookServlet?actioneditid% book.getId() %编辑/a/td /tr % } %这段代码的核心价值在于Servlet 把数据塞进request对象后JSP 直接强转取出并渲染。请求转发模式下request.getAttribute能取到值前提是 Servlet 里用的是request.getRequestDispatcher(bookList.jsp).forward(request, response)而不是sendRedirect。重定向会让浏览器重新发一次请求request对象已经不是同一个了JSP 里取出来就是 null。这是个新手必踩的坑也是老手一眼能看出代码水平的细节。表单提交则是 JSP 页面向 Servlet 传参的主要方式。form actionBookServlet methodpost里的 action 必须与web.xml中的 servlet-mapping 里的 url-pattern 匹配。常见的错误是action写成/BookServlet带斜杠而 url-pattern 是/BookServlet不带项目上下文实际部署后路径就变复杂了。基路径的问题通常用%request.getContextPath()%拼接来规避例如${pageContext.request.contextPath}/BookServlet。老式项目很少用 EL 表达式但你自己写的时候建议用能少一堆字符串拼接的麻烦。2.3 JDBC 驱动选择与 MySQL 版本匹配JDBC 是整个项目里最低层、也最容易出“黑匣子”问题的环节。驱动 jar 包版本不对或者连接 URL 格式写错报错信息往往含糊其辞你得从上千行堆栈里定位真正原因。Class.forName(com.mysql.jdbc.Driver); String url jdbc:mysql://localhost:3306/bookdb?useSSLfalsecharacterEncodingutf8; String username root; String password 123456; Connection conn DriverManager.getConnection(url, username, password);这段代码是 MySQL 5.x 配老版本驱动的标准写法。Class.forName是反射加载驱动类注册到 DriverManager。注意com.mysql.jdbc.Driver是 MySQL 5.x 驱动包里的类名如果你用的是 MySQL 8 以上版本和配套驱动类名必须改成com.mysql.cj.jdbc.Driver同时 URL 里需要补serverTimezoneAsia/Shanghai否则会报时区错误。很多人在“MySQL 8 驱动连接 MySQL 5.7 数据库”或反过来混用时在这里翻了车。数据库账号密码要检查两个位置一个是db.properties或jdbc.properties配置文件一个是 DAO 工具类里面直接写死的地方。老式课设常犯的毛病是把密码写在 Java 类里硬编码你拿到源码后第一件事是全局搜索pwd或password字符串把所有数据库连接配置统一改掉。另外 URL 中useSSLfalse建议保留本地开发环境不开 SSL 能减少握手时间如果出现SSL connection error就检查这一项是不是被改成了 true。2.4 数据库初始化SQL 脚本导入顺序与数据一致性图书管理项目一般自带一个book.sql或init.sql文件里面是建库、建表、插测试数据的语句。导入时用命令行最稳妥而不是在 Navicat 里双击执行。命令行能让你看到每一条语句的执行结果出错马上定位。mysql -uroot -p init.sql看到Query OK连续出现才说明导入成功。导入完成后用use bookdb; show tables;确认表都在。表结构至少要包含三张图书表bookid、name、author、price、publisher、stock 或类似字段、用户表userid、username、password、借阅记录表如果功能多的话。有些项目只有一张图书表加一张用户表纯做增删改查也能过。注意 SQL 文件里的编码格式。如果文件是 UTF-8 而 MySQL 客户端默认是 latin1导入后中文会变成乱码。导入前执行set names utf8;或者在命令行加--default-character-setutf8参数。这种问题的特征是代码没问题但页面显示中文乱码第一反应应该去查数据库里存进去的数据本身是不是乱的。3. 跑通本地环境Tomcat 版本、MySQL 连接参数与项目导入三分法3.1 为什么 Tomcat 8.5 是这个项目最稳的运行底座技术老的项目有一个共性对运行环境挑剔。JSP 和 Servlet 的版本是工程创建时定死的你用太高版本的 Tomcat 反而容易出现兼容问题。Tomcat 8.5 支持 Servlet 3.1、JSP 2.3和绝大多数课设项目的web.xml头部声明匹配Tomcat 9 对应 Servlet 4.0Tomcat 10 开始把javax.servlet包改名为jakarta.servlet老代码直接无法编译。所以最稳的 Tomcat 版本是 8.5.xx如果下载不到Tomcat 9 也可以尝试但小于 9 的版本就别用了。Tomcat 的配置有一个关键点端口。默认 8080 可能被占用特别是你电脑里已经装了其他服务。修改conf/server.xml里的Connector port8080 protocolHTTP/1.1 connectionTimeout20000 redirectPort8443 /把端口号改掉。这里还经常伴随一个问题Tomcat 启动一闪而过看不到日志。这时候要去logs/catalina.out或logs/localhost.log里查 JVM 内存和端口异常。3.2 导入 Eclipse 与 IDEA 的两种姿势和踩坑点Eclipse 和 IDEA 对老式 Web 工程的处理方式略有不同。我不能替你决定用哪个 IDE但两种方式的要点都可以讲清楚。Eclipse 用户选File Import General Existing Projects into Workspace但前提是工程里有.project和.classpath文件否则导入后不识别为 Java 工程。如果导入后代码没报错但无法运行多半是 Project Facets 里的 Dynamic Web Module 版本没勾对。IDEA 导入同样有讲究。选择File New Project from Existing Sources把根目录指到解压出的文件夹。IDEA 会识别出这是 Web 工程要求你配置本地 Tomcat。有一步容易漏File Project Structure Libraries里手动添加WEB-INF/lib下的驱动 jar 包否则编译时找不到com.mysql.jdbc.Driver。老式工程没有 Maven 帮你下载依赖所有 jar 都是手工管理动手添加是必须的。导入后第一件事不是点运行按钮而是先Build Rebuild Project确认编译通过。如果一堆Cannot resolve symbol HttpServlet报错说明缺少 Servlet API 的 jar 包。Tomcat 安装目录下的lib/servlet-api.jar可以手动加进工程或者用 IDE 的 Tomcat 集成功能自动补上。有些源码包里没有 lib 目录那是别人删了 jar 包再压缩上传的你得自己补齐驱动、servlet-api、jstl 三个核心包否则连编译都过不去。3.3 MySQL 连接配置文件重新对齐把 URL、账号、密码放到一个地方把数据库配置集中管理是这套源码必须做的一次“体检”。老式项目常见两种做法一种是写死在 DBUtil 的 Java 代码里另一种是读取db.properties。后者显然更好改但拿到手的源码未必采用需要你自己重构。新建一个db.properties文件放在src根目录内容如下jdbc.drivercom.mysql.jdbc.Driver jdbc.urljdbc:mysql://localhost:3306/bookdb?useSSLfalsecharacterEncodingutf8 jdbc.usernameroot jdbc.password123456配套在工具类里加载static { InputStream in DBUtil.class.getClassLoader().getResourceAsStream(db.properties); Properties props new Properties(); props.load(in); Class.forName(props.getProperty(jdbc.driver)); url props.getProperty(jdbc.url); username props.getProperty(jdbc.username); password props.getProperty(jdbc.password); }把这个配置外置以后换环境就不用改 Java 代码再重新编译了。但是文件路径必须确认是src根目录且类加载器能找到。getResourceAsStream(db.properties)不带斜杠是当前类所在包路径的类路径根如果你把文件放在别的子包下这句代码直接返回 null后面props.load就抛空指针异常。带 MySQL 8 驱动时记得把配置文件里的驱动类名改成com.mysql.cj.jdbc.DriverURL 加serverTimezoneAsia/Shanghai版本对齐后连接成功率能提高一大截。这个配置环节因为太基础经常被忽视但恰恰是项目跑不起来的首要原因。3.4 启动 Tomcat 后的自检清单从 404 到 500 的问题排查部署完成、Tomcat 跑起来以后先用浏览器访问http://localhost:8080/项目名/。这一步可能出现三种结果页面白屏、404、500。白屏先看 Tomcat 控制台有没有异常通常是有类没找到或数据库连接失败404 是 URL 路径或上下文路径不对确认项目名是否带/500 多数是 Servlet 代码或 JSP 编译出错。一个有效的自检方法把浏览器访问的 URL 和web.xml里的 servlet-mapping 对照看。比如登录页能打开但点登录报 404问题几乎一定在actionUserServlet写错或映射不一致。比如点登录直接 500看 Tomcat 日志里的Caused by行最常见的两个原因SQL 语句语法问题或字段不存在。日志里的堆栈信息会直接告诉你错误发生在哪一行代码对照代码改就行。到这里项目已经在本地立住了。后面真正花时间的往往不是业务功能而是各种环境细节——字符集、外键约束、资源释放。下一个章节专门把这几个硬骨头拆开。4. 图书增删改查的业务闭环从 DAO 层到 Servlet 再到 JSP 的完整数据流4.1 增删改查操作对应的 SQL 与关键参数图书管理核心是增删改查四类操作它们在你的 DAO 里各有对应方法。这里有两个容易出问题的地方一个是 SQL 注入另一个是查询结果集映射成对象时字段名大小写匹配。// 添加图书 String sql INSERT INTO book(name, author, price, publisher) VALUES(?, ?, ?, ?); PreparedStatement ps conn.prepareStatement(sql); ps.setString(1, book.getName()); ps.setString(2, book.getAuthor()); ps.setBigDecimal(3, book.getPrice()); ps.setString(4, book.getPublisher()); int rows ps.executeUpdate();// 删除图书 String sql DELETE FROM book WHERE id ?; PreparedStatement ps conn.prepareStatement(sql); ps.setInt(1, id); int rows ps.executeUpdate();用PreparedStatement加?占位符而不是直接拼接字符串是老项目里最重要的优化点。用Statement拼接你也能达到目的但万一书名里有单引号SQL 就会因为语法错误直接炸掉而且存在注入风险。setBigDecimal是专门给价格字段用的货比三家地避开float/double带来的精度问题——数据库里price DECIMAL(10,2)配BigDecimal才是正路。还有一个几乎所有新手都会踩的坑增删改操作后要不要“刷新列表页”。在 Servlet 里添加完图书后一般用重定向回到列表页才能看到新数据。如果用了转发浏览器地址栏不变用户按一下 F5 就会重复提交上一次的请求数据库里会出现两条一模一样的记录。这是一个典型的“刷新翻车”场景用response.sendRedirect(BookServlet?actionlist)就能避开。4.2 Servlet 里 param 与 attribute 的区别请求参数和数据传递的边界Servlet 代码里有两类对象从request.getParameter()拿到的用户输入和request.setAttribute()塞给 JSP 的数据。前者是浏览器通过 GET/POST 提交的字符串后者是 Servlet 在内部处理完业务后传给视图渲染的对象。二者混用的后果是你从 JSP 里取不到值或者误把一个参数当成对象去强转。String action request.getParameter(action); if (add.equals(action)) { String name request.getParameter(name); String author request.getParameter(author); String priceStr request.getParameter(price); BigDecimal price new BigDecimal(priceStr); Book book new Book(); book.setName(name); book.setAuthor(author); book.setPrice(price); BookDao dao new BookDao(); dao.addBook(book); response.sendRedirect(BookServlet?actionlist); }这里有一个很实际的问题priceStr是空字符串或包含非数字字符时new BigDecimal(priceStr)会抛NumberFormatException。正规写法是先判断非空再用try-catch包住。但很多课设源码不做校验所以你拿到项目后最好自己补上——万一答辩老师故意输一个非法值你就能现场救回来。action这个参数的取值决定了 Servlet 走哪个业务分支所以 URL 里的?actionadd是必须匹配的写错就落入 else 分支或者什么都没发生。4.3 JSP 列表页与编辑页之间怎么串起来因为 id 的参数传递编辑功能的链路比添加稍微复杂一点因为你要把数据库里已有的数据回显到表单上。在列表页每个“编辑”链接上带上主键 idServlet 根据 id 查回整条记录转发到一个edit.jsp在表单的 value 里填入旧数据。String idStr request.getParameter(id); int id Integer.parseInt(idStr); Book book bookDao.findById(id); request.setAttribute(book, book); request.getRequestDispatcher(edit.jsp).forward(request, response);edit.jsp的表单提交路径要区分“更新”和“插入”两个动作。常见设计是BookServlet?actionupdate通过一个隐藏字段input typehidden nameid value% book.getId() % /把主键带过去。如果没有这个 hidden 字段更新操作就不知道要改哪条记录新手经常在这里漏掉导致只能新增、更新失败。这是整个项目里最容易被忽略的隐藏参数之一。4.4 事务与连接释放“用完就关”为什么比功能本身更重要增删改查本身的代码不难难的是资源管理。JDBC 连接是昂贵资源用完不还回连接池系统迟早耗尽连接池报Connection is not available。这段代码是所有 DAO 方法的基本盘try (Connection conn DBUtil.getConnection(); PreparedStatement ps conn.prepareStatement(sql)) { // 业务代码 } catch (SQLException e) { e.printStackTrace(); }Java 7 的 try-with-resources 语法可以自动关闭PreparedStatement和Connection不用手工写finally块。源码若是老写法里面一堆finally { conn.close(); }你再检查一遍是否所有分支都会关闭连接。最常见的问题是在一个方法里开了连接某个return分支忘了关闭一次两次看不出问题跑一天后数据库连接数爆满整个项目卡死。多个表同时更新时需要开启事务比如借书操作涉及“插入借阅记录”和“图书库存减一”两个动作任何一个失败都应当回滚不能出现记录有了但库存没减的情况。Connection conn null; try { conn DBUtil.getConnection(); conn.setAutoCommit(false); // 插入借阅记录 // 扣减库存 conn.commit(); } catch (SQLException e) { if (conn ! null) { conn.rollback(); } } finally { if (conn ! null) { conn.close(); } }setAutoCommit(false)把这个连接从“每句 SQL 自动提交”切换到“手动提交”。注意事务的作用范围是以Connection为边界的你在一个方法里开连接才能管住同一个连接上的多条 SQL。这个逻辑单独写一个borrowBook方法然后在 Servlet 里调用别把事务代码散写在 Servlet 里否则线程安全会被你亲手破坏。5. 图书管理项目避坑指南乱码、SSL、驱动类名与运维细节——现象、原因与排查路径5.1 tomcat 启动后访问页面 404virtual path 与项目上下文路径的区别现象Tomcat 正常启动浏览器访问localhost:8080能看到 Tomcat 首页但访问localhost:8080/book/login.jsp直接 404。原因项目部署的上下文路径和你输入的 URL 不匹配。web.xml里 Servlet 映射用的是相对应用根路径的/BookServlet但浏览器访问一个 JSP 时必须带上上下文路径即/项目名/BookServlet或/项目名/login.jsp。如果你把项目打成 war 包部署时名字是book.war那访问根就是/book如果是直接把解压文件夹丢进webapps访问根取决于文件夹名。很多人把压缩包解压后文件夹名是一长串乱码或带版本号访问时用了文件夹名里的回车或空格就报 404。解决访问路径统一走http://localhost:8080/你的文件夹名/login.jsp。更省心的办法是在页面里用${pageContext.request.contextPath}动态拼接这样不管你项目文件夹叫什么都无需改代码。如果 JSP 页面里是硬编码form action/BookServlet那去掉前导斜杠或改用上下文路径。5.2 MySQL 8 驱动连接老库报 SSL 错误或时区错误现象项目启动或首次查询时报The server time zone value й׼ʱ is unrecognized紧接着是一长串英文堆栈后面还跟着 SSL 握手问题。原因使用的是 MySQL 8 驱动类名com.mysql.cj.jdbc.Driver但 URL 里没带serverTimezone和useSSLfalse。MySQL 8 驱动默认开启 SSL 连接并且强制要求服务端时区明确本地开发的单机 MySQL 通常没配置过 SSL 证书也没有明确时区驱动就像一台没有地图的汽车到处乱撞。解决把 URL 改成jdbc:mysql://localhost:3306/bookdb?useSSLfalseserverTimezoneAsia/ShanghaicharacterEncodingutf8。如果你用的是 MySQL 5 驱动类名com.mysql.jdbc.Driver连接 MySQL 8 则反过来是驱动不支持新协议建议换驱动包。两套组合不要混MySQL 5.7 mysql-connector-java 5.x或者 MySQL 8 mysql-connector-java 8.x这是最不容易出错的两组搭配。5.3 页面中文乱码字符集“三处对齐”缺一不可现象数据库中查到的中文是正常的但浏览器显示??或者乱码一堆。原因请求编码、响应编码、数据库连接编码、页面文件编码这四处只要有一处没设置成 UTF-8中文就会在某一环被转成字节流后再被错误解码。JSP 文件的charset只是页面编码声明不影响数据库交互更多时候是 jdbc URL 少了characterEncodingutf8或者 JSP 里没有request.setCharacterEncoding(UTF-8)。解决三步走。第一步 JSP 页面顶部写% page languagejava contentTypetext/html; charsetUTF-8 pageEncodingUTF-8%第二步在 Web.xml 里配置全局编码过滤器CharacterEncodingFilter如果你用的 Tomcat 没有自动配置的话确保 POST 请求参数按 UTF-8 解码第三步检查 jdbc URL保证characterEncodingutf8。三处都对齐了还是乱码去 MySQL 命令行里查show variables like character%确认库和表都是 utf8mb4。5.4 删除图书失败外键约束报错现象执行删除图书操作时程序抛Cannot delete or update a parent row: a foreign key constraint fails或者在命令行删除被拒绝。原因图书表被借阅记录表通过外键引用了比如borrow_record表里有book_id指向book.id。数据库为了保证引用完整性不允许直接删除仍有子记录依赖的父表行。部分老源码在设计borrow_record表时即使没明确声明外键约束也通过业务逻辑保证了一致性删除失败是根据业务规则来的。解决先处理关联数据即先删除借阅记录再删除图书。在 DAO 层里把删除操作放进事务DELETE FROM borrow_record WHERE book_id ?然后DELETE FROM book WHERE id ?。如果你只是为了演示功能而忽略外键可以在建表时写FOREIGN KEY (book_id) REFERENCES book(id) ON DELETE CASCADE但这对课设答辩不太友好回答“业务规则强制要求先还书再删除”更有说服力。5.5 表单提交后页面重复插入数据重定向问题现象添加图书后列表页多了一条记录但按 F5 刷新一次又多一条变成了“手动重复提交”。原因Servlet 用forward转发到 JSP 页面浏览器地址栏没变化刷新就是重新提交上一次 POST 请求。POST 的语义是不幂等的二次提交必然二次插入。解决使用 302 重定向。添加完成之后response.sendRedirect(BookServlet?actionlist)代替forward。重定向本质是浏览器重新发了一个 GET 请求地址栏变成列表页 URL刷新只会重复 GET不会触发重复插入。这个模式叫 Post/Redirect/Get是老项目里稍显前端一点但后端非常重要的思路。6. 从课设源码到能答辩的完整作品三个有用扩展和性能验证思路6.1 加一个“借阅排行榜”聚合查询与时间字段处理如果嫌这个项目功能太少第一个值得加的功能是借阅排行榜。它涉及 SQL 聚合操作和多表连接复杂度适中基本能撑住答辩里的“项目亮点”环节。在 DAO 层写一个专门的方法SELECT b.name, COUNT(br.id) AS borrow_count FROM book b LEFT JOIN borrow_record br ON b.id br.book_id GROUP BY b.id, b.name ORDER BY borrow_count DESC LIMIT 10这里有两个参数需要说明一下GROUP BY后面必须列出所有非聚合列否则 MySQL 启用了ONLY_FULL_GROUP_BY会直接报错LEFT JOIN的意义在于把“从没被借过的书”也显示出来count 为 0 的记录也在里面。这种查询结果映射到 Java 对象时要走ListMapString, Object或新建一个持有name和borrowCount两个字段的 VO。别硬塞进Book实体类里那样字段语义就乱了。6.2 把重复的模糊查询逻辑抽出来DAO 层 getConnection 的复用项目里每个 DAO 方法都有一遍相同的getConnection、prepareStatement、close三段式读着烦人而且容易漏。你可以在BaseDao里封装一个通用的增删改执行器和查询方法参数是 SQL 和可变参数列表。public int executeUpdate(String sql, Object... params) { try (Connection conn DBUtil.getConnection(); PreparedStatement ps conn.prepareStatement(sql)) { for (int i 0; i params.length; i) { ps.setObject(i 1, params[i]); } return ps.executeUpdate(); } catch (SQLException e) { throw new RuntimeException(e); } }Object...是 Java 的可变参数底层是一个 Object 数组。调用时executeUpdate(sql, book.getName(), book.getAuthor())和直接写executeUpdate(sql, new Object[]{...})效果一样。这套抽法能减少大约 30% 的重复代码显著提升答辩时“你的代码风格”这关的印象分。把每张表的 DAO 都继承BaseDao你要修一个 SQL 异常时只改一处而不用三个 DAO 轮着改。6.3 验证读写性能用时间戳方法做前后对比以及为什么批量插入更重要扩展做完了你得能证明它有用。最简单的性能验证方式是在 Servlet 的方法入口和出口各记一个时间戳long start System.currentTimeMillis(); ListBook books bookDao.findByName(keyword); long end System.currentTimeMillis(); System.out.println(查询耗时 (end - start) ms);打印结果不能说明太多但可以给你一个横向对比依据加索引前后各跑一次看耗时有没有下降。图书管理项目数据量小性能差异几乎看不出来这里的意义在于让你熟悉验证链路而不是优化效果本身。如果导师让优化核心方向是给book表的name字段加普通索引在book表数据量大时WHERE name LIKE ...的全文扫描变索引范围扫描效果立竿见影还是玄学就得看数据分布了。6.4 很关键的一步数据库脚本同步替换为 MySQL 8 注释规范升级到 MySQL 8 后老项目的 SQL 文件可能有兼容性细节。比如ENGINEInnoDB DEFAULT CHARSETutf8在 MySQL 8 里依然能用但utf8已经不算推荐改成utf8mb4对中文和多语言支持更完整。DEFAULT NULL或NOT NULL的定义检查完尤其注意用了旧式TYPEInnoDB的脚本——MySQL 8 里已经移除了TYPE关键字必须写成ENGINEInnoDB否则导入直接报错。把这些扩展做完你的项目已经不是“拿源码改改”的了而是能讲清楚设计思路的作品。我自己当年带过的学弟里有人坚持在原项目上加了分页和借阅排行榜答辩时用源码和 SQL 日志讲原理比那些换皮改色的明显稳很多。这里再补一句不管项目运行得多顺利都先备份一份能跑的完整版本再动手改。压缩包里的原始代码是个起点跑起来的环境是真正宝贵的东西很多人在扩展功能时不小心把连接配置弄坏了结果原来的代码也启动不了了。复制一份放到另一个目录给那个能跑的版本留个后悔药。希望这篇拆解能帮你把这个经典项目真正吃透少走那些我当年自己踩过的弯路。本文还有配套的精品资源点击获取
返回列表