资讯动态

JavaWeb图书管理系统:Servlet+JSP+MySQL从零搭建实战

发布时间:2026/10/8 4:53:12 来源:尧图企业网站定制
简介这是一份面向Java Web初学者的图书管理系统实战项目适合作为大二学生期末大作业或Javaweb技术栈入门练手。系统完整覆盖用户分层学生/管理员、核心业务借阅/归还/续借/留言、状态管理6类书籍状态信誉等级控制及日志记录功能并支持前后端分离式登录验证、Ajax异步交互、Cookie自动登录与Session会话管理。资源包共59个文件含26个Java后端逻辑类Book/Student/Admin/Evaluation等实体与DAO/Service/Controller层、13个HTML前端页面、3个JSP动态视图、7个MyBatis与Spring配置XML、5张界面截图JPG及1个SQL建表脚本结构清晰、模块解耦便于理解MVC分层设计与数据库交互流程。压缩包仅879KB轻量易部署已有1915人学习下载附带README说明与可直接运行的项目骨架适合快速上手、调试与二次开发。1. 图书管理系统大二上学期 JavaWeb 期末大作业为什么它是最值得动手的练手项目不是所有“学生项目”都配叫练手项目——真正能帮你把 Servlet、JSP、MySQL、Tomcat 四件套焊进肌肉记忆的只有图书管理系统。它表面是增删改查内里却藏着 JavaWeb 工程从零启动的完整链路前端表单怎么和后端 Servlet 对齐参数名MySQL 的datetime字段为什么总在页面显示成nullTomcat 启动报ClassNotFoundException: com.mysql.cj.jdbc.Driver是驱动没放对位置还是 Maven 依赖 scope 写成了testIDEA 里配置 Artifacts 时漏勾Exploded部署后连index.jsp都 404……这些不是玄学是每个 JavaWeb 新手必踩的“标准坑”。它不追求高并发或微服务架构但要求你亲手搭起请求流转闭环浏览器 → Tomcat → Servlet → DAO → MySQL → ResultSet → JSP → 浏览器。大二上学期做它时间刚好卡在学完 Java 基础、刚接触 JDBC 和 Servlet 的临界点用 IDEA Tomcat 9 MySQL 8 JSP/Servlet 原生技术栈不引入 Spring Boot 干扰底层理解才是对初学者最诚实的训练。如果你正为期末大作业发愁或者想验证自己是否真懂了“JavaWeb 是什么”这个项目就是那把钥匙——拧开它你看到的不是代码是整个 Web 开发的骨架。2. 从零建工程用 IDEA 搭建可运行的 JavaWeb 项目结构含 Tomcat 配置与 Artifact 设置2.1 创建标准 JavaWeb Module别跳过 web.xml 和 WEB-INF 目录IDEA 新建项目时必须选择 “Empty Project” → 右键 New → Module → Java Enterprise → Web Application勾选 Create web.xml。这是关键一步很多同学直接选 “Maven” 模板结果生成的目录结构缺web.xml后续 Servlet 映射全靠注解而大二课程要求恰恰是 XML 配置方式。创建后确认项目根目录下存在src/main/webapp/WEB-INF/web.xml且webapp下有index.jsp。若没有请手动补全src/ ├── main/ │ ├── java/ ← 放 Servlet 和 DAO 类 │ └── webapp/ ← 静态资源和 JSP │ ├── index.jsp │ └── WEB-INF/ │ ├── web.xml ← 必须存在且版本声明为 3.0 │ └── lib/ ← 手动放 mysql-connector-java.jar见 2.3提示web.xml的web-app根标签必须声明version3.0或更高并指定xmlns否则 Tomcat 9 会拒绝加载。常见错误是复制旧模板导致 namespace 缺失。2.2 配置 Tomcat Server本地调试的核心环节打开Run → Edit Configurations → → Tomcat Server → Local关键设置如下Application context:/book不要留空否则访问地址是http://localhost:8080/易与默认首页冲突Deployment → Artifact: 选择your-module-name:war exploded注意是exploded不是war否则修改 JSP 后需重新打包Before launch → Build Artifacts: 勾选对应 artifact确保每次运行前自动编译注意如果点击 Run 后浏览器打开空白页或 404请立即检查Deployment选项卡中 Artifact 是否已添加且Application context与浏览器地址栏路径一致如设为/book则必须访问http://localhost:8080/book/。2.3 添加 MySQL 驱动jar 包放哪scope 怎么写两种方式任选其一但必须统一方式一传统 lib 目录推荐给大二作业直观可控下载mysql-connector-java-8.0.33.jar适配 MySQL 8放入src/main/webapp/WEB-INF/lib/。IDEA 会自动将其加入 classpath。切记不要放在src/main/resources/或src/main/java/下——Web 容器只从WEB-INF/lib加载运行时依赖。方式二Maven 依赖需修改 pom.xmldependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId version8.0.33/version scoperuntime/scope !-- 关键不能是 compile否则打包时会冗余 -- /dependency此时需在Project Structure → Artifacts → your-war-exploded → Output Layout中右键WEB-INF/lib→From Maven确保 jar 被正确导出。逻辑说明scoperuntime表示该依赖仅在运行时需要编译期不需要。若误写为compileMaven 会把它打进 war 包但 Tomcat 本身已内置部分 JDBC 类可能引发ClassCastException。3. 数据库设计与连接MySQL 8 下的字符集、时区与连接池避坑指南3.1 创建图书数据库字符集必须用 utf8mb4Collation 选 utf8mb4_unicode_ci执行以下 SQL在 MySQL Workbench 或命令行CREATE DATABASE book_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; USE book_db; CREATE TABLE books ( id INT PRIMARY KEY AUTO_INCREMENT, title VARCHAR(100) NOT NULL, author VARCHAR(50) NOT NULL, isbn VARCHAR(20) UNIQUE, publish_date DATE, price DECIMAL(8,2), create_time DATETIME DEFAULT CURRENT_TIMESTAMP );参数说明utf8mb4支持 emoji 和生僻汉字如“龘”utf8mb4_unicode_ci排序更准确publish_date用DATE类型而非VARCHAR避免后续日期查询失效create_time设DEFAULT CURRENT_TIMESTAMP由数据库自动生成减少 Java 层拼接时间字符串的麻烦。3.2 JDBC 连接 URLMySQL 8 必须加 serverTimezone 和 allowPublicKeyRetrieval在src/main/java/utils/DBUtil.java中连接字符串必须包含private static final String URL jdbc:mysql://localhost:3306/book_db? useUnicodetruecharacterEncodingutf8mb4 serverTimezoneAsia/Shanghai // 关键否则 datetime 字段读取为 null allowPublicKeyRetrievaltrue // MySQL 8.0.28 必加否则抛 SQLException useSSLfalse; // 本地开发关闭 SSL简化配置逻辑说明serverTimezoneAsia/Shanghai解决时区错位问题——MySQL 默认用系统时区Java 用 JVM 时区两者不一致会导致ResultSet.getDate()返回nullallowPublicKeyRetrievaltrue是 MySQL 8.0.28 后强制要求的安全参数跳过公钥交换流程否则连接直接失败。3.3 手写简易连接池不用 Druid/HikariCP用静态单例 连接复用大二作业无需复杂连接池一个线程安全的静态单例足够public class DBUtil { private static Connection connection null; static { try { Class.forName(com.mysql.cj.jdbc.Driver); // MySQL 8 驱动类名 connection DriverManager.getConnection(URL, root, your_password); } catch (Exception e) { e.printStackTrace(); } } public static Connection getConnection() { return connection; // 直接返回不每次都 new降低开销 } }注意此写法适用于单用户本地调试。若需多用户并发必须改为ThreadLocalConnection或引入真实连接池但大二作业场景下静态连接已满足需求且便于理解底层机制。4. 核心功能实现Servlet 处理请求、DAO 封装操作、JSP 渲染页面的三层协作4.1 查询所有图书从 index.jsp 发起 GET 请求经 BookListServlet 返回数据index.jsp首页入口% page contentTypetext/html;charsetUTF-8 languagejava % html headtitle图书管理系统/title/head body h2图书列表/h2 a hrefadd.jsp添加新书/a | a hrefBookListServlet刷新列表/a brbr table border1 trthID/thth书名/thth作者/ththISBN/thth出版日期/thth价格/thth操作/th/tr % ListBook books (ListBook) request.getAttribute(bookList); if (books ! null !books.isEmpty()) { for (Book book : books) { % tr td% book.getId() %/td td% book.getTitle() %/td td% book.getAuthor() %/td td% book.getIsbn() %/td td% book.getPublishDate() %/td td% book.getPrice() %/td td a hrefBookDetailServlet?id% book.getId() %详情/a | a hrefBookDeleteServlet?id% book.getId() %删除/a /td /tr % }} else { % trtd colspan7暂无图书/td/tr % } % /table /body /html逻辑说明JSP 中通过request.getAttribute(bookList)获取 Servlet 设置的数据不是 session 或 application% %输出表达式必须确保Book类的 getter 方法返回非 null 值如publishDate为java.sql.Date需在toString()中格式化否则输出2023-01-01而非2023-01-01。4.2 BookListServlet接收请求、调用 DAO、转发到 JSPWebServlet(/BookListServlet) public class BookListServlet extends HttpServlet { Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { ListBook bookList new BookDAO().findAll(); // 调用 DAO 层 req.setAttribute(bookList, bookList); // 绑定到 request 域 req.getRequestDispatcher(index.jsp).forward(req, resp); // 转发保持 URL 不变 } }参数说明WebServlet(/BookListServlet)注解替代web.xml配置但大二作业建议仍用web.xml课程要求此处仅为演示forward()是服务器端跳转URL 地址栏不变适合 MVC 模式若用sendRedirect()URL 会变且 request 属性丢失。4.3 BookDAO封装 JDBC 操作PreparedStatement 防 SQL 注入public class BookDAO { public ListBook findAll() { ListBook list new ArrayList(); String sql SELECT id, title, author, isbn, publish_date, price FROM books; try (Connection conn DBUtil.getConnection(); PreparedStatement ps conn.prepareStatement(sql); ResultSet rs ps.executeQuery()) { while (rs.next()) { Book book new Book(); book.setId(rs.getInt(id)); book.setTitle(rs.getString(title)); book.setAuthor(rs.getString(author)); book.setIsbn(rs.getString(isbn)); book.setPublishDate(rs.getDate(publish_date)); // 自动转换为 java.util.Date book.setPrice(rs.getBigDecimal(price).doubleValue()); // BigDecimal → double list.add(book); } } catch (SQLException e) { e.printStackTrace(); } return list; } }逻辑说明使用try-with-resources自动关闭Connection/PreparedStatement/ResultSet避免连接泄漏rs.getDate(publish_date)返回java.sql.Date可直接赋值给Book类的java.util.Date字段JDK 8 兼容getBigDecimal().doubleValue()避免float精度丢失比rs.getFloat()更稳妥。5. 避坑指南大二作业中最常翻车的 5 个问题及血泪解决方案5.1 现象浏览器访问http://localhost:8080/book/显示 404但 Tomcat 控制台无报错原因web.xml中welcome-file-list未配置index.jsp或index.jsp不在webapp/根目录下。解决检查webapp/目录结构确保index.jsp与WEB-INF同级在web.xml中添加welcome-file-list welcome-fileindex.jsp/welcome-file /welcome-file-list5.2 现象添加图书后页面跳转到add.jsp但表单提交报 404URL 变成http://localhost:8080/add.jsp缺少 context path原因add.jsp中表单action写死为add.jsp或/add.jsp未带应用上下文。解决改为相对路径或 EL 表达式form action${pageContext.request.contextPath}/BookAddServlet methodpost或用 JSTL需引入c:url value/BookAddServlet varaddUrl/ form action${addUrl} methodpost5.3 现象MySQL 插入中文显示为??数据库字段存的是乱码原因MySQL 服务端、数据库、表、连接 URL 四层字符集不统一常见是 URL 缺characterEncodingutf8mb4。解决四步检查①SHOW VARIABLES LIKE character_set%;确认服务端为utf8mb4②SHOW CREATE DATABASE book_db;确认库字符集③SHOW CREATE TABLE books;确认表字符集④ JDBC URL 必须含characterEncodingutf8mb4。5.4 现象BookDetailServlet通过request.getParameter(id)获取不到值始终为 null原因HTML 中a hrefBookDetailServlet?id% book.getId() %的id参数名与 Servlet 中req.getParameter(id)的字符串完全匹配但大小写敏感或空格干扰。解决在 Servlet 开头加日志System.out.println(Received id param: [ req.getParameter(id) ]);若输出[null]检查 URL 是否被浏览器自动编码如id1变成id%3D1此时应检查链接生成逻辑禁止在 href 中拼接符号以外的特殊字符。5.5 现象Tomcat 启动时报java.lang.ClassNotFoundException: javax.servlet.http.HttpServlet原因IDEA 未将 Servlet API 加入编译依赖或 Tomcat 版本与 Servlet 规范不匹配如用 Tomcat 9 但web.xml声明version2.5。解决①Project Structure → Modules → Dependencies点击 → Library → Java选择 Tomcat 安装目录下的lib/servlet-api.jar②web.xml根标签必须为web-app xmlnshttp://xmlns.jcp.org/xml/ns/javaee xmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xsi:schemaLocationhttp://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd version4.06. 进阶技巧让作业脱颖而出的 3 个低成本优化点附可抄代码6.1 用 Filter 统一处理中文乱码避免每个 Servlet 都写request.setCharacterEncoding(UTF-8)创建EncodingFilter.javaWebFilter(/*) public class EncodingFilter implements Filter { Override public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { HttpServletRequest request (HttpServletRequest) req; HttpServletResponse response (HttpServletResponse) resp; request.setCharacterEncoding(UTF-8); response.setContentType(text/html;charsetUTF-8); chain.doFilter(request, response); } }逻辑说明WebFilter(/*)拦截所有请求必须放在web.xml或使用注解启用chain.doFilter()是关键漏写会导致请求中断此 Filter 替代了在每个 Servlet 中重复设置编码的繁琐操作且对 POST/GET 请求均生效GET 乱码需额外在 Tomcatconf/server.xml的Connector中加URIEncodingUTF-8。6.2 用 JSTL 替代 scriptlet让 JSP 更干净老师一眼看出你懂规范先在pom.xml引入dependency groupIdjavax.servlet/groupId artifactIdjstl/artifactId version1.2/version /dependency然后在index.jsp顶部加% taglib prefixc urihttp://java.sun.com/jsp/jstl/core %替换原 JSP 中的 Java 代码块c:if test${empty bookList} trtd colspan7暂无图书/td/tr /c:if c:forEach items${bookList} varbook tr td${book.id}/td td${book.title}/td td${book.author}/td td${book.isbn}/td td${book.publishDate}/td td${book.price}/td td a href${pageContext.request.contextPath}/BookDetailServlet?id${book.id}详情/a | a href${pageContext.request.contextPath}/BookDeleteServlet?id${book.id}删除/a /td /tr /c:forEach优势EL 表达式${book.title}比% book.getTitle() %更简洁c:forEach替代 for 循环无 scriptlet符合 JSP 2.0 最佳实践pageContext.request.contextPath自动获取应用路径避免硬编码。6.3 用 Bootstrap 快速美化界面3 行代码接入 CDN告别原始 HTML 表格在index.jsphead中加入link hrefhttps://cdn.jsdelivr.net/npm/bootstrap5.3.3/dist/css/bootstrap.min.css relstylesheet script srchttps://cdn.jsdelivr.net/npm/bootstrap5.3.3/dist/js/bootstrap.bundle.min.js/script然后将表格改为 Bootstrap 样式table classtable table-striped table-hover thead classtable-dark trthID/thth书名/thth作者/ththISBN/thth出版日期/thth价格/thth操作/th/tr /thead tbody !-- c:forEach 循环体不变 -- /tbody /table效果响应式表格、悬停高亮、斑马纹、深色表头5 分钟提升作业颜值CDN 加载无需下载文件适合快速交付所有样式类名均为 Bootstrap 5 标准兼容性好。我带过大二 JavaWeb 实验课三年每年都有学生卡在web.xml版本声明或contextPath拼写上熬通宵。后来我把这些坑整理成 checklist 打印出来贴在实验室墙上再没人因为404去重装 Tomcat。真正的练手项目不在于功能多炫而在于每一步都踩在技术栈的真实断层上——图书管理系统就是那道最合适的门槛。希望帮到你。本文还有配套的精品资源点击获取

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

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

免费获取报价 →
↑