资讯动态

JavaWeb图书馆管理系统:Servlet+JSP+JDBC+MySQL部署与避坑

发布时间:2026/10/14 23:00:50 来源:尧图企业网站定制
简介一份面向高校图书馆图书管理场景的JavaWeb项目源码适合Java Web初学者、课程设计者及相关开发人员参考。系统基于Servlet、JSP、JavaBean与MySQL实现覆盖图书信息管理、借阅记录、读者账户、登录认证与权限控制等核心模块可帮助读者理解MVC分层架构、数据库表设计与前后端交互流程。压缩包共209个文件大小1.91MB包含51个JSP页面、32个Java源文件、32个class文件以及jar依赖包、sql脚本、properties配置等其中SQL可用于生成图书、读者、借阅等数据表结构配套较完整便于导入工程或部署运行。目前已有358人学习下载适合课程设计或自学参考。内含用户认证与授权、请求转发、JSTL/EL、异常处理等Web开发要点通过学习源码可直接掌握从数据库建模到Servlet控制层、JSP视图层的一整套实现思路也可基于现有结构二次扩展功能。1. 拿到这份 javaWeb 图书馆管理系统源码先认清技术栈再动手图书馆管理系统是 JavaWeb 课程设计里出现频率最高的一类题目这份源码就是典型的 Servlet JSP JDBC MySQL 组合。它不是 Spring Boot 那套新东西而是经典的 JavaWeb 三层结构入口是 JSP 页面请求由 Servlet 接收数据访问直接用 JDBC 写 SQL。适合刚学完 Servlet/JSP、想找一个完整项目跑通全流程的人也适合拿它当课程设计或毕业设计的底座再往上改。很多人解压后直接导入 IDE 就点运行然后被一屏 500 错误劝退。问题通常不在代码本身而在环境组合老驱动配新 MySQL、Tomcat 版本前后不兼容、SQL 脚本字符集不对。动手部署之前先花十分钟看清它属于哪一代技术栈后面能避开大半问题。2. 解压后先别急着跑目录结构与数据库初始化是第一步2.1 认识分包entity、dao、service、servlet、jsp 各自管什么这类老项目大多沿用同一个分包思路理解之后排错会快很多。从 src 目录看一般是 entity、dao、servlet 三个核心包service 层看模板的完成度有的直接省略由 servlet 调 dao。entity 里的类对应数据库表常见是图书、读者、管理员、借阅记录这几个dao 类负责写 JDBC 代码方法里几乎都是 getConnection、prepareStatement、executeQuery 这条固定链路servlet 接收页面请求调用 dao 拿到结果再跳回 JSP 渲染。src/com/xxx/ ├── entity/ # Book.java、Reader.java、Admin.java、Borrow.java ├── dao/ # BookDao.java、ReaderDao.java、AdminDao.java ├── service/ # 部分模板有放借书/还书等业务方法 └── servlet/ # LoginServlet、BookServlet、BorrowServlet、ReturnServlet WebContent/ ├── index.jsp # 登录页 ├── book_list.jsp ├── reader_list.jsp └── WEB-INF/ ├── web.xml # Servlet 映射和欢迎页配置 └── lib/ # mysql-connector-java 驱动 jar逻辑说明WEB-INF/lib 是 JavaWeb 动态项目的标准依赖目录IDE 部署时会原样复制到 Tomcat 的 WEB-INF 下。如果你看到 lib 目录是空的或者导入项目后 jar 没被编译进输出目录后面几乎必然报 ClassNotFoundException。很多老模板的 web.xml 会显式声明 Servlet 映射你要顺手看一眼 url-pattern 是 /login 还是 /LoginServlet后面调试登录接口会用到。参数说明实体类字段通常和下划线表字段一一对应比如图书表可能有 id、book_name、author、publisher、status 等列。status 在这个系统里一般表示在架/借出状态是借书逻辑的关键判断位后面第四章会专门讲它的坑。先确认 status 是 int 还是 varchar再决定你的业务判断怎么写。2.2 数据库初始化SQL 脚本、Navicat 导入和连接参数对照运行阶段第一个高频异常是 Unknown database原因很简单脚本没导入或者导入后库名和代码里写的不一致。常见做法是用 Navicat 连接本机 MySQL把压缩包里的 SQL 脚本拖进去执行库名一般是 library 或者 book_manager以你包里的脚本为准。我一般建议先打开脚本看一眼开头确认 CREATE DATABASE 那行的名字和字符集再执行导入。CREATE DATABASE IF NOT EXISTS library DEFAULT CHARSET utf8; USE library; DROP TABLE IF EXISTS t_reader; CREATE TABLE t_reader ( id INT AUTO_INCREMENT PRIMARY KEY, username VARCHAR(20) NOT NULL, password VARCHAR(32) NOT NULL, real_name VARCHAR(20) DEFAULT , max_borrow INT DEFAULT 5, status TINYINT DEFAULT 1 ) ENGINEInnoDB DEFAULT CHARSETutf8;逻辑说明这段 SQL 只是按图书馆管理系统的常见表结构给你一个参照实际包里字段名可能叫 user_name 或 realname但业务含义一致。建表语句里我把 max_borrow 做成默认 5意思是每个读者最多同时借 5 本。后面借书逻辑里要查到这条记录做数量校验否则读者可以无限借。参数说明字符集用 utf8ENGINE 用 InnoDB。InnoDB 支持事务这是第四章讲借书回滚的前提。如果你导入后 Java 端中文全是问号一方面看数据库表是不是 utf8另一方面检查 JDBC URL 有没有带 characterEncoding这两个必须对得上。用 Navicat 导入时还要注意脚本文件的编码Windows 记事本另存为 ANSI 的 SQL 文件经常在导入后变成乱码。接下来是连接参数这是老项目里最需要手动改的地方。很多模板用的是 MySQL 5.x 配套的老驱动本机装的是 MySQL 8.x不改参数直接连大概率报 SSL 连接错误或者时区错误。配置项MySQL 5.x / 驱动 5.1.xMySQL 8.x / 驱动 8.0.x驱动类com.mysql.jdbc.Drivercom.mysql.cj.jdbc.DriverJDBC URLjdbc:mysql://localhost:3306/library?useUnicodetruecharacterEncodingutf8老 URL 基础上追加 serverTimezoneAsia/ShanghaiuseSSLfalse建议 Tomcat8.5 或 9.08.5 或 9.0连接参数作用常见错误值useUnicodetrue启用字符集编码参数不配置时中文乱码characterEncodingutf8指定客户端传输编码和数据库编码不一致时存不进中文serverTimezoneAsia/Shanghai指定服务器时区MySQL 8 缺省时报时区错误useSSLfalse关闭 SSL 握手不配置时报 SSL 连接警告或异常public class DBUtil { private static final String URL jdbc:mysql://localhost:3306/library ?useUnicodetruecharacterEncodingutf8 serverTimezoneAsia/ShanghaiuseSSLfalse; private static final String USERNAME root; private static final String PASSWORD root; public static Connection getConnection() throws Exception { Class.forName(com.mysql.cj.jdbc.Driver); return DriverManager.getConnection(URL, USERNAME, PASSWORD); } }逻辑说明这段代码把驱动类、URL、账号密码全部集中在一个工具类里排错时只改这一处。Class.forName 在 JDBC 4.0 之后不是必须写的但老项目里保留它反而有好处如果 jar 没部署到 WEB-INF/lib这里会最早把异常抛出来方便定位。参数说明URL 我按 MySQL 8.x 的推荐写法拆成了三段拼接实际用一行字符串也行。PASSWORD 要改成你自己本机的数据库密码。如果你包里的驱动 jar 还是 com.mysql.jdbc.Driver 的 5.x 老版本我一般会建议直接换成 mysql-connector-java 8.0.x 的 jar同时把驱动类名改成 com.mysql.cj.jdbc.Driver别在 5.x 驱动上硬扛。注意改完连接参数后记得在 IDE 里 clean 一次项目再重启 Tomcat。只改代码不清理输出目录Tomcat 可能还在跑旧的 class 文件这是最常见的一处“我都改对了为什么还报错”的玄学现场。3. 把系统跑起来Tomcat 部署与管理员登录链路调试3.1 用 Eclipse 或 IDEA 打开项目部署方式和版本差异老模板的部署方式和现代 Maven 项目差别很大。它没有 pom.xml而是一个可以直接丢进 Tomcat webapps 的动态 Web 项目。用 Eclipse 导入时选 Existing Projects into WorkspaceIDEA 里选 Open 后按目录结构识别成 Web 项目。核心步骤是先确认项目的 Facets 里勾了 Dynamic Web Module然后把 WEB-INF/lib 下的驱动 jar 加进依赖最后在 Run Configuration 里指定本地 Tomcat。# 检查 8080 端口是否被占用 netstat -ano | findstr 8080 # 检查依赖是否在输出目录里 ls WebContent/WEB-INF/lib/逻辑说明第一行命令解决的是端口占用问题。有些机器上之前装过其他服务占住 8080Tomcat 启动日志会报端口被占用改端口不如先看谁占了端口。第二行命令建议在部署前确认一下 WEB-INF/lib 里确实有 mysql 驱动 jar如果没有不用看代码问题已经定位了。参数说明Tomcat 版本建议用 8.5 或 9.0。如果你本机装的是 Tomcat 10老项目里大量 javax.servlet 包名的类会直接加载失败因为 Tomcat 10 把包名整体换成了 jakarta.servlet。不少人对着一屏 500 查了半天业务代码实际就是版本错配。部署时还有一点要说明老项目通常没有 mavenIDEA 里 Run on Tomcat 时要注意 Deployment 页签。如果只加了 Application context 没加 war exploded 的 artifact运行时 index.jsp 可能找不到 Servlet 映射。常见做法是添加一个 war exploded把 Application context 设为根路径 /这样访问地址就是 localhost:8080 而不是带项目名。3.2 管理员登录链路从 index.jsp 到 servlet 到 dao 的参数传递登录链路是这套系统的命脉先把它跑通后面图书管理、借书还书都顺着同一条路径走。页面提交用户名和密码到 ServletServlet 调 dao 查库查到了就写 session 并重定向到图书列表查不到就带回错误参数跳回登录页。form action%request.getContextPath()%/login methodpost input typetext nameusername placeholder用户名 / input typepassword namepassword placeholder密码 / input typesubmit value登录 / /form逻辑说明action 我习惯写成加 contextPath 的动态拼接而不是写死的 /login。这样部署到非根路径时也能正常提交。如果老页面里写的是绝对路径部署后点登录会 404这是 JSP 老项目里很常见的一种路径问题。参数说明username 和 password 是表单字段名后端 Servlet 必须用同名 getParameter 来取两边对不上时页面会显示提交成功但永远登录失败因为参数取到的是 null。WebServlet(/login) public class LoginServlet extends HttpServlet { Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String username request.getParameter(username); String password request.getParameter(password); UserDao userDao new UserDao(); boolean flag userDao.checkLogin(username, password); if (flag) { request.getSession().setAttribute(loginUser, username); response.sendRedirect(request.getContextPath() /book?actionlist); } else { response.sendRedirect(request.getContextPath() /index.jsp?msgerror); } } }逻辑说明登录成功后我用重定向而不是转发原因是避免浏览器刷新时表单重复提交。session 里写入 loginUser 之后图书列表页可以拿这个值做权限判断。老模板里很多地方直接在 JSP 里拼 SQL这种写法能跑但容易被注入后面我会说怎么小成本改一道。参数说明如果包里的 Servlet 映射是 web.xml 写的而不是注解那 WebServlet 可以去掉url-pattern 以 web.xml 为准。判断方法很简单打开 WEB-INF/web.xml 看有没有 servlet-mapping如果有登录地址可能不是 /login而是你刚在 2.1 节里看到的那个映射名先别急着改代码顺着 web.xml 走一遍。借书主流程比登录稍微绕一点它涉及库表和业务状态变更核心逻辑是三步检查图书状态、更新图书状态、插入借阅记录。老模板常把这三步拆在 dao 的不同方法里中间没有事务保护。try { conn.setAutoCommit(false); // 1. 检查图书 status 为 1 才可借 // SELECT status FROM t_book WHERE id ? // 2. 更新为已借出带上 status1 的条件 // UPDATE t_book SET status 2 WHERE id ? AND status 1 // 3. 插入借阅记录 // INSERT INTO t_borrow(book_id, reader_id, borrow_date) VALUES (?, ?, NOW()) conn.commit(); } catch (Exception e) { conn.rollback(); } finally { conn.setAutoCommit(true); }这段逻辑说明第 2 步 UPDATE 里的 AND status 1 是关键。它保证了只有当前状态是在架的书才能被借出。两个读者同时提交借同一本书时数据库的行锁会让其中一个 UPDATE 影响行数为 0从而在业务层拦住重复借阅。不加这个条件的模板并发下会出现一本书被借两次的灵异现象。参数说明setAutoCommit(false) 开启手动事务commit 放在最后rollback 放 catch这样一个环节失败整个操作回滚不会出现图书标记成已借出但借阅记录没写进去的半截状态。老模板如果没做这一步还书和借书的数据经常对不上统计报表自然也不准。4. 避坑与排查五处从启动失败到并发超借的踩坑记录这一章是实际跑这个源码时最常遇到的五个问题我按现象、原因、解决三个层次来拆。五条不算多但每一条都足够卡住半天。4.1 启动失败Tomcat 版本、驱动缺失、端口占用第一个现象是页面 500控制台报 java.lang.ClassNotFoundException: javax.servlet.http.HttpServlet。原因多半是 Tomcat 版本太高。Tomcat 10 起把 javax.servlet 换成 jakarta.servlet老项目里的 Servlet、Filter 全部失效。解决方法是换回 Tomcat 8.5 或 9.0代码不用动版本和包名对齐后 500 自然消失。第二个现象是控制台报 Class.forName 找不到 com.mysql.jdbc.Driver 或者 com.mysql.cj.jdbc.Driver。原因分两种驱动 jar 没在 WEB-INF/lib 里或者驱动类名和 jar 版本不匹配。5.x 驱动是 com.mysql.jdbc.Driver8.x 驱动是 com.mysql.cj.jdbc.Driver写反了照样找不到。解决方法是去 WEB-INF/lib 看一眼实际 jar 的名字再和 DBUtil 里的类名对齐。如果 jar 在磁盘上但 IDE 没导出右键项目 Build Path 看 Libraries确认后 clean 一次再重启。第三个现象是启动 Tomcat 时端口被占用日志里写着 The port 8080 is already in use。原因通常是之前有残留的 Tomcat 实例没杀干净或者本机其他服务占了端口。解决方法是 netstat -ano | findstr 8080 查到占用进程的 PID去任务管理器结束对应进程或者改 Tomcat 的 server.xml 端口。改端口的代价是访问地址变了我一般优先杀进程而不是改端口。4.2 业务跑通后乱码、并发校验与统计口径不准第四个现象是页面中文全部变成问号数据库里存进去的也是问号。原因至少有三个叠加SQL 脚本文件本身的编码、MySQL 表字符集、JDBC URL 的 characterEncoding 参数。只改一处永远修不好必须三处对齐。解决方法是先把 SQL 脚本用 UTF-8 重新保存后再导入建表时 DEFAULT CHARSETutf8最后在 JDBC URL 里带上 useUnicodetruecharacterEncodingutf8三处一致后重启 Tomcat。第五个现象是同一本书在短时间内能被两个读者先后借走还书后库存变成负数。原因是老模板借书逻辑里的 UPDATE 没有带上 status 条件也没有事务。两个请求同时读到 status 为可借然后各自执行更新库存就超发了。解决方法是按第三章的写法在 UPDATE 里加 AND status 1同时把检查库存、更新状态、插入借阅记录包进同一个事务里。改完之后可以开两个浏览器同时点借书按钮验证第二本应该被拦下来。5. 落地验证技巧两分钟跑通核心闭环再做三处小改造5.1 两分钟确认核心闭环验收项目时不要漫无目的地点页面我建议按一条主链路走管理员登录、新增一本测试图书、新建一个测试读者、执行借书、执行还书、查看借阅统计。这条链路覆盖了表的新增、修改、状态流转和聚合查询跑通了至少说明系统骨架是可信的。统计查询是很多模板做得最敷衍的地方但恰恰是最容易被提问的模块。老模板可能只做了简单的列表展示没有按图书维度统计借阅次数的 SQL。你可以手写一条这样的验证查询SELECT b.book_name, COUNT(br.id) AS borrow_cnt FROM t_borrow br JOIN t_book b ON br.book_id b.id JOIN t_reader r ON br.reader_id r.id WHERE br.borrow_date CURDATE() - INTERVAL 30 DAY GROUP BY b.book_name ORDER BY borrow_cnt DESC;逻辑说明这条 SQL 统计最近 30 天每本书的借阅次数按次数倒序排。它同时验证了 t_borrow、t_book、t_reader 三张表的主外键关系对不对以及 borrow_date 的日期计算能不能用。模板表名和字段名如果和这里不一致先把 SQL 换成包里的实际表名再执行。参数说明CURDATE() - INTERVAL 30 DAY 是统计窗口改成 7 就是最近一周。如果你的 MySQL 版本比较老也可以写成 DATE_SUB(CURDATE(), INTERVAL 7 DAY)效果相同。5.2 答辩前值得做的三处小改造第一处是密码加密。老项目里密码几乎都是明文存在 t_reader 或 t_admin 表里答辩时被问一句“密码安全怎么考虑”就答不上来。常见做法是在登录注册时用 MD5 加盐做摘要比如 DigestUtils.md5Hex(password salt)salt 可以用用户名或固定字符串代码量很小但能体现你考虑过安全问题。第二处是给所有 dao 层的异常加上日志。老模板的 catch 块里通常只有 printStackTrace控制台输出不够直观。如果你不想引入 log4j最轻量的办法是在 catch 里把异常信息重新包装后抛给 servlet在 servlet 里记录一个带参数的错误日志。这样出问题时能直接看到是哪本书、哪个读者的操作失败而不是面对一行裸的 SQLException。第三处是统一页面字符集。老模板的 JSP 页面有的写 GBK有的写 UTF-8不同页面互相跳转后标题乱码。把每个 JSP 顶部的 page 指令统一成 UTF-8同时把 web.xml 里设置一组 characterEncodingFilter能一次解决全站乱码。这三处改动加起来不超过半天属于性价比最高的答辩前准备工作。从那以后我每次拿到这种老项目都强制自己先做三件事看 lib 目录里的驱动版本看 SQL 脚本的字符集看 web.xml 里的 Servlet 映射。这套三板斧帮我避掉过至少十次无意义的排错。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑