ARTICLE DETAIL

资讯详情

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

Java Web毕设实战:JSP+Servlet+SQL Server车辆管理系统部署与事务详解

Java Web毕设实战:JSP+Servlet+SQL Server车辆管理系统部署与事务详解 简介这是一套面向计算机专业本科生的毕业设计实战项目资源聚焦住宅小区车辆管理业务场景基于Java Web技术栈实现完整B/S架构系统。资源包含可直接运行的JSP源码、SQL Server数据库脚本、JDK 1.8环境工具包及同框架项目的详细安装教程覆盖用户中心、车辆进出、车位预定、管理员权限等8大核心模块适合课程设计、毕设开发与Web全栈技能巩固。压缩包共638个文件以43个JSP页面、34个Java类、35个Class编译文件、272个GIF/PNG/JPG界面素材及30个JS/CSS前端资源为主辅以SQL脚本、配置文件与AVI操作演示视频整体23.01MB结构清晰便于分层学习与二次开发。目前已有117人下载学习配套说明文档详述部署流程视频直观展示系统功能是少有的含完整前后端数据库实操录屏的毕业设计闭环方案。1. 这不是又一个“JavaJSPSQL Server”套壳项目它真能跑通小区车辆进出登记、车位状态联动、超时自动预警这三件实事你搜“毕业设计 javajsp 住宅小区车辆管理系统”页面刷出来上百个同名压缩包点开全是login.jspweb.xmlsqlserver.bak的三件套——但真正能插上U盘、配好驱动、连上本地 SQL Server 2019、在浏览器里输入http://localhost:8080/carmanage/login.jsp后手动录入一辆车牌号、选择入口闸机、点击提交5秒内看到数据库t_car_record表里多出一条带时间戳和status1的记录且后台t_parking_space表对应车位is_occupied1实时更新的不到3%。这个qlkrp源码包就是那3%里的实战组合它没用 Spring Boot 做遮羞布没靠 Tomcat 9 自带 JSP 编译器硬扛而是用JSP 内置 JavaBean Servlet 手动事务控制 SQL Server 2012 兼容型 T-SQL把“车辆进→车位锁→超时告警→人工核验→车辆出→车位释放”这条业务链压进 7 个核心 JSP 页面、4 个关键 Servlet 和 12 张表结构里。它不教你怎么写简历但能让你答辩时当场演示凌晨2:17分系统自动查出京AXXXXX 在地下B2区停了73小时弹窗提醒物业值班员并生成report_timeout_20240521.csv下载链接。适合需要快速验证业务逻辑闭环、拒绝“启动成功即交付”的本科毕设同学也适合想拆解传统 Web 层事务边界的 Java 初级开发者——你得亲手改CarRecordServlet.java里的con.setAutoCommit(false)才能理解为什么“登记成功但车位没锁住”这种翻车从来不是前端按钮没点而是 JDBC 事务没兜住。2. 从零部署用最朴素的 JDK8 Tomcat8.5 SQL Server 2012 SP4 跑通核心流程这个源码包的生存逻辑是向后兼容而非向前炫技。它不依赖 Maven 多模块、不调用 MyBatis 动态 SQL、不走 RESTful API 抽象层所有数据操作直击 JDBC Statement 和 ResultSet。这意味着你不需要装 IntelliJ IDEA Ultimate 版不用配 Lombok 插件甚至不用碰pom.xml——只要确保三件套版本对齐就能在 Windows 10 家庭版上跑起来。下面步骤按真实实验室环境无管理员权限、无 Docker、无云服务器设计每步都卡过我三次以上。2.1 SQL Server 环境准备避开“服务启动失败”和“sa密码被拒”两大玄学坑提示别用 SQL Server 2022 或 Express 版本。qlkrp的建库脚本car_db.sql里含FILEGROUP分区定义和TEXTIMAGE_ON子句Express 版默认禁用这些特性2022 版则因datetime2默认精度变更导致t_car_record.in_time字段插入时抛SqlException: Conversion failed when converting date and/or time from character string。实测稳定组合是SQL Server 2012 SP4版本号 11.0.7493.4 Windows Authentication 模式。先确认服务已启动# 以管理员身份运行 cmd执行 sc query MSSQLSERVER # 若 STATE 为 4 RUNNING则继续若为 1 STOPPED执行 net start MSSQLSERVER再用 SQL Server Management Studio (SSMS) 连接localhost用 Windows 身份认证登录。关键动作右键服务器 → “属性” → “安全性” → 确保“SQL Server 和 Windows 身份验证模式”已勾选 → 点击“确定”后必须重启 SQL Server 服务net stop MSSQLSERVER net start MSSQLSERVER否则 sa 账户永远无法启用。接着执行建库脚本注意路径-- 打开 SSMS 新建查询粘贴并执行 car_db.sql 全文 -- 特别注意第 12 行CREATE DATABASE car_db ON PRIMARY (NAME car_db_data, FILENAME D:\car_db\car_db.mdf) -- 如果你的 D 盘没有 car_db 文件夹请提前手动创建否则建库直接报错 -- 执行完后在“对象资源管理器”中展开“数据库”确认 car_db 已存在最后配 sa 账户毕设答辩演示必须用密码登录-- 在 car_db 数据库下执行 ALTER LOGIN sa ENABLE; GO ALTER LOGIN sa WITH PASSWORD Qlkrp2024; GO -- 再次右键服务器 → “属性” → “连接” → 勾选“允许远程连接到此服务器” -- 重启服务生效2.2 Tomcat 与 JDK 配置为什么java.lang.UnsupportedClassVersionError总在答辩前两小时出现qlkrp的WEB-INF/classes下.class文件编译目标是1.8即 JDK8但很多同学用 JDK17 启动 Tomcat导致org.apache.jasper.JasperException: Unable to compile class for JSP。不要卸载 JDK17只需指定 Tomcat 使用 JDK8下载jdk-8u202-windows-x64.exeOracle 官网归档页可得安装到C:\Program Files\Java\jdk1.8.0_202修改tomcat/bin/setenv.bat若不存在则新建echo off set JAVA_HOMEC:\Program Files\Java\jdk1.8.0_202 set JRE_HOME%JAVA_HOME%\jre启动tomcat/bin/startup.bat观察控制台首行是否输出Using JAVA_HOME: C:\Program Files\Java\jdk1.8.0_202若仍报错检查tomcat/conf/catalina.properties中java.endorsed.dirs是否指向旧 JDK 的jre/lib/endorsed删掉该行或注释掉。2.3 部署 WAR 包别信“直接拖进 webapps 就行”context.xml里藏着数据库密码明文qlkrp源码包解压后是carmanage/目录不是标准 WAR。需手动构建成 WAR 并注入数据库配置用记事本打开carmanage/META-INF/context.xml修改Resource标签Resource namejdbc/carDB authContainer typejavax.sql.DataSource maxActive20 maxIdle10 minIdle5 usernamesa passwordQlkrp2024 !-- 此处必须和上一步设置的 sa 密码一致 -- driverClassNamecom.microsoft.sqlserver.jdbc.SQLServerDriver urljdbc:sqlserver://localhost:1433;databaseNamecar_db;encryptfalse;trustServerCertificatetrue;/用 WinRAR 选中carmanage/全目录 → 右键“添加到压缩文件” → 压缩格式选“ZIP” → 修改后缀为.war如carmanage.war将carmanage.war拖入tomcat/webapps/等待自动解压约 20 秒观察tomcat/logs/catalina.out是否出现INFO [main] org.apache.catalina.startup.HostConfig.deployWAR Deploying web application archive [D:\tomcat\webapps\carmanage.war]若无此日志说明 WAR 包结构错误——检查carmanage/WEB-INF/web.xml是否存在且web-app根标签 version2.5不是 3.0 或 4.02.4 验证核心链路用三组测试数据打穿“进-停-出”闭环启动成功后访问http://localhost:8080/carmanage/login.jsp账号admin密码123456。立即执行以下三步验证每步必须看到数据库实时变化车辆入场登记进入“车辆登记”页 → 车牌号填京A12345→ 入口闸机选东门1号→ 点击“登记”查t_car_record表plate_number京A12345 AND status1 AND in_time IS NOT NULL查t_parking_space表space_codeB2-001 AND is_occupied1系统默认分配首个空闲车位超时预警触发手动修改t_car_record中京A12345的in_time为2024-05-20 10:00:00模拟停放超 24 小时访问http://localhost:8080/carmanage/servlet/TimeoutCheckServlet这是独立预警接口非页面跳转查t_warning_log表新增一条warning_typeOVER_TIME AND plate_number京A12345 AND status0车辆出场核销返回“车辆登记”页 → 输入京A12345→ 点击“出场”按钮查t_car_recordout_time字段被填入当前时间status2查t_parking_spaceB2-001的is_occupied变回0注意若第2步访问TimeoutCheckServlet返回 404说明web.xml中 servlet-mapping 未生效。检查carmanage/WEB-INF/web.xml第 87 行url-pattern/servlet/TimeoutCheckServlet/url-pattern是否与TimeoutCheckServlet.java的WebServlet(/servlet/TimeoutCheckServlet)严格一致大小写、斜杠都不能错。3. 代码层深挖JSP 如何用 JavaBean 绑定表单、Servlet 怎样手动控制事务边界qlkrp的技术诚实性体现在它没用任何框架掩盖 JDBC 底层细节。它的CarRecordServlet.java是整个系统的事务心脏——所有“登记锁位”、“出场解锁”操作都包裹在同一个Connection的setAutoCommit(false)里。这意味着如果INSERT INTO t_car_record成功但UPDATE t_parking_space SET is_occupied1失败整个事务会回滚不会留下“车进了但车位没锁”的脏数据。这种写法在 Spring Boot 时代显得笨重但在毕设答辩现场它让你能指着代码说“老师这里con.rollback()就是防止数据不一致的后悔药”。3.1 JSP 表单与 JavaBean 的双向绑定为什么request.getParameter(plate)不如jsp:useBean可靠add_record.jsp里没用原生request.getParameter()获取表单值而是通过 JavaBean 封装!-- add_record.jsp 片段 -- jsp:useBean idcar classbean.CarBean scopepage/ jsp:setProperty property* namecar/ !-- 后续在 Servlet 中直接 getCar() 即可 --对应的bean/CarBean.javapublic class CarBean { private String plateNumber; private String gateName; private String inTime; // getter/setter 省略... }为什么这样写因为jsp:setProperty property*会自动将所有 request 参数名如plateNumber,gateName映射到同名 Bean 属性避免手写 10 行request.getParameter()且漏掉空值校验。更重要的是当用户输入plateNumber 京A12345 带空格时CarBean的 setter 方法可内置 trimpublic void setPlateNumber(String plateNumber) { this.plateNumber plateNumber null ? : plateNumber.trim(); }而原生request.getParameter(plateNumber).trim()若参数为空会抛NullPointerException必须层层判空——毕设代码里少一个if (xxx ! null)答辩时就可能被问“如果用户不填车牌号系统怎么处理”。3.2 Servlet 中的手动事务控制con.setAutoCommit(false)后的三道生死线CarRecordServlet.java的doPost方法是事务核心关键代码如下protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { Connection con null; PreparedStatement ps1 null, ps2 null; try { con DBUtil.getConnection(); // 获取连接池中的 Connection con.setAutoCommit(false); // 【第一道生死线】关闭自动提交 // 步骤1插入车辆记录 ps1 con.prepareStatement(INSERT INTO t_car_record(...) VALUES(?, ?, ?, ?)); ps1.setString(1, car.getPlateNumber()); ps1.setString(2, car.getGateName()); ps1.setTimestamp(3, new Timestamp(System.currentTimeMillis())); ps1.setInt(4, 1); ps1.executeUpdate(); // 步骤2更新车位状态关键此处可能因车位满而失败 ps2 con.prepareStatement(UPDATE t_parking_space SET is_occupied1 WHERE space_code?); ps2.setString(1, getAvailableSpace()); // 从 t_parking_space 查第一个 is_occupied0 的 space_code int rows ps2.executeUpdate(); if (rows 0) { // 【第二道生死线】查无空闲车位主动抛异常触发回滚 throw new SQLException(No available parking space!); } con.commit(); // 【第三道生死线】全部成功才提交 request.setAttribute(msg, 登记成功); } catch (SQLException e) { if (con ! null) { try { con.rollback(); // 关键回滚所有操作 } catch (SQLException ex) { ex.printStackTrace(); } } request.setAttribute(msg, 登记失败 e.getMessage()); } finally { DBUtil.close(ps1, ps2, con); // 必须关闭否则连接池耗尽 } request.getRequestDispatcher(add_record.jsp).forward(request, response); }参数说明与踩坑点DBUtil.getConnection()返回的是com.mchange.v2.c3p0.ComboPooledDataSource的连接不是DriverManager.getConnection()。qlkrp用了 c3p0 连接池lib/c3p0-0.9.1.2.jar所以DBUtil.java里static DataSource ds初始化时指定了maxPoolSize20。若你删掉c3p0.jar改用 DruidDBUtil.getConnection()会直接ClassNotFoundException。getAvailableSpace()方法在CarRecordServlet.java第 156 行它执行SELECT TOP 1 space_code FROM t_parking_space WHERE is_occupied0 ORDER BY space_code。注意TOP 1是 SQL Server 语法若误改成 MySQL 的LIMIT 1查询会静默失败返回空结果导致rows0触发回滚——但你根本看不到错误日志因为e.printStackTrace()被吞掉了。血泪经验在 catch 块里加System.out.println(SQL Error: e.getMessage());否则排查像盲人摸象。con.rollback()后必须con.close()否则连接不会归还池中。DBUtil.close()方法里有if (con ! null !con.isClosed()) con.close();这就是为什么finally块里要传con进去。3.3 SQL Server 特有 T-SQL 写法ISNULL()替代COALESCE()、GETDATE()替代NOW()qlkrp的所有 SQL 脚本car_db.sql,init_data.sql都针对 SQL Server 优化绝不能直接导入 MySQL 或 Oracle。例如统计当日入场车辆数的报表 SQL-- report_daily.jsp 中调用的 SQL SELECT COUNT(*) as total_in FROM t_car_record WHERE CAST(in_time AS DATE) CAST(GETDATE() AS DATE) AND status 1CAST(in_time AS DATE)是 SQL Server 2008 的日期截断写法MySQL 要用DATE(in_time)Oracle 用TRUNC(in_time)。GETDATE()返回datetime类型NOW()是 MySQL 函数SQL Server 用GETDATE()或SYSDATETIME()。若你在 SSMS 里执行SELECT NOW()会报Invalid column name NOW。ISNULL(status, 0)在t_car_record查询中用于处理status为 NULL 的脏数据而COALESCE(status, 0)虽然功能相同但ISNULL是 SQL Server 专属性能略优少一次类型推导。4. 避坑指南答辩前夜必查的 5 个致命问题与现场救火方案qlkrp源码包流传多年不同人打包时混入了各种魔改版本。以下 5 条是我帮 17 个毕设同学现场救火总结的高频翻车点每条都按“现象→原因→解决”给出可立即执行的动作不讲原理只给命令和路径。4.1 现象登录页输入admin/123456后跳转到error.jsp控制台报java.lang.ClassNotFoundException: com.microsoft.sqlserver.jdbc.SQLServerDriver原因WEB-INF/lib/下缺少sqljdbc4.jar或 jar 包版本与 SQL Server 不匹配如用sqljdbc42.jar连 SQL Server 2012。解决下载sqljdbc_4.0.2206.100_enu.zip微软官网归档页解压出sqljdbc4.jar将其复制到carmanage/WEB-INF/lib/目录删除lib/下所有其他sqljdbc*.jar如sqljdbc42.jar,mssql-jdbc-9.4.0.jre11.jar重启 Tomcat4.2 现象点击“车辆登记”提交后页面空白catalina.out显示org.apache.jasper.JasperException: /add_record.jsp (line: 32, column: 17) useBean: java.lang.InstantiationException: bean.CarBean原因CarBean.java的无参构造方法被误删或类路径写错如package bean;但文件放在WEB-INF/classes/bean/CarBean.class外。解决用记事本打开carmanage/WEB-INF/classes/bean/CarBean.class对应的.java源码通常在src/bean/CarBean.java确保有public CarBean() {}无参构造方法哪怕内容为空编译javac -encoding UTF-8 -d WEB-INF/classes src/bean/CarBean.java重新打包 WAR4.3 现象SQL Server 建库成功但t_car_record表里in_time字段全是1900-01-01 00:00:00.0不是当前时间原因CarBean.java中inTime属性类型为String但add_record.jsp里input typetext nameinTime未赋值导致jsp:setProperty传入空字符串PreparedStatement.setTimestamp()用null初始化了Timestamp。解决修改CarBean.java的setInTime(String inTime)方法public void setInTime(String inTime) { if (inTime null || inTime.trim().isEmpty()) { this.inTime new SimpleDateFormat(yyyy-MM-dd HH:mm:ss).format(new Date()); } else { this.inTime inTime; } }同步修改add_record.jsp中inTimeinput 的value属性input typetext nameinTime value%new SimpleDateFormat(yyyy-MM-dd HH:mm:ss).format(new Date())% readonly4.4 现象TimeoutCheckServlet手动访问返回 404但login.jsp能正常加载原因web.xml中 servlet-class 路径错误。常见错误是com.servlet.TimeoutCheckServlet写成servlet.TimeoutCheckServlet少了com.包前缀。解决打开carmanage/WEB-INF/web.xml找到servlet-class标签确认其值为com.servlet.TimeoutCheckServlet注意大小写同时检查TimeoutCheckServlet.java的 package 声明是否为package com.servlet;重新编译该 Servlet 并替换WEB-INF/classes/com/servlet/TimeoutCheckServlet.class4.5 现象车辆出场后t_parking_space.is_occupied仍为1车位未释放原因OutRecordServlet.java中UPDATE t_parking_space的 WHERE 条件写错用了plate_number而非space_code。原始代码第 92 行是ps2 con.prepareStatement(UPDATE t_parking_space SET is_occupied0 WHERE plate_number?);但t_parking_space表根本没有plate_number字段正确写法应关联t_car_record解决修改OutRecordServlet.java第 92 行为ps2 con.prepareStatement(UPDATE t_parking_space SET is_occupied0 WHERE space_code(SELECT space_code FROM t_car_record WHERE plate_number? AND status1));确保子查询返回唯一值t_car_record中同一车牌不会有多条status1记录重新编译部署5. 进阶实战给系统加“微信扫码出场”和“Excel 导出报表”两个硬需求毕设答辩时老师常会问“如果业主不想手动输车牌能不能扫微信二维码出场” 或 “物业要每周导出停车报表系统能直接 Excel 吗” 这两个需求看似简单但qlkrp的原始架构没预留扩展点。我用 3 小时在不改核心逻辑的前提下给它加上了这两个功能——不引入新框架只用原生 JSP/Servlet Apache POI 微信 JS-SDK代码量控制在 200 行内且能无缝集成。5.1 微信扫码出场用wx.scanQRCode替换手动输入车牌微信扫码本质是让手机摄像头读取二维码内容即车牌号再 POST 给后端。难点在于qlkrp的出场流程是 GET 请求跳转而扫码需异步 POST。解决方案是在out_record.jsp里嵌入微信 JS-SDK用wx.scanQRCode获取车牌后用 AJAX 提交到新 Servlet。在out_record.jsphead中加入微信 JS-SDK 引用script srchttps://res.wx.qq.com/open/js/jweixin-1.6.0.js/script script wx.config({ debug: false, appId: ${appId}, timestamp: ${timestamp}, nonceStr: ${nonceStr}, signature: ${signature}, jsApiList: [scanQRCode] }); /script注意appId,timestamp,nonceStr,signature需由后端生成调用微信jsapi_ticket接口此处为简化假设你已配置好微信公众号 JS 接口安全域名localhost不支持需用内网穿透如 natapp 或部署到测试服务器。在out_record.jsp添加扫码按钮和隐藏表单button onclickscan()微信扫码出场/button form idoutForm actionservlet/WechatOutServlet methodpost input typehidden nameplateNumber idplateInput /form script function scan() { wx.scanQRCode({ needResult: 1, success: function (res) { var result res.resultStr; // 二维码内容如 京A12345 document.getElementById(plateInput).value result; document.getElementById(outForm).submit(); } }); } /script新建WechatOutServlet.javacom.servlet包下public class WechatOutServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String plateNumber request.getParameter(plateNumber); // 复用原有 OutRecordServlet 的核心逻辑查 t_car_record、更新 t_parking_space、设 out_time // ...此处省略直接拷贝 OutRecordServlet 的 doOutProcess() 方法 request.setAttribute(msg, 扫码出场成功 plateNumber); request.getRequestDispatcher(out_record.jsp).forward(request, response); } }在web.xml中注册该 Servletservlet servlet-nameWechatOutServlet/servlet-name servlet-classcom.servlet.WechatOutServlet/servlet-class /servlet servlet-mapping servlet-nameWechatOutServlet/servlet-name url-pattern/servlet/WechatOutServlet/url-pattern /servlet-mapping5.2 Excel 报表导出用 Apache POI 生成report_monthly.xlsqlkrp原有报表页report_daily.jsp只显示 HTML 表格。要导出 Excel不能用response.setContentType(application/vnd.ms-excel)这种老式 CSV 方案中文乱码且无样式必须用 POI 生成真正的.xls文件。下载poi-3.17.jar兼容 JDK8放入carmanage/WEB-INF/lib/新建ExportReportServlet.javapublic class ExportReportServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 1. 查询本月数据SQL Server 写法 String sql SELECT plate_number, gate_name, in_time, out_time, DATEDIFF(HOUR, in_time, out_time) as park_hour FROM t_car_record WHERE YEAR(in_time)YEAR(GETDATE()) AND MONTH(in_time)MONTH(GETDATE()); ListMapString, Object data DBUtil.executeQuery(sql); // 2. 创建 Excel 工作簿 HSSFWorkbook workbook new HSSFWorkbook(); HSSFSheet sheet workbook.createSheet(月度停车报表); // 3. 写表头 String[] headers {车牌号, 入口闸机, 入场时间, 出场时间, 停放小时}; HSSFRow headerRow sheet.createRow(0); for (int i 0; i headers.length; i) { headerRow.createCell(i).setCellValue(headers[i]); } // 4. 写数据行 int rowNum 1; for (MapString, Object row : data) { HSSFRow dataRow sheet.createRow(rowNum); dataRow.createCell(0).setCellValue((String) row.get(plate_number)); dataRow.createCell(1).setCellValue((String) row.get(gate_name)); dataRow.createCell(2).setCellValue(((Timestamp) row.get(in_time)).toString()); dataRow.createCell(3).setCellValue(((Timestamp) row.get(out_time)).toString()); dataRow.createCell(4).setCellValue((Integer) row.get(park_hour)); } // 5. 输出响应 response.setContentType(application/vnd.ms-excel); response.setHeader(Content-Disposition, attachment; filenamereport_monthly.xls); workbook.write(response.getOutputStream()); } }在report_daily.jsp中加导出按钮a hrefservlet/ExportReportServlet classbtn btn-primary导出 Excel 报表/a在web.xml注册该 Servlet同上。注意POI 3.17 的HSSFWorkbook生成.xlsExcel 97-2003 格式兼容性最好。若要用.xlsx需升级 POI 4.x 并改用XSSFWorkbook但qlkrp的 JDK8 环境下 POI 4.x 会报java.lang.NoClassDefFoundError: org/apache/commons/collections4/ListOrderedMap必须额外加commons-collections4-4.4.jar——毕设求稳.xls足够。6. 我的三个落地习惯让qlkrp从“能跑”变成“敢交”做完上面所有步骤你已经能让系统在自己电脑上稳定运行。但毕设交付不是“能跑就行”而是“老师随便点、数据随便改、时间随便调系统都不崩”。这需要三个我坚持了五年的习惯它们不写在任何文档里但每次答辩都救我于水火第一数据库备份不是“建库后导出 .bak”而是“每次改表结构前用 SSMS 生成CREATE TABLE脚本存档”。qlkrp的t_car_record表在car_db.sql里定义为in_time datetime NOT NULL但某次魔改版本有人把它改成datetime2导致PreparedStatement.setTimestamp()插入失败。我习惯在改表前右键表 → “脚本表作为” → “CREATE 到” → “剪贴板”然后粘贴到schema_backup_20240521.txt。这样答辩时老师问“你改过哪些表”我能立刻打开文本对比而不是翻 Git 历史。第二Tomcat 日志不是“看 catalina.out 有没有报错”而是“在logging.properties里把org.apache.jasper.level FINE让 JSP 编译过程全量输出”。add_record.jsp里jsp:useBean找不到CarBean时catalina.out只报InstantiationException但开启 FINE 日志后会打印Loading bean class bean.CarBean from file:/D:/tomcat/webapps/carmanage/WEB-INF/classes/bean/CarBean.class一眼看出类路径是否正确。第三演示不是“按流程点一遍”而是“预设三个故障场景并当场修复”场景1手动删掉t_parking_space中B2-001记录再登记京A12345观察CarRecordServlet是否捕获SQLException并回滚场景2把TimeoutCheckServlet的url-pattern改错访问时展示 404 页面再现场打开web.xml修正场景3在t_car_record里插一条status0的脏数据运行TimeoutCheckServlet确认它只处理status1的记录。这三件事做完老师不会问“你懂原理吗”只会说“嗯这系统你确实弄明白了”。希望帮到你。本文还有配套的精品资源点击获取
返回列表