ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

JavaWeb图书管理系统:Tomcat9+MySQL8事务权限实战

JavaWeb图书管理系统:Tomcat9+MySQL8事务权限实战 简介本资源是一套完整、高分的JavaWeb图书管理系统毕业设计项目面向计算机专业本科生及Java初学者解决课程设计、期末大作业与毕业设计选题难、实现难、文档缺等实际问题。压缩包共352个文件含37个核心Java源码、91个可运行class字节码、91个依赖jar包、41个Excel模板用于数据导入导出、14个HTML页面、13个CSS样式与12个JS交互脚本辅以SQL建表语句、XML配置、JSP视图及多张PNG/JPG界面截图整体64.79MB结构清晰、模块分明涵盖用户管理、图书维护、借阅统计、Excel批量操作等完整业务链。已有544人学习下载代码全程手写并附详尽中文注释配套文档说明部署步骤与功能逻辑开箱即用——解压后导入IDE、配置数据库、启动Tomcat即可运行特别适合零基础学生快速理解MVC分层架构与Web开发全流程。1. 这不是“又一个JavaWeb课程设计”它是一套能跑在Tomcat 9MySQL 8上的、带完整事务控制和角色权限分离的图书管理闭环系统你搜“JavaWeb图书管理系统”满屏是2015年写的JSPServlet老古董连数据库连接都用Class.forName硬编码部署到Tomcat 9直接报java.sql.SQLException: Unknown system variable query_cache_size或者更糟——用IDEA新建项目时卡在“Add Framework Support”里死循环根本加不上Servlet API。但这个标题里的“高分项目”真正在意的是三件事第一它必须绕过所有被废弃的API比如javax.servlet.http.HttpServletRequest.getRealPath()第二它把借阅/归还这种典型业务封装成原子事务不是简单写个INSERT就完事第三文档不是Word截图堆砌而是用PlantUML画出真实调用链路连DAO层SQL参数绑定顺序都标得清清楚楚。适合两类人大三学生赶毕设答辩要求3天内本地跑通能改数据库字段、刚转Java的后端新人想补Web开发肌肉记忆从web.xml配置到Filter拦截器怎么写。别信“源码文档开箱即用”——真正能落地的是它把Tomcat部署路径、MySQL时区、JDBC驱动版本这些玄学参数全列在README.md第一页。2. 从零启动用IDEA 2023.3 Tomcat 9.0.87 MySQL 8.0.33搭出可运行环境2.1 创建Maven Web项目避开IDEA的“Add Framework Support”陷阱很多新手卡在第一步右键项目 → Add Framework Support → 勾选Web Application → 点OK → 报错“No web.xml found”。这不是你操作错是IDEA默认生成的web.xml路径不对。正确做法是手动创建标准目录结构src/main/java # 存放Servlet、DAO、Service类 src/main/webapp # 存放JSP、HTML、WEB-INF/web.xml src/main/resources # 存放db.properties、log4j2.xml提示不要用IDEA的“New Project → Maven → Web Application”向导它会生成过时的archetype如maven-archetype-webapp导致webapp目录被建在src/main/webapp之外。直接用“New Project → Empty Project”再手动建上述三个目录。接着在pom.xml里声明核心依赖——注意版本必须匹配否则Tomcat启动时会因Servlet API冲突直接退出properties maven.compiler.source1.8/maven.compiler.source maven.compiler.target1.8/maven.compiler.target project.build.sourceEncodingUTF-8/project.build.sourceEncoding /properties dependencies !-- Servlet API必须用4.0.1Tomcat 9.0.x对应此版本 -- dependency groupIdjavax.servlet/groupId artifactIdjavax.servlet-api/artifactId version4.0.1/version scopeprovided/scope /dependency !-- JSP支持Tomcat 9自带Jasper只需声明依赖 -- dependency groupIdjavax.servlet.jsp/groupId artifactIdjavax.servlet.jsp-api/artifactId version2.3.3/version scopeprovided/scope /dependency !-- MySQL驱动必须用8.0.28否则连MySQL 8.0.33会报时区错误 -- dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId version8.0.28/version /dependency !-- 数据库连接池HikariCP比DBCP快3倍且自动处理MySQL 8的SSL握手 -- dependency groupIdcom.zaxxer/groupId artifactIdHikariCP/artifactId version5.0.1/version /dependency !-- 日志Log4j2替代log4j避免CVE-2021-44228 -- dependency groupIdorg.apache.logging.log4j/groupId artifactIdlog4j-core/artifactId version2.20.0/version /dependency dependency groupIdorg.apache.logging.log4j/groupId artifactIdlog4j-slf4j-impl/artifactId version2.20.0/version /dependency /dependencies关键点说明scopeprovided/scope表示Servlet/JSP API由Tomcat提供打包时剔除否则WAR包会因重复类加载失败MySQL驱动版本低于8.0.28会导致The server time zone value UTC is unrecognized错误必须升级HikariCP的autoCommitfalse默认值能保证后续借阅事务不被意外提交。2.2 配置Tomcat 9解决“HTTP Status 404 – Not Found”的根源404不是代码问题90%是Tomcat部署路径没对齐。在IDEA中配置Run Configuration时必须手动指定Application context为/book不是默认的/因为项目所有URL都基于此路径设计如登录页是/book/login.jsp。步骤如下点击右上角Edit Configurations...→ 左侧选中你的Tomcat Server在Deployment标签页 → 点击→Artifact→ 选择book:war exploded关键一步在Application context输入框填/book注意开头有斜杠结尾无斜杠切换到Server标签页 →VM options添加-Dfile.encodingUTF-8避免中文乱码On ‘Update’ action选Update classes and resources热更新才生效。注意如果跳过第3步浏览器访问http://localhost:8080/login.jsp永远404因为实际路径是http://localhost:8080/book/login.jsp。这是本项目文档里明确写的部署约定不是BUG。2.3 初始化MySQL 8绕过密码认证插件和时区坑MySQL 8默认用caching_sha2_password插件而旧版JDBC驱动不兼容。执行以下SQL重置root密码并切换插件-- 登录MySQL后执行 ALTER USER rootlocalhost IDENTIFIED WITH mysql_native_password BY your_password; FLUSH PRIVILEGES;接着创建图书库并授权CREATE DATABASE book_system CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE USER book_userlocalhost IDENTIFIED BY book123; GRANT ALL PRIVILEGES ON book_system.* TO book_userlocalhost; FLUSH PRIVILEGES;最关键的一步修改MySQL配置文件my.cnfLinux在/etc/mysql/my.cnfWindows在C:\ProgramData\MySQL\MySQL Server 8.0\my.ini在[mysqld]段添加default-time-zone 08:00 character-set-serverutf8mb4 collation-serverutf8mb4_unicode_ci重启MySQL后用SELECT time_zone;确认返回08:00。否则new Date()插入时间会比系统时间慢8小时借阅记录的时间戳全错。3. 核心业务落地借阅/归还事务如何用JDBC原生实现而不翻车3.1 为什么不用Spring——本项目用纯JDBC手写事务的底层逻辑高分项目评审最看重“是否理解事务本质”。Spring的Transactional像黑匣子而本项目在BookService.java里用Connection.setAutoCommit(false)显式控制代码直白到能背下来public boolean borrowBook(int userId, int bookId) throws SQLException { Connection conn null; PreparedStatement ps1 null, ps2 null; try { conn DataSourceUtil.getConnection(); // HikariCP获取连接 conn.setAutoCommit(false); // 关键关闭自动提交 // 步骤1检查图书库存 ps1 conn.prepareStatement(SELECT stock FROM books WHERE id ?); ps1.setInt(1, bookId); ResultSet rs ps1.executeQuery(); if (!rs.next() || rs.getInt(stock) 0) { throw new SQLException(图书库存不足); } // 步骤2扣减库存 ps2 conn.prepareStatement(UPDATE books SET stock stock - 1 WHERE id ?); ps2.setInt(1, bookId); ps2.executeUpdate(); // 步骤3插入借阅记录 PreparedStatement ps3 conn.prepareStatement( INSERT INTO borrow_records (user_id, book_id, borrow_date) VALUES (?, ?, ?)); ps3.setInt(1, userId); ps3.setInt(2, bookId); ps3.setDate(3, new java.sql.Date(System.currentTimeMillis())); ps3.executeUpdate(); conn.commit(); // 所有操作成功才提交 return true; } catch (SQLException e) { if (conn ! null) conn.rollback(); // 任一环节失败回滚 throw e; } finally { // 必须关闭所有资源否则连接池耗尽 if (ps1 ! null) ps1.close(); if (ps2 ! null) ps2.close(); if (conn ! null) conn.close(); } }逻辑说明setAutoCommit(false)是事务起点之后所有SQL都在同一事务上下文rollback()必须在catch块里显式调用否则异常后连接仍处于未提交状态下次获取连接会继承脏状态close()放在finally里但注意conn.close()实际是归还连接到HikariCP池不是物理断开。3.2 角色权限分离用Filter实现管理员/普通用户路由拦截权限不是靠if-else判断URL而是用LoginFilter.java统一拦截public class LoginFilter implements Filter { Override public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { HttpServletRequest request (HttpServletRequest) req; HttpServletResponse response (HttpServletResponse) resp; String uri request.getRequestURI(); // 放行静态资源和登录页 if (uri.contains(/css/) || uri.contains(/js/) || uri.equals(/book/login.jsp) || uri.equals(/book/LoginServlet)) { chain.doFilter(req, resp); return; } // 检查Session是否存在 HttpSession session request.getSession(false); if (session null || session.getAttribute(user) null) { response.sendRedirect(request.getContextPath() /login.jsp); return; } // 角色校验管理员可访问所有普通用户禁止访问/admin/ User user (User) session.getAttribute(user); if (uri.startsWith(/book/admin/) !admin.equals(user.getRole())) { response.sendError(HttpServletResponse.SC_FORBIDDEN, 无权访问管理员页面); return; } chain.doFilter(req, resp); } }在web.xml中注册filter filter-nameLoginFilter/filter-name filter-classfilter.LoginFilter/filter-class /filter filter-mapping filter-nameLoginFilter/filter-name url-pattern/book/*/url-pattern /filter-mapping参数说明url-pattern必须是/book/*因为Tomcat部署context是/book否则Filter不生效SC_FORBIDDEN返回403而非重定向避免普通用户通过修改URL绕过session.getAttribute(user)存储的是User对象含id、name、role字段不是字符串所以能直接取getRole()。4. 避坑指南这5个错误让90%的人卡在部署前30分钟4.1 现象Tomcat启动成功但访问http://localhost:8080/book/login.jsp报404原因IDEA中Tomcat的Application context没设成/book或web.xml里welcome-file-list没配login.jsp。解决检查Run Configuration → Deployment → Application context是否为/book确认src/main/webapp/WEB-INF/web.xml存在且包含welcome-file-list welcome-filelogin.jsp/welcome-file /welcome-file-list4.2 现象登录时抛java.lang.ClassNotFoundException: com.mysql.cj.jdbc.Driver原因MySQL驱动版本与JDBC URL格式不匹配。MySQL 8必须用com.mysql.cj.jdbc.Driver且URL要加serverTimezoneGMT%2B8。解决db.properties中写drivercom.mysql.cj.jdbc.Driver urljdbc:mysql://localhost:3306/book_system?useUnicodetruecharacterEncodingUTF-8serverTimezoneGMT%2B8 usernamebook_user passwordbook123确保pom.xml里MySQL驱动版本≥8.0.28。4.3 现象借阅成功后图书库存没减少或出现负数原因事务没生效或UPDATE语句没加WHERE id ?条件导致全表扣减。解决检查BookService.borrowBook()里conn.setAutoCommit(false)是否在try块外用MySQL命令行执行SELECT * FROM books WHERE id 1;确认原始库存再借阅一次后立刻查看是否变化若库存变负数说明UPDATE语句漏了WHERE应为UPDATE books SET stock stock - 1 WHERE id ?。4.4 现象中文显示为??日志里全是方块原因Tomcat、MySQL、IDEA三端编码不一致。解决Tomcatconf/server.xml中Connector标签加URIEncodingUTF-8MySQLmy.cnf里[client]和[mysqld]段都加default-character-setutf8mb4IDEAFile → Settings → Editor → File Encodings→ 全部设为UTF-8。4.5 现象管理员登录后点击“用户管理”跳转到空白页控制台无报错原因JSP里用了EL表达式${userList}但web.xml没声明Servlet 3.0版本导致EL被忽略。解决src/main/webapp/WEB-INF/web.xml第一行必须是?xml version1.0 encodingUTF-8? 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.0版本号4.0对应Servlet 4.0EL表达式才启用。5. 文档说明的实战价值如何用PlantUML把“借阅流程”画成可执行的时序图5.1 不是截图是PlantUML源码文档里真正该有的东西很多所谓“文档说明”就是Word里贴10张IDEA界面截图。而本项目的docs/sequence_diagram.puml是可编译的PlantUML代码打开就能看到借阅全流程startuml title 图书借阅时序图 actor 用户 participant LoginServlet as login participant BookService as service participant BookDAO as dao database MySQL as db 用户 - login: POST /login login - service: checkUser(username, password) service - dao: findByUsername(username) dao - db: SELECT * FROM users WHERE name ? db -- dao: 返回User对象 dao -- service: 返回User service -- login: 返回User或null login -- 用户: 重定向到/home.jsp 或 login.jsp 用户 - service: borrowBook(userId, bookId) service - db: BEGIN TRANSACTION service - db: SELECT stock FROM books WHERE id ? db -- service: 返回stock值 service - db: UPDATE books SET stock stock - 1 WHERE id ? service - db: INSERT INTO borrow_records ... db -- service: COMMIT service -- 用户: 返回true enduml生成方式安装PlantUML插件IntelliJ IDEA Marketplace搜“PlantUML Integration”右键.puml文件 →Export Diagrams→ 输出PNG/PDF。这张图的价值在于它和BookService.borrowBook()方法1:1对应每行代码都能在图中找到位置BEGIN TRANSACTION标注提醒你事务起点避免在DAO层误加conn.commit()SELECT stock和UPDATE之间没有其他SQL证明库存检查与扣减是原子操作。5.2 数据库ER图用MySQL Workbench反向工程导出真实结构文档里docs/er_diagram.png不是手绘而是用MySQL Workbench连接book_system后Database → Reverse Engineer自动生成。关键字段含义必须标注表名字段类型说明usersroleVARCHAR(10)取值admin/userFilter据此拦截booksstockINT NOT NULL DEFAULT 0库存为0时借阅失败前端禁用按钮borrow_recordsstatusTINYINT(1) DEFAULT 00已借出1已归还归还时UPDATE此字段提示status字段用TINYINT而非ENUM因为Java JDBC读取ENUM需要额外类型映射而getInt(status)直接返回0/1省去转换成本。5.3 高分答辩话术如何30秒讲清技术选型理由评委最常问“为什么不用Spring Boot”——别背概念用对比数据说话维度Spring Boot方案本项目方案你的回答启动时间3.2秒含自动配置扫描0.8秒手动注入“毕设演示只有5分钟省2.4秒能多演1次借阅流程”WAR包大小18MB含所有starter4.2MB仅需HikariCPLog4j2“部署到学校服务器带宽有限小包上传更快”事务可见性Transactional注解黑盒conn.commit()/rollback()明文“答辩时能现场debug事务边界证明理解ACID”最后收尾那句我常对学生说“别把文档当作业交把它当你的技术简历——评委扫一眼ER图和时序图就知道你是不是真写过代码。”希望帮到你。本文还有配套的精品资源点击获取
返回列表