
简介一套基于Java与JSP的图书馆管理系统完整源码及数据库文件面向Java课程设计、期末大作业与毕业设计参考场景。项目选用经典Servlet和JSP分层架构核心业务包括读者管理、图书管理、借还书、邮件通知等源码已在本地编译运行通过评审得分达到98分难度适中且经过助教老师审定可直接用于学习演示或二次扩展。资源压缩包共178个文件主要是Java源码、JSP页面、XML配置文件附带SQL数据库脚本、前端CSS与JS以及图片资源整体容量约11MB目录结构清晰能够按Controller、Service、实体类快速定位。目前已有149人学习下载。下载后导入IDE即可运行可重点参考图书检索、登录会话和邮件服务等模块对于完成课程设计和理解JSP项目开发有较直接的帮助。1. 期末大作业要的图书馆管理系统JSP 这套还值不值得交如果你正在做 Java 期末大作业手头这个「基于 JavaJSP 实现的图书馆管理系统」应该是相当经典的选题了它既是 JavaWeb 课程设计案例源码里最常见的一类也是老师最能快速验证你「有没有真跑起来」的项目。JSP 这套技术栈虽然看着老但它的好处恰恰在于结构透明——页面是 JSP、控制是 Servlet、数据是 JDBC三层关系一眼能看穿答辩时不容易被问倒也方便你往里面塞自己写的功能。这篇笔记按我自己的落地习惯来写先讲这套系统为什么长这样、表结构怎么设计再讲怎么把源码和数据库文件在你自己的电脑上跑通然后串一遍登录和借书还书的核心代码最后把最容易翻车的问题集中排掉。适合两类人一类是刚学完 JavaWeb 想找个能改的作业底子另一类是已经跑起来但想加功能、准备答辩的。全程不用框架正好把 JSP 和 Servlet 的本体看清楚。2. 先看技术栈和表结构图书馆系统的三层代码与 7 张表怎么配合2.1 为什么这个选题适合用 JSP 而不是 Spring Boot很多同学拿到题目第一反应是「能不能用 Spring Boot 做」。能用但期末大作业用 Spring Boot 有一个实际风险老师要求的是 JSP/Servlet 技术点你交上去一个 Boot 项目要么被扣分要么答辩时被追问「你用的依赖和自动配置到底做了什么」——这个问题对新手来说很容易答崩。JSP 的好处是每个文件都在干明确的事index.jsp就是首页LoginServlet.java就是处理登录代码量少、链路短背也好背。另外这套系统的业务复杂度也刚好卡在 JSP 擅长的范围。图书馆管理无非就是图书信息维护、读者信息、借书、还书、逾期判断都是单表单查询没有复杂的异步交互和状态流转。JSP Servlet JDBC 足够覆盖加个 Spring Boot 反而显得用牛刀杀鸡。真要给作品加分不如把加分项放在事务处理和 SQL 细节上这两块做好了比堆框架更能让老师认可。2.2 数据库文件里通常包含哪些表我见过的大多数 JavaJSP 图书馆管理系统源码里附带的数据库文件一般是.sql脚本少数会给.sqlite或 Access 格式。SQL 脚本最常见因为它可以直接在 MySQL 里用source命令导入跨机器也不会丢数据。表的设计大同小异核心有这么几张t_admin管理员表存账号密码登录功能主要查这张表t_book图书表包含书名、作者、出版社、ISBN、库存总量、当前可借数量t_reader读者表包含读者编号、姓名、联系方式、办证日期t_borrow借阅记录表核心字段是读者编号、图书编号、借出日期、应还日期t_return还书记录表有的系统把它和借阅合并成一张有的分两张除了这五张有的版本还会加t_category图书分类和t_punish罚款记录。表数量不是越多越好加表的代价是 JSP 页面和 Servlet 都要跟着改所以拿到源码后第一件事不是写代码而是打开 SQL 脚本数一下表摸清哪些表被哪些页面引用。2.3 三层结构的划分JSP 管显示、Servlet 管转发、DAO 管 SQL这套系统的代码目录一般长这样src/ ├── com.library.dao // 数据访问层里面是 BookDao、ReaderDao 等 ├── com.library.entity // 实体类对应每张表 ├── com.library.servlet // 控制层处理页面请求 ├── com.library.util // 工具类比如 DBUtil 数据库连接 └── com.library.filter // 过滤器处理编码和登录拦截WebRoot 或 webapp 目录下则是 JSP 页面和WEB-INF/web.xml。JSP 页面按功能分文件夹常见的是admin/和reader/分开因为管理员和读者的操作入口不一样。这里要强调一点JSP 页面不应该直接写 JDBC 代码。有些偷懒的版本把 SQL 直接写在% %里跑是能跑但老师问「你的分层是什么」时这种写法很难自圆其说。拿到源码先检查有没有dao包如果没有改造的第一步就是把它拆出来。3. 把源码跑通IDEA 导入、数据库恢复、Tomcat 部署三步走3.1 导入源码前的检查JDK 版本和项目类型导入到 IDEA 之前我先确认三件事JDK 版本、项目是 Web 工程还是普通 Java 工程、有没有带.iml或 Maven 配置。多数课程设计源码是传统 Web 工程不依赖 Maven所以你需要在 IDEA 里用「新建空项目 → 把源码拷进去 → 右键添加为模块」的方式导入或者直接用「Open」打开整个目录后IDEA 会自动识别是否为 Web 工程。一个比较隐蔽的坑是 JDK 版本。老源码用 JDK 8 编译你本机装的是 JDK 17 甚至更高代码里有javax.servlet的 import编译时就会报「程序包不存在」。做法是先看Project Structure里有没有设好 JDK再确认 Tomcat 版本。Tomcat 9 对应 JDK 8 以上没问题Tomcat 10 已经把javax.servlet换成了jakarta.servlet老源码在 Tomcat 10 上跑必挂。所以这个组合最稳JDK 8 Tomcat 9 MySQL 5.7 或 8.0。3.2 把数据库文件导入 MySQL两种方式选一种拿到.sql文件后打开 MySQL 命令行或者 Navicat。第一种方式是命令行导入适合文件比较大的情况mysql -u root -p --default-character-setutf8 mysql source D:/library.sql;souce后面写 SQL 文件的绝对路径注意路径里的斜杠方向。执行完可以show tables;确认表是否建好。第二种方式是图形化导入。Navicat 里右键「运行 SQL 文件」选到library.sql这一步特别容易出问题的是编码——如果 SQL 文件里有中文注释或中文数据编码选错了导进去就是乱码。建议在 MySQL 连接配置里把字符集设为utf8mb4再执行导入。导入完成后验证一下数据完整性SELECT COUNT(*) FROM t_book;如果返回 0可能是导入时丢了数据或者表结构里没有初始化数据。一般课程设计源码的 SQL 文件里会自带几条测试数据方便答辩时直接演示没有数据的话你得自己插几条。3.3 修改数据库连接配置账号密码和连接串数据库恢复好后下一步是找到项目里的数据库连接配置。常见位置有两个DBUtil.java里的静态代码块或者src/db.properties文件。内容一般是这样的Class.forName(com.mysql.cj.jdbc.Driver); String url jdbc:mysql://localhost:3306/library? useUnicodetruecharacterEncodingutf8useSSLfalseserverTimezoneAsia/Shanghai; String user root; String password 123456; Connection conn DriverManager.getConnection(url, user, password);这是我实际处理过的一个版本几个参数要特意说明useSSLfalse是为了避免 MySQL 8.0 的 SSL 警告serverTimezoneAsia/Shanghai是因为新版驱动连接时如果不指定时区会直接报错characterEncodingutf8配合数据库字符集才能保证中文不乱码。如果你的 MySQL 是 5.7驱动用com.mysql.jdbc.Driver也行但 MySQL 8.0 必须用com.mysql.cj.jdbc.Driver并且cj不能省略——这是换驱动包后最常踩的坑。3.4 Tomcat 部署IDEA 里跑和打包 war 两条路本地调试用 IDEA 内置 Tomcat 集成最快。在Run Configuration里新增 Tomcat Server选 LocalDeployment 标签页加 ArtifactApplication context 填/library。启动后访问http://localhost:8080/library看能不能出首页。如果首页出不来优先看 IDEA 的控制台日志常见是端口被占、Context 路径配错、缺依赖包。如果你在宿舍没有 IDEA 正版授权或者答辩时要换一台电脑演示更稳妥的方式是打包成 war。传统 JSP 项目打包 war 不需要 MavenIDEA 里 Build → Build Artifacts → 选择library:war即可然后把library.war丢到 Tomcat 的webapps目录下启动 Tomcat 自动解压。这个方式的好处是部署链路跟 IDEA 无关换机器只需要 JDK Tomcat MySQL 三个环境对答辩现场的兼容性最好。要注意 war 包的 context 路径默认是 war 文件名访问地址会变成http://localhost:8080/library/。4. 核心代码串讲登录、借书、还书三条链路的落地写法4.1 登录校验Servlet 里查表Session 记状态登录是整套系统的门面代码链路也最完整JSP 表单提交到 ServletServlet 调 DAO 查管理员表查到了就跳主页查不到就回登录页带个错误提示。我挑一段登录 Servlet 的核心代码来说public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding(UTF-8); String username request.getParameter(username); String password request.getParameter(password); AdminDao dao new AdminDao(); Admin admin dao.findByUsernameAndPassword(username, password); if (admin ! null) { HttpSession session request.getSession(); session.setAttribute(admin, admin); response.sendRedirect(admin/index.jsp); } else { request.setAttribute(error, 账号或密码错误); request.getRequestDispatcher(login.jsp).forward(request, response); } }几个容易被忽略的细节setCharacterEncoding(UTF-8)必须在getParameter之前调用否则 POST 提交的中文用户名会乱码sendRedirect和forward的选择有讲究登录成功后用重定向避免刷新页面时重复提交表单密码校验放在 DAO 里而不是 Servlet 里保持分层清晰。这里还要注意Admin实体类的字段要和表结构对应我见过源码里findByUsernameAndPassword返回的是boolean这样 Session 里就存不了完整的管理员信息后续页面要显示「欢迎 xxx 登录」就得再查一次表。4.2 借书逻辑事务在这里是最关键的加分项借书是整个系统里最容易出 bug 的地方因为它在逻辑上要同时干两件事往t_borrow表插一条借阅记录把t_book表里对应图书的可借数量减一。这两步必须同时成功或同时失败否则就会出现「借阅记录有了但库存没减」或者反过来。很多课程设计源码在这里用两条独立 SQL 搞定不出故障还好一旦中途报错数据就脏了。答辩时你能主动把这个问题点出来是很明显的加分项。public boolean borrowBook(int readerId, int bookId) throws Exception { Connection conn null; PreparedStatement ps1 null; PreparedStatement ps2 null; try { conn DBUtil.getConnection(); conn.setAutoCommit(false); // 关键关闭自动提交 String sql1 INSERT INTO t_borrow (reader_id, book_id, borrow_date, return_date) VALUES (?, ?, NOW(), DATE_ADD(NOW(), INTERVAL 30 DAY)); ps1 conn.prepareStatement(sql1); ps1.setInt(1, readerId); ps1.setInt(2, bookId); ps1.executeUpdate(); String sql2 UPDATE t_book SET available_num available_num - 1 WHERE id ? AND available_num 0; ps2 conn.prepareStatement(sql2); ps2.setInt(1, bookId); if (ps2.executeUpdate() 0) { conn.rollback(); // 库存不足回滚借阅记录 return false; } conn.commit(); return true; } catch (Exception e) { conn.rollback(); throw e; } finally { DBUtil.close(conn, ps1, ps2); } }这里available_num 0这个条件很值得展开讲库存在并发情况下两条请求同时判断「数量大于 0」都可能通过但加上这个条件到 Update 语句里数据库层面的行锁会保证只有一个请求真正更新成功另一个executeUpdate()返回 0然后回滚。这就是把业务规则塞进 SQL 而不是靠 Java 代码判断的好处。参数上INTERVAL 30 DAY是借期 30 天不同学校要求不一样改这个数字就能适配。4.3 还书逻辑计算逾期把状态写干净还书比借书多一个动作算逾期。t_borrow表里存了return_date应还日期还书时拿当前日期和它比逾期就把罚款记录写进t_punish表。常见写法是public void returnBook(int borrowId) throws Exception { Connection conn DBUtil.getConnection(); conn.setAutoCommit(false); String sql1 SELECT book_id FROM t_borrow WHERE id ? AND actual_return_date IS NULL; // 查到借阅记录 String sql2 UPDATE t_borrow SET actual_return_date NOW() WHERE id ?; String sql3 UPDATE t_book SET available_num available_num 1 WHERE id ?; // 判断逾期计算天数并插入罚款 String sql4 INSERT INTO t_punish (borrow_id, days, amount) VALUES (?, ?, ?); ... }还书容易漏的一步是只更新了借阅表的实际还书日期忘了把可用数量加回去。这种 bug 的表现是「借了几次之后库存慢慢变成负数」。如果源码里没有这一步你要么自己补上要么在答辩时明确说「还书只做了记录更新库存恢复还需要扩展」这两种选择都比假装没问题强。5. 踩坑记录从导入报错到中文乱码的 5 个高频问题5.1 编译报「程序包 javax.servlet 不存在」现象源码导入 IDEA 后所有 Servlet 类都飘红报java: package javax.servlet does not exist。原因项目没有把 Tomcat 自带的 servlet-api 依赖加到构建路径里。IDEA 里单纯配了 Tomcat Server 不代表编译时就自动带上了 Servlet API。解决菜单 File → Project Structure → Libraries → 加 Tomcat 所在目录下lib/servlet-api.jar或者更省事情的做法是在「添加框架支持」里重新关联一遍 Tomcat。如果你是 JDK 17 Tomcat 10 的组合光加 jar 也没用因为 Tomcat 10 改成jakarta.servlet了最省心的方案就是按前面说的降到 JDK 8 Tomcat 9。5.2 MySQL 驱动报错ClassNotFoundException 或 Public Key Retrieval is not allowed现象启动 Tomcat 后第一次访问数据库相关页面日志里抛java.lang.ClassNotFoundException: com.mysql.jdbc.Driver或Public Key Retrieval is not allowed。原因前者是项目里根本没有 mysql 驱动 jar 包后者出现在 MySQL 8.0 用 caching_sha2_password 认证时驱动连接串少了allowPublicKeyRetrievaltrue参数。解决把mysql-connector-java的 jar 包放到WEB-INF/lib目录下连接串加上两个参数allowPublicKeyRetrievaltrueuseSSLfalse。注意驱动类名MySQL 8 的驱动类必须是com.mysql.cj.jdbc.Driver老版本的com.mysql.jdbc.Driver虽然兼容但已经不建议用了。5.3 登录时页面显示乱码数据库里的中文也乱现象登录页输入中文用户名校验不过或者页面上显示「????????」。原因三层编码不一致数据库连接串的characterEncoding没设或者 JSP 页面头部没有 contentType 声明或者导入 SQL 文件时选了错误的字符集。这三处只要有一处断链必乱码。解决按三个位置依次检查。第一数据库连接串加上useUnicodetruecharacterEncodingutf8第二JSP 页面顶端确认% page contentTypetext/html; charsetUTF-8 %第三重新导入 SQL 文件用--default-character-setutf8参数。三层全对齐后乱码基本根治。如果还乱检查 MySQL 服务端全局变量character_set_server用SHOW VARIABLES LIKE character_set%;查看。5.4 Tomcat 启动后报端口被占用现象IDEA 控制台报Port 8080 was already in use项目起不来。原因上次运行 Tomcat 没有正常关闭后台还残留一个 java 进程占着端口。这在宿舍联调、反复改代码的场景下特别常见。解决Windows 下用netstat -ano | findstr :8080查出 PID然后任务管理器里结束对应进程。更省事的办法是把端口改掉IDEA 的 Run Configuration 里 HTTP port 改成 8081注意改了之后访问地址要跟着换。顺便说一句war 包部署到 Tomcat 后如果遇到端口占用是webapps下同名项目在 Tomcat 启动时重复加载导致冲突检查一下webapps目录里是否有解压目录和 war 包共存。5.5 JSP 页面里% %显示的是%原文现象页面直接输出%或者 JSP 脚本片段没有被解析源码原样显示在浏览器里。原因文件后缀不是.jsp或者 web.xml 里没有正确配置 JSP 的 servlet 映射。常见的变体是把 JSP 页面存成了.html然后里面写 JSP 标签。解决确认文件扩展名改成.jsp如果是 IDEA 里新建的 HTML 文件写的 JSP 代码直接把扩展名改掉IDEA 会重新识别。另外检查 web.xml 中welcome-file-list首页配置要指向实际存在的 JSP 文件否则 Tomcat 找不到默认页也会展示源码路径。6. 答辩前的进阶改造借阅上限、逾期罚款与 war 打包验证到这一步系统已经能跑、能借能还但期末作业想要拿高分得往里面加几个老师一眼就能看到「你动了脑子的功能」。我比较推荐三个方向改动量小、逻辑清晰、答辩也好讲。第一个是读者分级借阅上限。很多源码里读者可以无限借书你可以在t_reader表加一个max_borrow_num字段借书时在事务里先查当前未还数量达到上限就拒绝。这段逻辑放在borrowBook方法开头大概多 5 行代码。第二个是逾期罚金的自动计算。还书时把actual_return_date return_date的天数乘上单日罚金写进t_punish表这个功能能把你前面学的事务处理完整串起来。第三个是页面上的统计展示管理员首页加一行 SQL 查当前借出总数和逾期未还列表用 JSTL 标签循环展示即可。改造完建议做一轮完整的验收流程新管理员登录 → 新增一本测试图书 → 新增一个读者 → 借书 → 改数据库里的应还日期为昨天 → 还书 → 查看罚款记录。每一步都截图答辩 PPT 里直接放截图比放代码有说服力。最后用前面说的打包 war 方式在干净的 Tomcat 环境里跑一遍确认换机器不依赖 IDEA 就能演示。我自己的习惯是在答辩前把webapps里的旧目录删掉重新丢一次 war 包这样能确保 TOMCAT 解压出的资源是最新的能避免演示时改过的代码没生效这种尴尬情况。这套流程走完你手里就不只是一个交差的作业而是一个能讲清楚每个模块为什么这么写的作品。希望帮到你。最后一句话送给你调试 JSP 项目遇到问题先看日志再看配置最后才看代码——九成问题出在你以为没问题的地方。本文还有配套的精品资源点击获取