ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Servlet+JSP+MySQL图书管理系统:从部署到借阅归还实现全解析

Servlet+JSP+MySQL图书管理系统:从部署到借阅归还实现全解析 简介面向JavaWeb初学者的图书管理系统项目采用JSP Servlet JavaBean MVC分层模式开发数据库选用MySQL 5覆盖图书信息维护、学生借阅、归还、逾期处理以及用户登录等核心业务适用于课程设计、毕业设计和JavaWeb项目实训。压缩包大小约8.74MB内含完整项目源码、运行文档、配套论文及答辩PPT支持导入MyEclipse或Eclipse搭配JDK1.7、Tomcat8、MySQL5.6/5.7直接运行文档对部署步骤、数据库初始化和功能模块划分做了清晰说明。已有1321人浏览学习代码由作者亲自测试运行页面交互与核心事务逻辑完整可靠。读者借助源码、运行文档和论文可以快速理解MVC各层职责、Servlet请求转发与重定向、JDBC数据库访问以及图书借阅归还的业务流程设计同时也能参考答辩PPT梳理项目亮点在此基础上扩展图书预约、管理员权限控制、借阅统计等进阶功能。1. 拿到的这个压缩包到底能帮你省多少事如果你正在做 Java 课程设计或者毕业设计大概率被“图书管理系统”甩过脸老师给个题目要求 Servlet JSP MySQL还得有借阅归还的功能最好再来一份还算像样的文档。网上搜出来的源码要么缺数据库脚本要么是纯 JSP 早就跑不起来的老古董要么解压之后发现文档是空的——光是把环境调通就够熬一个通宵。这个以 “java图书管理系统 servletjspmysql学生借阅归还项目源码含文档报告.zip” 命名的项目走的就是最主流也最容易复现的那条路Servlet 当控制器、JSP 做页面、JDBC 连 MySQL功能上覆盖图书管理、学生注册登录、借书还书这几条核心链路外加一份课程设计报告和数据库脚本。它对口的场景非常明确Java Web 课程设计、期末大作业、以及那些“只想把项目跑起来交差但不想从零手写”的人——注意是“跑起来交差”不是“靠它去面试”。如果你正处于这个阶段这篇笔记把解压到跑通再到改造成自己的项目全链路拆开讲能少走至少两晚的弯路。2. 先拆解项目的技术选型为什么是 Servlet JSP MySQL而不是别的2.1 Servlet、JSP 和 MySQL 各自的角色在动手部署之前先把这个项目的分工搞清楚不然改起代码来会到处碰壁。这个项目的请求链路是按照 Java Web 早期最经典的三层模型搭的浏览器发起请求打到 Servlet 上Servlet 负责接收参数、调用逻辑、跳转页面JSP 负责把结果渲染成 HTML 返回给浏览器MySQL 只存数据既不管页面也不管业务。为什么是这个组合原因很实在Servlet 是这门课的考纲重点JSP 在页面渲染上写起来比 Servlet 拼 HTML 要舒服太多MySQL 又是零成本安装就能上手的数据库。这三者搭起来结构一目了然——你的老师会一眼看到“懂 Java Web 基础规范”。相比之下Spring Boot MyBatisVue 的方案虽然更贴近工业界但很多课程设计的评分标准里根本没有这一项答辩的时候老师也不好切入提问。所以选这个技术栈不是因为它新而是因为在这个标题对应的问题域里它就是性价比最高的答案。2.2 项目在开发工具里的目录划分不要试图一把梭把所有文件放在同一个包下假设解压之后在src下看到的主要 Java 文件包括LoginServlet.java、BookServlet.java、BorrowServlet.java、DBUtil.java这些类常见的划分方式是把它们按职责扔进controller或servlet包里把数据库相关代码归入dao把实体类丢到entity目录。这里的核心原则是把你改动的范围控制住。比如要改“还书”的日期判断你找BorrowServlet或者ReturnServlet而不是去一堆乱放的文件里盲猜。有个细节值得提有些老项目的源码里会出现sevlet这个拼错的包名——标题里也写了sevlet说明包名或者文件名里可能保留了同样的笔误。这不会影响编译如果后续你引包的时候发现import报错直接右键类名 Rename 调整即可不要因此觉得项目是坏的。配置层面WEB-INF/web.xml是 Servlet 映射的老管家。打开看会发现每个 Servlet 的servlet-mapping都写在里面比如servlet servlet-nameLoginServlet/servlet-name servlet-classcontroller.LoginServlet/servlet-class /servlet servlet-mapping servlet-nameLoginServlet/servlet-name url-pattern/login/url-pattern /servlet-mapping如果你的项目用WebServlet(/login)注解Servlet 3.0 的写法就不需要改web.xml里的映射新旧两种方式别重复配置同一路径否则部署到 Tomcat 时启动会报冲突。JSP 页面一般集中在WebContent或webapp目录下login.jsp、book_list.jsp、borrow_record.jsp这些页面文件与 Java 类分离改样式的时候不用重新编译 Java这是一条能省时间的边界。2.3 环境匹配JDK 8 别挂 Servlet 6Tomcat 9 才是标准答案这里稍微讲一下版本之间的“适配契约”。Servlet 是个接口规范Tomcat 是它的实现。Servlet 4.0 对应的正好就是 Tomcat 9 和 JDK 8这是课程设计开源项目最常见的组合。JDK 11 可以用但如果你碰到class file has wrong version这种启动报错多半是编译器级别设高了。更常见的坑是项目里用到javax.servlet依赖你引入的 Tomcat 是 10.1.x那包名已经变成jakarta.servlet了直接导致所有import javax.servlet.*编译全红。我的做法是固定组合JDK 8 Tomcat 9 宽松的编译级别这些主流开源课程项目全部能在这个组合下跑起来。3. 从零把项目跑起来数据库脚本与 JDBC 连接是第一个鬼门关3.1 建库建表脚本先导入注意 MySQL 版本的两个差异点绝大多数这类项目里都会带一个book_manager.sql或者library.sql打开先看不急着执行。你需要在 MySQL 的命令行或 Navicat 里新建一个数据库专门给这个项目用CREATE DATABASE IF NOT EXISTS db_library DEFAULT CHARSET utf8mb4; USE db_library; SOURCE /你的路径/book_manager.sql;如果你比较习惯命令行上面这段一步到位如果用 Navicat选中数据库db_library之后右键运行 SQL 文件即可——注意导入前后一定要确认当前选中的数据库是你要导入的那个不然表会落进别的库里。表结构这一块图书管理系统大致都会建这几张表t_book书名、作者、出版社、库存总量、t_student或t_user学号/工号、姓名、密码、t_borrow借书ID、图书ID、学生ID、借书日期、还书日期、是否归还。核心的借还逻辑靠t_borrow和t_book两张表关联完成——库存的变化以t_book中的数字为准每借出一本就把库存减一归还时加一。这时候要注意 MySQL 8.0 的问题把表导进去之后如果 SQL 里有gmt_create这种字段并且报错多半是旧版本日期类型的定义写法不兼容默认值改成DEFAULT CURRENT_TIMESTAMP就可以解决。3.2 数据库连接类别改错——尤其是 utf8 和时区引号的坑项目里那个负责与 MySQL 打交道的类通常叫DBUtil.java它决定了你是连得上数据库还是被Access denied按在地上摩擦。常见写法是package util; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; public class DBUtil { private static final String URL jdbc:mysql://localhost:3306/db_library?useSSLfalseserverTimezoneAsia/ShanghaicharacterEncodingutf8; private static final String USER root; private static final String PASSWORD 你的MySQL密码; 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); } }这里面有几个参数是血泪经验换来的必须单独解释一下useSSLfalse是关闭 SSL 握手因为 MySQL 8.0 驱动默认开启 SSL而本地的课程设计项目甚至 MySQL 服务端都没配证书报SSL connection error是常态跟上面那行热词错误完全对得上。serverTimezoneAsia/Shanghai是解决“服务器时区值一时区无法识别”的经典解法“CST”在中国服务器上被 MySQL 解释成美国中部时间结果就是日期永远差 13 个小时加了时区参数后借还书的日期计算才不出幺蛾子。characterEncodingutf8是保证中文不乱码的关键列写简体中文书名和姓名能不能正常入库就靠它。如果你的 MySQL 是 5.7 或更老驱动名要换成com.mysql.jdbc.Driver8.0 以后只能用com.mysql.cj.jdbc.Driver。写错驱动类名会直接抛ClassNotFoundException而且这个错不是在 IDE 里提示而是在 Tomcat 启动过程中炸给你看措辞是 “The origin server did not find a current representation for the target resource”。USER和PASSWORD是这台机器上的 MySQL 账号密码拿不到就去mysql -uroot -p试一下你想用的密码试出来的那份写进去就好。3.3 编译级别与库引用为什么老项目在别人的电脑上编译一大堆红色波浪线打开项目后IDE 里动不动就是一片红最常见的原因不是代码有问题而是三个环境小项没有对齐JDK 版本、语言级别、项目里引用的 Jar 包。这类项目一般会在根目录下带一个lib文件夹里面放着mysql-connector-java-x.x.jar、jstl.jar这些必要的依赖。如果在 Eclipse/IDEA 里不把这个文件夹 Add as Library代码里的import java.sql.*编译不过去查不出原因。具体动作以 IDEA 举个例子File → Project Structure → Libraries → → Java选中lib目录确定之后import的爆红至少能消掉一半。用 Maven 管理依赖的项目会更好办一点直接看pom.xml里的 artifact 版本把它粘贴进依赖搜索框同步即可。这里倒不用刻意追求新版本mysql-connector-java用 8.0.xjavax.servlet-api跟着 Tomcat 9 用 4.0.1版本保持这个组合稳定优先。搞定这三步之后Tomcat 能正常启动首页能打开你才真正拿到了“项目已跑通”的入场券。4. 把借阅归还这条主链路跑顺Servlet 请求处理与 JSP 页面联动4.1 借书功能的最小实现借书在流程上是一个“提交表单 → 接收参数 → 校验库存 → 改库存与记录”的事务这类项目的核心魅力就在这里Servlet 把串行逻辑穿起来JSP 只负责把你填好的表单内容传给后端。先看借书表单长什么样通常是borrow.jsp或者内嵌在book_list.jsp的一小块表格里form actionBorrowServlet methodpost input typehidden namebookId value${book.id} 学生学号input typetext namestudentNo button typesubmit借阅/button /formbookId用 hidden 隐藏域传递是因为用户列表里看到的是书名和作者后端真正要操作的是数据库里的主键 ID而不是书名这个可重复的字段。学生学号用文本框让用户输入对应的是t_student表里的唯一标识。你在部署之后试着借一本库存为 0 的书会跳到“借阅失败”的页面这就是后端校验的结果。4.2 Servlet 接收参数与业务处理BorrowServlet.java的职责是把 JSP 提交过来的数据接住然后决定“借阅成功”还是“借阅失败”。代码主体逻辑比较常见的是长这个样子的WebServlet(/BorrowServlet) public class BorrowServlet extends HttpServlet { protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.setCharacterEncoding(UTF-8); int bookId Integer.parseInt(req.getParameter(bookId)); String studentNo req.getParameter(studentNo); BorrowService service new BorrowService(); boolean ok service.borrowBook(bookId, studentNo); if (ok) { resp.sendRedirect(BorrowSuccessServlet); } else { req.setAttribute(msg, 借阅失败库存不足或学号不存在); req.getRequestDispatcher(borrow_fail.jsp).forward(req, resp); } } }req.setCharacterEncoding(UTF-8)放在doPost第一行是处理中文乱码的开场动作它管的是 POST 请求的 body 编码。如果你试图用 GET 方式提交中文参数那要改 Tomcat 的server.xml里的连接器配置加上URIEncodingUTF-8这是另一个独立话题。逻辑上先校验学生和书是否存在、库存是否大于 0再执行两步 SQL 更新插入借阅记录 图书库存减 1这两步在BorrowService.borrowBook()方法里最好开事务。4.3 事务边界为什么要卡在 Service 而不是 Servlet上面代码里我把具体逻辑交给了BorrowService而不是在doPost里直接写 SQL这是整个项目结构里值得你抄过去的一个分层习惯。BorrowService内部逻辑大致这样public boolean borrowBook(int bookId, String studentNo) { Connection conn null; try { conn DBUtil.getConnection(); conn.setAutoCommit(false); StudentDao studentDao new StudentDao(); Student s studentDao.findByNo(conn, studentNo); BookDao bookDao new BookDao(); Book b bookDao.findById(conn, bookId); if (s null || b null || b.getStock() 0) { return false; } bookDao.decreaseStock(conn, bookId); borrowDao.insert(conn, bookId, s.getId(), new Date(), null); conn.commit(); return true; } catch (Exception e) { try { if (conn ! null) conn.rollback(); } catch (SQLException ex) { ex.printStackTrace(); } return false; } finally { try { if (conn ! null) conn.setAutoCommit(true); conn.close(); } catch (SQLException e) { e.printStackTrace(); } } }核心在于conn.setAutoCommit(false)之后两步数据库操作要么全部提交要么全部回滚。如果没开事务就可能出现“库存减了 1 但借阅记录没插进去”或者反过来的状态后面你统计借阅报表时对不上账这个问题的排查成本远高于你开事务的这几行代码。常见的课程设计项目不会把Connection这个对象传进 DAO 方法而是每个方法内部重新拿一条连接那么事务边界就断了这种设计在这个场景可以直接改掉。4.4 还书流程与超期判断的处理还书相对借阅更简单定位到未归还的借阅记录把return_date写成当天。但多数项目不止做这一步它还会在还书时顺便判断是否超期并记录一个“逾期天数”或“罚款金额”字段。这个判断放在 SQL 里比较常见比如UPDATE t_borrow SET return_date NOW(), is_returned 1, overdue_days DATEDIFF(NOW(), borrow_date) - 30 WHERE borrow_id ? AND is_returned 0;别把DATEDIFF当成无限精确它只按天截断小时和分钟不会导致半天误差。如果想要更精准的时长需要TIMESTAMPDIFF(HOUR, ...)配合取整。这一步跑通后用户就能看到“应还日期”“已还日期”“是否逾期”这些列的正确跳变项目的核心功能就算闭环了。4.5 JSP 里的列表输出与 JSTL少用 Java 脚本片断看 JSP 页面时最难受的写法是用% %包一段 Java 代码去拼循环列表。虽然项目能跑但会牺牲页面的可读性——建议在能改的地方尽量用JSTL的c:forEach输出表格table c:forEach items${bookList} varbook tr td${book.name}/td td${book.author}/td td${book.stock}/td tda hrefBorrowServlet?bookId${book.id}借阅/a/td /tr /c:forEach /table注意${book.name}实际上调的是Book类里getName()方法JavaBean 规范在这里体现了价值。如果你改字段名比如把bookName改成name那么 JSP 里的表达式也得同步变化改了 Java 不用同步 JSP 是导致页面显示空白的经典翻车场景。Servlet 传数据给 JSP 的常见方式是req.setAttribute(bookList, service.findAllBooks()); req.getRequestDispatcher(book_list.jsp).forward(req, resp);转发的核心特征是浏览器地址栏不变还是/book_list.jspsendRedirect不一样它是浏览器重新发起一次新请求地址栏会变化。这两个术语是这类项目的核心考点也是你改代码时要分清楚的关键节点。5. 避坑清单5 个让这类项目跑不起来的隐蔽原因5.1 Tomcat 启动失败报ClassNotFound但代码里明明有 Jar 包现象代码里import com.mysql.cj.jdbc.Driver不爆红但 Tomcat 一启动或浏览器一访问就抛ClassNotFoundException: com.mysql.cj.jdbc.Driver。 原因驱动依赖虽然在 IDE 的构建路径里但没有打进运行环境。如果 Eclipse确认 Jar 放在了WebContent/WEB-INF/lib目录下而不是仅 Build Path如果 IDEA检查 Artifacts 的输出里是否包含 Jar。 解决把mysql-connector-java-x.x.jar单独复制到WEB-INF/lib内再 Clean 一次 Tomcat 的 work 目录重启就好了。5.2 登录页面点击“登录”后地址栏变成/login.jsp404现象按了登录按钮URL 停在http://localhost:8080/library/login.jsp并提示 404。 原因常见的是web.xml或WebServlet中映射的路径尖括号写错或者表单的action指向了一个不存在的login.jsp路径。 解决先用浏览器 F12 看 Network 面板确认请求的地址是不是/login如果确实请求到了 Servlet但 404重新检查WebServlet(/login)里路径开头有没有少斜杠表单里action是否使用了${pageContext.request.contextPath}/login以便添加上下文路径。5.3 页面中文全部变成问号????现象JSP 页面上中文正常数据库里也是正常中文但页面输出变成一行问号。 原因响应编码没设置。Tomcat 默认 ISO-8859-1 输出中文字符超过其范围就被转成?。 解决在 Servlet 的doGet/doPost里加一行resp.setContentType(text/html; charsetUTF-8)同时在 JSP 页面第一行确认有% page contentTypetext/html; charsetUTF-8 %。注意JSP 页面本身还要保存为 UTF-8 编码否则源代码里的中文就已经是乱码了。5.4Access denied for user rootlocalhost现象连数据库报无法访问但用 Navicat 连同一个数据库却正常。 原因DBUtil.java里写死了别的密码或者项目配置里的账号压根不是这台机器上的 MySQL 账号。 解决先用命令行mysql -uroot -p验证密码然后把DBUtil.java或jdbc.properties文件里的值替换成验证过的真实账号密码。MySQL 8 的驱动对空密码和默认密码策略比较敏感建议给 MySQL 设一个非空密码再试。5.5 改了数据库连接配置但重启后没效果现象改完jdbc.properties里 URL 的库名重启 Tomcat 看日志连接报的还是老库。 原因Tomcat 的内存缓存没有清理。修改了配置文件后直接 Redeploy 不能保证清掉旧的 class 缓存里的静态配置。 解决Better 的做法是在 IDEA 里先 Stop 再 Clean 项目删除out目录或者 Eclipse 里的target目录然后再 Start。如果还不行干脆到 Tomcat 安装目录的webapps下把旧目录删除再重新部署。6. 验证这套系统合不合格的三个要点以及我能给你的进阶方向项目跑起来并不意味着交付就结束。百分制里能不能拿到分甚至高分通常要盯三个验证方向功能链路是否完整、边界情况处理是否干净、文档里的“核心设计说明”能否对得上代码。功能链路上至少完整走一遍注册/初始账号登录 → 查看图书列表 → 借书 → 库存变化 → 还书 → 记录可见 → 重复借同一本书时库存不足提示。边界情况上要做两个极端的测试把库存改成 1借两次看第二次是否成功把当前日期改到应还日期之后看还书是否会标记超期。这两条是答辩老师最爱挑的软肋。文档报告方向上这类项目附带的那份《课程设计报告》一般会有功能模块图、数据库 ER 图、核心代码说明。把这些与你改过的代码对齐改过DBUtil就把截图换掉改过表名就把 ER 图同步改否则老师一边打开 PDF 一边看代码对不上号反而减分。因为实际工作里报告和代码一致本身就是评分点。最后给一个可选的进阶方向既不影响交付稳定性又比加分更有效果把DBUtil改成基于HikariCP的数据库连接池体验一下“每来一次借书请求不再重新连接 MySQL”的差异。这个改动只需引入一个HikariCP的 Jar替换DBUtil里获取连接的方式无论从实际系统的压测表现还是从谈话表现来说都远远好过只拿着 DriverManager 访问数据库。我的一个习惯是跑通之后抽一晚把 DAO 层的方法签名统一改成接口再去答辩因为当吸引老師关注的角度不只剩“为什么不用 Spring”。希望这些经验能真的救到某个熬到凌晨跑不通项目的你祝顺利跑通。提示项目跑通后先备份一份原压缩包后续改任何代码都基于复制出来的另一份目录操作这是所有 Java Web 老开发共同认可的后悔药。本文还有配套的精品资源点击获取
返回列表