JSP网上玩具销售系统全解析:从架构搭建到答辩避坑
简介一份基于JSP的网上玩具销售系统毕业设计资源包面向Java Web方向的高校学生与开发者可作为课程设计、毕业设计的完整参考解决了从系统分析、数据库设计到前后端实现、项目报告撰写的多项痛点。压缩包共1059个文件、约23.2MB类型以JSP页面、Java源码、SQL脚本、HTML/CSS/JavaScript前端文件和GIF/JPG图片素材为主另含配置类文件、第三方编辑器组件与项目文档便于导入开发环境运行和二次定制。整体技术侧重JSPServletJavaBean数据库脚本提及MySQL适合希望独立完成网上商城项目的初中级学习者掌握Java Web分层与业务逻辑。已有390人学习下载资源内包含前台商品浏览、购物车、用户中心等核心流程同时给出导航栏设计、会话与Cookie处理、支付接口思路等实现细节对照源码和数据库脚本即可快速跑通项目有效节省从零搭建的时间。1. 基于JSP的网上玩具销售系统毕业设计高频选题先搞清楚这三点基于JSP的网上玩具销售系统是JavaWeb毕业设计里出现频率极高的题目。拿到压缩包后很多人看到一堆JSP页面、Servlet类、数据库脚本第一反应不是兴奋而是不知道从哪下手。这套资源我拆过一遍先说结论它本质上是一个标准的JSP Model 2结构的电商demoJSP负责展示页面Servlet处理请求JavaBean封装数据MySQL当仓库。它能帮你把前端页面、后端逻辑、数据库这三年学的零碎东西串成一条线。适合正在做毕业设计、或者想系统补一遍JavaWeb基础的人。如果你已经在用Spring Boot做项目了这篇文章能让你反过来理解JSP时代的底层逻辑。2. 技术选型与架构JSP Model 2 为什么能成为毕设标准答案2.1 从题目反推技术栈JSP 是评审老师最熟悉的“安全牌”毕业设计的评分标准往往不是谁的技术新而是谁能把业务讲清楚。JSPServletJavaBean的Model 2结构恰好是大多数高校JavaWeb课程的标准内容。老师不用看代码光看结构图就知道你的系统是怎么跑的。这一点是Spring Boot、SSM这些框架比不了的——不是不能用而是答辩时你需要花更多时间解释框架本身而不是业务。那为什么不建议直接用Spring Boot 2集成JSP呢两个原因。第一Spring Boot对JSP的支持很别扭需要额外配置视图解析器war包部署时还容易踩路径坑。第二毕设源码包大多都是从旧项目改过来的你非要迁移到Spring Boot等于把数据库脚本、JSP页面里的EL表达式、自定义标签全重写一遍工作量翻倍。用这份资源自带的JSPServlet反而是最快的路径。所以我的建议是如果你对JavaWeb还不熟练就不要动“重构到Spring Boot”的念头。先把JSP Model 2跑通答辩时讲清楚“请求怎么进来、模型怎么处理、视图怎么渲染”这条链路比什么都管用。资源里虽然也有jsp文件夹、service层这类中间产物但骨架仍然是京东淘客那种老式分层只要老师问起MVC你能指着代码说出Model、View、Controller分别对应哪些文件这一关就过了。2.2 运行环境SQL Server 2005 源脚本与 MySQL 的实际配置项目描述里提到“数据库选用的是SQL Server 2005服务器环境是IIS5.0或更高版本”但压缩包文件名又写着“jsp651玩具购物商城mysql-qrp”。这两个信息不冲突说明这是一套经历过迁移的毕设源码。原始版本可能跑在IISSQL Server上后来有人把数据库脚本改成了MySQL重新打包成这份资源。实际开发中我一般建议直接用MySQL原因很现实TomcatMySQLJDBC是JavaWeb毕设最经典的组合环境好搭教程多出了问题网上随便一搜就有答案。如果你坚持要用SQL Server 2005那我提醒一句JDBC驱动很旧和Windows 10/11的兼容性不好而且SQL Server 2005的安装包本身就不容易找到。所以除非老师明确要求否则不要自找麻烦。MySQL 5.7是这份代码最舒服的运行环境往下兼容5.5往上到8.0需要注意时区和驱动版本问题这点在第5章会细说。另外IIS和Tomcat并不冲突但在Windows上调试JSP直接用Tomcat反而简单IIS只是给那些非要套ASP环境的同学添乱的建议别碰。2.3 项目目录里的陌生文件fckeditor、class_upload.asp 和 io.asp 到底是什么解压后你在根目录或WebRoot里看到的fckeditor文件夹、class_upload.asp、io.asp不是病毒也不是老师故意放的干扰项。fckeditor是老牌的富文本编辑器很多老项目用它做商品描述、新闻公告的在线编辑。class_upload.asp和io.asp是FCKeditor的ASP服务端上传组件只有在部署到IIS ASP环境时才会生效。现在你的项目是JSP Tomcat这两个文件完全不会参与编译和运行。但这里藏着一个坑如果你把整个WebRoot目录原样丢到Tomcat里Tomcat虽然不会编译.asp文件但访问这些URL时可能返回403或者让浏览器直接下载。更关键的是FCKeditor的JSP版本需要单独配置上传处理类默认的ASP上传类是失效的。所以我的做法是直接删除class_upload.asp和io.asp或者把整个fckeditor换成较轻量的KindEditor。压缩包里还有fckeditor.afp、sample01.afp、sample02.afp这一堆.afp文件看起来像临时数据或者样例脚本不是Java可用的类同样建议排除。config.ascx是ASP.NET的用户控件配置跟JSP项目也没有关系看到它不用慌删除或忽视都可以。2.4 核心数据表设计玩具商品、会员、订单三张表的字段清单无论是SQL Server还是MySQL玩具商城系统的表结构都大同小异。常见的表有玩具商品表t_product、用户表t_user、订单表t_order、订单明细表t_order_item。这里给一份我惯用的核心字段你可以拿去跟资源里的SQL脚本对比看有没有缺失。表名核心字段说明t_productid, toy_name, category_id, price, stock, image_url, description, create_timecategory_id关联分类表图片存相对路径t_userid, username, password, phone, email, reg_timepassword建议存MD5摘要不存明文t_orderid, user_id, order_no, total_price, status, create_timestatus用字符串或枚举0表示未支付1表示已支付t_order_itemid, order_id, toy_id, quantity, price单价快照防止商品改价后订单金额出错这四张表是命令行级别的结构。特别注意订单明细的price字段它是下单那一刻的商品价格快照关联查询时不要用t_product的当前价格去算历史订单金额这是很多毕设项目里会被答辩老师追问的地方。会员表和订单表之间通过外键关联但实际开发中我更推荐只用普通索引约束逻辑关系不建物理外键因为毕设的增删改查操作频繁物理外键容易让删除商品的时候报“有订单关联”的错影响演示流畅度。老项目里用户表通常叫admin但玩具商城是C端系统管理员表反而应该单独建不要让普通用户和管理员混在一张表里。2.5 架构分层index.jsp、ProductServlet、ProductBean 之间怎么配合这套项目的代码分层不算严格但核心链路还是清晰的。以商品列表为例浏览器地址栏输入product?actionlist请求先到达ProductServlet的doGet方法。doGet里通过action参数判断要调哪个业务方法然后调用ProductDao查询数据库结果放进List 再用request.setAttribute传值最后forward到product_list.jsp。JSP页面通过EL表达式${product.toyName}循环打印数据。这个过程中ProductBean是纯数据载体属性名必须和数据库字段名对应得上。ProductDao和ProductService之间的边界老项目往往比较模糊有时候直接在Servlet里new一个Dao就开始查。答辩时如果老师较真分层你最好自己补一句“这里为了减少过度设计把Service合并到Dao层了”大多数老师都能接受。真正需要突出的不是分层而是你对每一个请求生命周期的理解。3. 搭建与数据库配置从解压到跑起来最长半小时3.1 解压后的资源清单哪些文件该看哪些别动拿到压缩包“jsp651玩具购物商城mysql-qrp”后正常解压会得到一套完整Eclipse工程。你重点关注这几个目录srcJava源码、WebRoot或web存放JSP页面、CSS、JS、配置文件、数据库脚本文件夹通常是.sql文件。目录/文件作用建议src/com/xxx/servlet控制器Servlet逐个阅读理解请求处理src/com/xxx/beanJavaBean实体类对应数据库表字段src/com/xxx/util数据库连接工具、分页类重点看DBUtilWebRoot/WEB-INF/web.xml项目配置检查Servlet映射和欢迎页WebRoot/header.jsp顶部导航修改站点名、菜单项sql/*.sql数据库脚本放到MySQL里执行fckeditor、.asp、.afp无用上传组件建议删除或忽略一个很重要的工作是当你打开Eclipse开始修改前先复制一份原始工程做备份。因为这种老项目经常会因为编码不同步、文件缺失导致编译不过没有后悔药可吃。你可以在压缩包上右键重命名保留一份带_backup后缀的版本然后解压第二份开始干活。我每次拆这类源码包都会先建一个README.txt记录解压后第一版能成功运行的状态后面改坏了直接回滚。3.2 数据库建库与导入从.sql脚本到MySQL 5.7先确认MySQL服务已启动。打开命令行或使用Navicat执行以下命令完成建库和数据导入mysql -uroot -p123456 -e CREATE DATABASE toy_mall DEFAULT CHARSET utf8 COLLATE utf8_general_ci; mysql -uroot -p123456 toy_mall sql/toy_mall.sql这里toy_mall是数据库名sql/toy_mall.sql是资源包里的脚本路径。如果脚本里原本就有CREATE DATABASE语句第一行可以省略。手动指定utf8编码是关键很多中文乱码的根源就是这里没有显式设置字符集。如果脚本执行过程中报错先检查脚本文件本身是什么编码——用Notepad打开如果右下角显示ANSI先转成UTF-8再执行。导入成功后用这条命令验证数据表是否都建好USE toy_mall; SHOW TABLES;常见的输出应该有十几张表比如t_user、t_product、t_order、t_order_item等。如果你发现只有表结构没有数据那一定是脚本里INSERT语句被注释了或编码问题导致插入失败。这种情况我一般不建议手动补数据可以写一个简单的SQL循环生成500条玩具商品记录但要注意价格和销量字段的随机范围。玩具商品的图片字段也要处理老项目里的image_url多半是空字符串建议批量改成项目实际要用的占位图路径否则页面上一片裂图。3.3 数据库连接参数从SQL Server到MySQL的迁移关键点原项目若是SQL Server 2005则数据库连接字符串用的是jdbc:sqlserver协议驱动类名是com.microsoft.sqlserver.jdbc.SQLServerDriver。现在用MySQL需要找到src/util/DBUtil.java或类似类把连接写到统一位置。// DBUtil.java 核心片段 public class DBUtil { private static String url jdbc:mysql://localhost:3306/toy_mall?useUnicodetruecharacterEncodingutf8useSSLfalseserverTimezoneAsia/Shanghai; private static String user root; private static String password 123456; static { try { Class.forName(com.mysql.jdbc.Driver); } catch (ClassNotFoundException e) { e.printStackTrace(); } } public static Connection getConnection() throws Exception { return DriverManager.getConnection(url, user, password); } }这段代码里的驱动类名如果你用的是MySQL 5.7及配套驱动写com.mysql.jdbc.Driver没问题如果换到MySQL 8.0驱动类名要改成com.mysql.cj.jdbc.Driver并且serverTimezone参数不能省。URL里的characterEncodingutf8和useSSLfalse是持久化连接不乱码和跳过SSL验证的两个关键参数漏掉任何一个后面都会弹出一堆奇怪的警告。因为这套代码很老推荐用5.1.49的驱动jar包不折腾。修改完连接参数后还要把对应的JDBC驱动jar包放进WebRoot/WEB-INF/lib目录。资源包一般自带但版本可能老旧。我建议删掉旧的mysql-connector-java-x.x.x.jar去Maven仓库下载一个5.1.49版本这个版本对MySQL 5.7兼容性最稳不会出现时区报错。如果项目里还有连接池配置比如DBCP或c3p0注意配置文件里也有一份数据库账号密码别只改了DBUtil忘了配置文件。3.4 Tomcat 部署Eclipse内置Tomcat与独立Tomcat的差异很多同学在Eclipse里直接run on server跑通了就以为交给老师也能跑。实际上评阅老师可能没有Eclipse只装了Tomcat。所以在答辩前最好把项目打成war包放进独立Tomcat的webapps目录里。常见做法是# 在Tomcat webapps目录下启动访问地址会自动带上war包名 cp toy_mall.war /opt/tomcat/webapps/ /opt/tomcat/bin/startup.sh启动后浏览器访问http://localhost:8080/toy_mall/如果能看到登录页或首页说明部署成功。如果报404先看Tomcat日志catalina.out里有没有Servlet初始化异常。这里要特别提醒如果web.xml里配置了欢迎页index.jsp但工程里文件名是login.jsp就会出现访问根路径404的情况。需要修改web.xml里的welcome-file-list把它指向实际存在的页面。另外MyEclipse或Eclipse导出的war包和IDEA导出的war包结构会有差别。IDEA默认会将编译结果放在out/artifacts目录并且war包里可能没有WEB-INF/classes下的配置文件导完之后要检查一下。部署时建议把war包名称设置成toy_mall不要叫ROOT否则访问路径会和课程设计报告里写的不一致。答辩老师会按照你演示时的URL来核对功能这里别翻车。4. 核心功能实战导航栏、商品列表、购物车到个人中心4.1 导航栏复用JSP include 指令与登录状态判断导航栏是每个页面都会出现的公共部分老项目里最经典的做法是用% include fileheader.jsp %静态引入。这样做的好处是编译后只有一个Servlet性能好。缺点也很明显header.jsp一旦改动整个应用都要重新编译。但在毕设体量下这个缺点可以忽略。%-- header.jsp 片段 --% % page contentTypetext/html;charsetUTF-8 % % Object userObj session.getAttribute(loginUser); % div classnavbar a hrefindex.jsp首页/a a hrefproduct?actionlistcategory1益智玩具/a a hrefproduct?actionlistcategory2早教玩具/a a hrefcart.jsp购物车/a % if (userObj null) { % a hreflogin.jsp请登录/a % } else { % a hrefuser?actionmyinfo个人中心/a a hrefuser?actionlogout退出/a % } % /div这段代码的核心是用session里的loginUser判断登录状态。注意瘦身版的判断直接放JSP里适合小项目如果按Model 2标准应该在Servlet里把用户信息塞到request或session然后JSP用EL表达式${sessionScope.loginUser ! null}判断。这里用脚本片段更直白答辩时跟老师解释也没问题。关键是导航栏中的链接要跟web.xml里的Servlet映射一致比如product?actionlist对应ProductServlet。如果映射配的是普通字符串匹配请求路径大小写也要严格统一。4.2 商品列表分页JSTL 标签 分页参数的正确写法玩具商城商品数量多分页必不可少。常见的分页实现是基于limit关键字LIMIT offset, pageSize。在ProductServlet的doGet方法里通过request.getParameter(page)拿到当前页然后查询总记录数计算出总页数。这里给出一段简化的Servlet分页逻辑int pageSize 12; int currentPage Integer.parseInt(request.getParameter(page) null ? 1 : request.getParameter(page)); String sql SELECT COUNT(*) FROM t_product; // 通过JDBC执行查询得到 totalCount int totalPage (totalCount pageSize - 1) / pageSize; int offset (currentPage - 1) * pageSize; String sqlList SELECT * FROM t_product ORDER BY id LIMIT ?,?; // 设置参数 offset, pageSize查询列表放入 request.setAttribute(productList, list) request.setAttribute(currentPage, currentPage); request.setAttribute(totalPage, totalPage); request.getRequestDispatcher(product_list.jsp).forward(request, response);分页算法里(totalCount pageSize - 1) / pageSize是向上取整这样总记录数为0时也能算出totalPage为0避免页面显示“第1页/共0页”的尴尬。LIMIT后面的两个参数必须都是int注意不能直接在SQL里拼接page参数否则有SQL注入风险。JSP页面上用JSTL的c:forEach遍历商品用c:if判断是否有上一页/下一页。如果你发现引入JSTL标签报错多半是在WEB-INF/lib里缺了jstl.jar和standard.jar或者web.xml被配置成了Servlet 3.0规范需要新的taglib引用。老项目多半用的是标准标签新Tomcat下可能不兼容这时候建议把JSP页面里的JSTL换成最简单的Java脚本循环代码丑一点但稳定。我之前见过一个项目JSTL引用的taglib地址还是sun的旧域名Tomcat 9下直接解析失败换成https://java.sun.com/jsp/jstl/core也不行最后干脆把c:forEach改成% for %问题立刻消失。4.3 购物车模块用 Session 存一个 Map为什么比存数据库好玩具商城的购物车毕设阶段不需要做到存数据库。最常见的方案是把购物车对象放进session用商品id作为key购买数量作为value。这样做的好处是用户在未登录状态下也能加购物车登录后再把session里的购物车数据合并到数据库。不过大部分毕设只做了前者。购物车类可以设计成这样的JavaBeanpublic class Cart { private MapInteger, Integer items new HashMapInteger, Integer(); private double totalPrice; public void add(int toyId, int quantity) { if (items.containsKey(toyId)) { items.put(toyId, items.get(toyId) quantity); } else { items.put(toyId, quantity); } recalculate(); } public void remove(int toyId) { items.remove(toyId); recalculate(); } private void recalculate() { // 遍历 items根据 t_product 价格计算新 totalPrice // 正常情况需要调用商品Dao获取价格这里省略 } // getter/setter 省略 }注意recalculate方法需要在商品数量变化时执行否则总价不对。很多同学把totalPrice做成独立的setter方法在Servlet里手动累加结果一刷新页面就重复累计。正确做法是购物车的totalPrice永远从items里实时推导不要在add方法外手动改。另外session里丢购物车是常见问题原因多半是web.xml里session的timeout被设置成了负数或过短。Tomcat默认session超时30分钟如果你在代码里改了session.setMaxInactiveInterval(负数)会导致session永远不过期这在空调房内无所谓但在答辩演示时可能因为长时间不操作被系统自动踢下线影响体验。4.4 个人中心信息展示JSP Servlet 回显流程与 EL 表达式搜索“jsp个人信息展示页面”的同学遇到最多的状况是页面能打开但用户名、手机号显示空白。原因不是查询失败而是Servlet没有正确把用户对象放到request作用域或者JSP用EL表达式时属性名拼写有误。个人中心的完整流程是这样浏览器发起user?actionmyinfoUserServlet从session取出loginUser并查出最新资料再转发到user_info.jsp。User user (User) session.getAttribute(loginUser); User freshUser userDao.findByUsername(user.getUsername()); request.setAttribute(userinfo, freshUser); request.getRequestDispatcher(user_info.jsp).forward(request, response);JSP页面上使用EL表达式获取用户名${userinfo.username} br/ 手机号${userinfo.phone} br/ 注册时间${userinfo.regTime} br/这里有个新手必踩的坑JavaBean里如果是regTime属性EL会解析getRegTime()方法。如果你在jsp里写${userinfo.reg_time}就会拿不到值。我看到很多毕设代码里数据库字段用下划线Java属性用驼峰容易搞混。建议统一把数据库字段的别名改成驼峰或者在SQL里显式加别名SELECT reg_time AS regTime FROM t_user。用setAttribute传值后千万不要再用response.sendRedirect否则重定向会丢掉request里的数据页面还是空白。这也是为什么要求用forward转发而不是重定向。如果你在个人中心还要显示用户头像记得先在Servlet里把头像文件读成Base64字符串再传给页面否则直接写相对路径可能会因为目录层级不对而显示裂图。4.5 商品搜索功能模糊查询与关键字高亮很多同学做完基础CRUD觉得系统已经完整了其实商品搜索是提升完成度最快的一个功能。在导航栏加一个输入框提交到product?actionsearchkeyword拼图。ProductServlet里这样处理String keyword request.getParameter(keyword); keyword new String(keyword.getBytes(ISO-8859-1), UTF-8); // 如果Tomcat已配置请求编码可以直接使用 keyword String sql SELECT * FROM t_product WHERE toy_name LIKE ? OR description LIKE ?; // PreStatement 设置参数为 % keyword % request.setAttribute(productList, list); request.getRequestDispatcher(product_list.jsp).forward(request, response);注意keyword的编码转换。如果JSP页面的请求编码是UTF-8Tomcat 8以上默认UTF-8可以不用做getBytes(ISO-8859-1)这步。但老项目经常在Tomcat 7下运行Get请求的查询串会按ISO-8859-1解码这里必须转一下否则中文关键字全是乱码搜索直接失效。Page里显示结果时可以用字符串替换把关键字加上红色背景这是答辩时一个非常加分的细节体验。5. JSP 玩具商城避坑指南五个高频翻车现场与排查思路5.1 中文乱码页面、数据库、服务器三重编码不一致现象商品名称和用户名在页面上显示成问号或者插入数据库后变成“”。原因项目里JSP页面的pageEncoding是ISO-8859-1数据库却是utf8Tomcat默认请求编码又不是UTF-8三重不一致导致乱码。解决统一三处编码。JSP页面首行设置为UTF-8数据库连接URL中加useUnicodetruecharacterEncodingutf8同时给CharacterEncodingFilter过滤器设置请求编码。filter filter-nameencoding/filter-name filter-classcom.toy.filter.CharacterEncodingFilter/filter-class init-param param-nameencoding/param-name param-valueUTF-8/param-value /init-param /filter从排查顺序上讲先在浏览器里打开页面源代码看中文是直接在HTML中乱码还是数据本身是问号。前者改JSP编码后者改数据库连接。只要这三步做了90%的乱码问题都能解决。还有5%发生在SQL脚本文件本身脚本文件是ANSI编码而数据库是utf8导入就乱。用Navicat导入SQL时注意选择文件编码为UTF-8。5.2 EL 表达式取不到值JavaBean 属性命名和 getter 不匹配现象商品详情页的${product.toyName}输出为空控制台也不报错。原因JavaBean类里写的方法是getToy_name()而属性名是toyNameEL表达式按JavaBean规范找getToyName()找不到就返回null。解决要么把属性改成toy_name并写getToy_name()要么在数据库查询SQL里用别名统一驼峰。更保险的做法是用IDE的source生成getter/setter别手敲。另一个常见原因是JavaBean没有被实例化session里的对象类型是Object强制转换时用了错误包名。比如session存的是com.toy.bean.User你转成com.toy.pojo.User页面就拿不到值。5.3 富文本编辑器加载异常.afp 和 .asp 文件不是 JSP 能调用的服务端组件现象商品描述编辑功能打不开浏览器控制台报fckeditor.js或fckeditor.afp相关的404/500。原因前面说过老项目里的class_upload.asp、io.asp是ASP服务端上传器Tomcat不处理它而且fckeditor.afp是编辑器产生的临时数据文件不是可调用接口。解决最省心的是把整个富文本编辑器从fckeditor换成KindEditor或UEditor的JSP版。如果老师不允许换组件就把fckeditor目录下的connectors/asp整个删掉改成jsp目录下的上传类同时确保fckeditor.js的路径正确。还有一点如果在Eclipse里看到.afp文件报错直接右键排除构建路径它们跟项目运行无关。删除这些杂文件前最好先全局搜索一下哪个JSP引用了它们避免页面报文件不存在。这套资源里没有前端页面依赖这些.asp文件所以直接删除就好。5.4 JDBC 驱动版本与 MySQL 8.0 的兼容问题通讯链路异常和时区报错现象Tomcat启动正常但一查数据库就报The server time zone value ???ú±ê׼ʱ¼ä is unrecognized或者Communications link failure。原因MySQL 8.0及以上版本JDBC驱动类和时区处理都变了。解决降级到MySQL 5.7配合mysql-connector-java-5.1.49问题最少。如果非要用MySQL 8.0按3.3节那样把驱动改为com.mysql.cj.jdbc.Driver并在URL加上serverTimezoneAsia/Shanghai和allowPublicKeyRetrievaltrue。注意5.1.49驱动不支持MySQL 8.0的caching_sha2_password认证方式数据库用户密码要改回mysql_native_password。这是我在一个商城项目里被卡了一晚上的地方那时MySQL 8.0刚出很多人不知道新认证机制和老驱动不兼容。5.5 Tomcat 部署后 404web.xml 里 Servlet 映射和欢迎页不一致现象直接用Tomcat访问项目根路径出现404但直接访问index.jsp能打开或者通过页面链接访问product?actionlist返回404。原因项目默认欢迎页index.jsp根本不在WebRoot根目录下或ProductServlet映射写的是/ProductServlet但前端链接用的是product。解决在web.xml的servlet-mapping里把URL模式改成和前端完全一致的路径然后确认welcome-file-list里的页面真实存在。如果是在Eclipse里run on server正常、打包war后404还要检查war包结构不要把WEB-INF目录放错层级。正确结构是war根目录下直接有index.jsp而不是再套一层项目名的子目录。部署后如果你访问http://localhost:8080/toy_mall/返回的是Tomcat默认首页那说明war包可能没解压成功去webapps目录看下有没有同名文件夹把旧的这个目录删除后重新启动Tomcat再试。6. 答辩前常做的三个升级让系统从“能跑”变成“能演示”6.1 统一异常处理替换掉散落在每个Servlet里的 try-catch翻看代码你会发现每个Servlet里都有一段差不多的try-catch错误提示写的是“系统错误”。我习惯在中间层加一个BaseServlet把异常统一抛给入口然后由一个ErrorPageServlet接收记录日志后跳转到友好提示页。这样演示时不容易在页面上看到一堆堆栈答辩观感完全不同。实现也不复杂写一个实现了HttpServlet的父类在service方法里包一层try-catch捕获后把异常信息放到request里转发到error.jsp。具体报错细节可以放在页面源代码注释里给导师检查时看但界面上只显示“开小差了请刷新重试”。6.2 会话超时提醒防止在演示时突然掉线在web.xml里设置session超时时间为20分钟并利用session的isNew属性在登录前做一个判断。常见做法是在header.jsp里加入一个JS定时器每60秒请求一次当前用户状态如果发现session已经失效直接弹窗提示重新登录。这个细节能明显提升演示的流畅度。因为答辩现场的时间往往比较紧张你可能在讲架构时忽略了页面操作等回头演示下单时发现已经超时重新登录一遍很尴尬。我在header.jsp里加了一段简单的fetchsetInterval(function () { fetch(user?actioncheckSession) .then(function (response) { return response.text(); }) .then(function (result) { if (result timeout) { alert(登录超时请重新登录); location.href login.jsp; } }); }, 60000);UserServlet里对应的checkSession逻辑很简单判断session.getAttribute(loginUser)是否为null为空则输出字符串timeout不为空输出ok。这段代码用的是原生fetch不依赖jQuery老项目里也能直接跑。如果你用的Tomcat版本较老不支持async也不要紧这里只是普通请求。6.3 用过滤器统一登录拦截给用户中心、购物车结算这些需要登录的URL加一个登录验证过滤器。注意排除login.jsp、register.jsp、静态资源路径。这样你不必在每个Servlet里写“if (user null) { response.sendRedirect(login.jsp); }”代码干净得多。一个简洁的LoginFilter如下public class LoginFilter implements Filter { public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletRequest request (HttpServletRequest) req; HttpServletResponse response (HttpServletResponse) res; String uri request.getRequestURI(); String ctx request.getContextPath(); if (uri.endsWith(login.jsp) || uri.endsWith(register.jsp) || uri.contains(/css/) || uri.contains(/js/) || uri.endsWith(.jpg) || uri.endsWith(.png)) { chain.doFilter(request, response); return; } Object user request.getSession().getAttribute(loginUser); if (user null) { response.sendRedirect(ctx /login.jsp); } else { chain.doFilter(request, response); } } }注意这里图片静态资源前缀和使用filter-mapping的url-pattern要匹配。如果filter配的是/*一定要把静态资源路径排除干净否则图片全部加载不出来。我第一次配这个过滤器时忘了排除.css结果整个页面裸奔所有样式都没了。当时还以为是CSS文件的问题折腾半天才发现是filter把请求拦住了。从那以后我每次配好filter都会先跑一遍项目根路径再用浏览器开发者工具看Network请求是不是有静态资源被误伤。这套过滤器逻辑在答辩时也很容易讲老师说“你怎么控制未登录用户访问订单页”你直接把web.xml里的filter-mapping截图扔到PPT里就行。从那以后我每次改web.xml都会先把原有配置备份成.bak文件再一行行加加完用curl -I http://localhost:8080/toy_mall/验证根路径是否正常接着用无痕浏览器窗口把登录、加购、下单、退出全流程走一遍。这套动作帮我避开了很多临时改配置导致的大翻车。希望帮到你。本文还有配套的精品资源点击获取