简介:一套基于Javaweb的网上宠物销售商城系统,面向Java Web初学者、课程设计及毕业设计人员,重点解决从零搭建可运行商城系统的痛点,覆盖宠物展示、用户注册登录、购物车、订单管理等核心电商业务流程,可帮助读者贯通前端页面、后台业务逻辑与数据库操作,建立完整项目开发认知。压缩包大小27.24MB,内含项目源代码、数据库脚本及配套论文文档,代码按功能模块分层组织,便于阅读和二次开发;数据库脚本预置用户、宠物分类、商品、订单等数据表,可直接导入MySQL验证功能。论文部分包含需求分析、系统设计、功能实现与测试等章节,其中需求分析梳理了宠物商城的业务流程和数据模型,系统设计给出了模块划分与数据库表结构,功能实现与测试则展示了编码方法和验证过程,既能作为毕业设计说明书蓝本,也能辅助理解整体架构与关键实现思路。目前已有37人学习下载,对需要参考完整Web商城项目来提升实战能力或完成毕设任务的学习者,有较高的参考价值。
1. Javaweb网上宠物销售商城:毕业设计级代码包到底能不能直接跑起来
拿到的这份「基于Javaweb的网上宠物销售商城系统(源代码+数据库+论文).rar」,本质是一个Javaweb完整项目案例,Servlet + JSP + MySQL这种经典组合,配好了源码、SQL脚本和一篇毕业论文。这个资源真正能解决的是三类人的问题:要做Javaweb课程设计但不想从零写业务逻辑的学生,想看完整前后端交互流程的初级开发者,以及需要一份规范化论文来对照自己文档结构的毕业生。它不是一个高并发生产系统,而是一份围绕宠物商品展示、购物车、订单提交、用户管理这条主线展开的教学型完整工程。
先说结论:这份资源能不能直接跑起来,取决于你对Javaweb运行环境的理解程度,而不是代码本身。IDE用IntelliJ IDEA,Tomcat 8.5,JDK 1.8,MySQL 5.7,这四个组件的版本匹配处理好,从导入到看到登录页也就是十分钟的事。但如果你不熟悉IDEA里配置Tomcat和Artifact的关联方式,再完整的源码也会卡在404上。下面我把项目结构拆开讲,重点落在数据库脚本怎么导、IDEA运行参数怎么配、购物车和订单这类核心模块的代码逻辑怎么读,最后把移植项目最常见的几个坑一条条列出来。
2. 项目结构和数据库脚本:Javaweb完整案例的目录映射与表设计逻辑
2.1 从资源包里的三层结构反推技术选型
一个合格的Javaweb项目资源包,打开rar之后应该有这三层东西:源代码工程目录、数据库脚本文件(通常是.sql格式)、论文文档。这份资源的正确打开方式是先看SQL脚本,再看源代码里的DAO层,最后才看JSP页面。因为Javaweb项目里,数据库表结构决定了业务能走到哪一步,DAO层的SQL语句决定了功能怎么落地。
历史原因,这套课设资源的主流技术选型是JSP + Servlet + JDBC,而不是Spring Boot。原因是很多学校的Javaweb课程考核点就在Servlet生命周期、Request/Response对象使用、Session状态管理这些基础概念上,用Spring Boot会把底层细节全部屏蔽掉,答辩时反而讲不出东西。对应到这份资源的源代码目录设计,一般是webapp(或WebContent)下放JSP和静态资源,src下分servlet / service / dao / model四层,model是实体类,dao是JDBC操作,service是业务判断,servlet是请求入口。
如果你之前只写过Spring Boot项目,刚打开这种老式结构会觉得别扭,因为Servlet的请求路径写在web.xml或者@WebServlet注解里,跳转方式用的是forward和redirect,而不是return "index.html"。我一般建议先别急着改代码,按这个顺序把代码和数据库的对应关系检查完,再动手增删功能。
2.2 数据库表设计:一张用户表和三张订单关联表就撑起整个商城
这套宠物商城系统的数据库核心表通常是5张左右。用户表user_info存登录账号、密码、昵称、电话、地址,这是所有业务的前提;宠物表pet_info存宠物名称、品种、价格、图片路径、库存量,这是商品展示的数据源;购物车表cart和订单表orders、订单明细表order_detail关联起来,构成了从加购到下单的完整链路。
-- 用户表 CREATE TABLE `user_info` ( `id` int(11) NOT NULL AUTO_INCREMENT, `username` varchar(50) NOT NULL, `password` varchar(50) NOT NULL, `nickname` varchar(50) DEFAULT NULL, `phone` varchar(20) DEFAULT NULL, `address` varchar(255) DEFAULT NULL, `create_time` datetime DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `uk_username` (`username`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- 宠物表 CREATE TABLE `pet_info` ( `id` int(11) NOT NULL AUTO_INCREMENT, `pet_name` varchar(50) NOT NULL, `breed` varchar(50) DEFAULT NULL, `price` decimal(10,2) NOT NULL, `image` varchar(255) DEFAULT NULL, `stock` int(11) DEFAULT '0', `description` text, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;这两张表的设计有两个值得注意的点。第一是用户名字段加了唯一索引,虽然代码里登录时也会查一次用户名是否存在,但数据库层的唯一约束兜底了并发注册时两条相同用户名同时通过校验、后者覆盖前者的脏数据问题。第二是价格用decimal(10,2)而不是float——float在计算0.1+0.2这类场景会出精度问题,订单总价计算用的字段必须用定点数。
订单表和订单明细表是父子表关系。父表orders只存订单编号、用户ID、总金额、下单时间、状态(待付款/已付款/已发货/已完成),子表order_detail存订单ID、宠物ID、单价、数量。这种拆分避免了用户一次性买多只宠物时,一只宠物对应一条父订单记录的冗余写法,也让修改订单某个商品的数量状态时不需要动父表数据。
2.3 数据库脚本导入:Navicat执行SQL的时间点选择
把SQL脚本导入MySQL这一步,决定了后面项目能不能起来。第一步先在MySQL里创建一个空数据库,名字最好和源码里jdbc.properties配置的数据库名一致,常见命名是pet_shop。第二步用Navicat或命令行执行SQL文件,我优先推荐命令行执行——因为Navicat在导入较长SQL脚本时遇到默认字符集不一致的情况,会出现“1064 You have an error in your SQL syntax”这类报错,但同一条SQL在命令行里能正常执行,多数情况下是Navicat连接时选的编码和脚本头部声明的字符集不一致。
mysql -u root -p pet_shop < pet_shop.sql执行完这条命令之后,去检查一下pet_info表里有没有自带测试数据。很多课程设计资源会在脚本里预置十几条宠物记录,这样项目跑起来首页直接有内容展示。如果脚本里没有INSERT语句,说明需要自己在后台管理模块里添加,这是分辨资源完整度的一个常用方法。
数据库这步做完,接下来就是配置连接参数。源码里一般有个db.properties或jdbc.properties,需要把用户名、密码、连接地址改成你自己的环境值。注意MySQL 8.0以上版本的驱动类名和连接串参数和5.7不一样,如果你本机装的是8.0,驱动要换成com.mysql.cj.jdbc.Driver,并且连接串后面要加serverTimezone=Asia/Shanghai,这是Javaweb项目从MySQL 5.7升级到8.0之后最常见的兼容性调整。
3. 在IDEA里把Javaweb项目跑起来:Artifact配置与Tomcat部署的完整流程
3.1 导入项目的两种方式和前置检查
IntelliJ IDEA运行Javaweb项目配置这一块,卡住了很多人。拿到源码包后,先解压,然后在IDEA里用Open方式选择解压目录,注意不能直接Open rar文件。IDEA会识别出这是一个Web项目,但版本不同识别能力不一样,IDEA 2020及以上版本基本能自动识别,旧版本可能需要你手动添加Web Facet。
导入后第一件事不是点运行,而是检查Project Structure里的三块:Project SDK是不是1.8、Language Level是不是8、Modules里的Web模块有没有正确关联到web.xml所在目录。这里有个经验判断:如果源码里web.xml放在webapp/WEB-INF下,那Modules设置的目录应该是webapp;如果放在WebContent/WEB-INF下,就对应WebContent。路径选错的话,部署后Tomcat会报404,因为你访问的index.jsp根本不在部署包的根路径下。
还有一个容易被忽略的坑:源代码里如果有.idea文件夹或.classpath文件,说明对方用的是Eclipse或IDEA的旧版本,导入时最好把自己的.idea重置一下。我一般做法是删除源码包里的.idea目录再Open,这样IDEA会按当前版本重新生成项目配置,避免旧配置里的绝对路径和新机器不匹配导致的一堆红色报错。
3.2 Tomcat配置的四个关键参数
在IDEA里配置Tomcat,主要填四个参数。URL端口号默认8080,如果本机8080被占用,改成8081或9090都行——改的时候注意同时修改代码里跳转路径里写死的端口号,如果源代码中页面跳转是访问http://localhost:8080/pet_shop/...这种绝对路径,那就必须保持一致。Application context建议直接设为/,这样访问路径是http://localhost:9090/index.jsp,清爽不会写错。如果不改直接用源作者留的/pet_shop,那所有前面没加项目名的跳转路径全都会404。
# IDEA中配置Tomcat时的关键参数:Deployment - Application context # 推荐配置为:/ # 此时访问地址为:http://localhost:8080/index.jsp # 也可以配置为:/pet_shop # 此时访问地址为:http://localhost:8080/pet_shop/index.jsp第三个参数是Tomcat的VM options。如果你发现项目启动时内存报错,可以在VM options里加上-Xms256m -Xmx512m。第四个参数是server.xml里的URIEncoding。Javaweb项目中文参数乱码的问题,一半出在页面编码没统一,另一半就是Tomcat默认对URL里的非英文参数用ISO-8859-1解码,导致从链接里传递的中文到了Servlet变问号。
3.3 从Deployment到浏览器看到首页:完整操作序列
配置好Tomcat后,点Run按钮会经历三个阶段:编译、部署、启动。编译阶段看Build菜单的Output区域有没有红色报错;部署阶段IDEA会把工程打成war包放到Tomcat临时目录;启动阶段Tomcat日志输出到IDEA控制台。看到Server startup in xxx ms就说明启动成功了,然后浏览器手动打开地址,而不是依赖IDEA自动弹出的页面。
从源码导入到首页显示,完整序列是这样的:打开IDEA选Open导入解压后的源码目录——如果目录带.idea旧配置就在文件管理器里先删掉——配置Project SDK为1.8——打开Project Structure确认Web Facet正确——下载并配置Tomcat 8.5——创建一个本地Tomcat运行配置——Deployment里点+号选择Artifact,Application context设/——启动前检查db.properties里数据库账号密码——运行并观察控制台日志。
这套流程走下来,如果代码库里没有隐藏的编译错误,一个干净的可运行的Javaweb商城系统就起来了。这一步做完,你就拿到了项目的执行入口,后面的功能验证和代码阅读才真正开始。
4. 商城核心业务链路:登录过滤、购物车Session方案与订单状态机的代码实现
4.1 登录逻辑与Session管理:过滤器拦的是没登录就乱逛的请求
这套系统里用户登录用Session来维持状态,这是Javaweb课程要求里最常见的身份认证方案。登录Servlet做的事是:从请求里取用户名和密码,调用UserDao的findByUsernameAndPassword方法查库,查到就把用户对象塞进Session,然后重定向到首页;查不到就在request里放一个error信息,forward回登录页面提示。这套流程里,真正值得学的是Session和Cookie的边界把握。Session存在服务器端,Cookie存sessionId在浏览器端,关闭浏览器Cookie消失,但Session在服务器端还能存在一段时间。所以做一个“记住我”功能,不能只依赖Session,而是在Cookie里写入用户名和密码哈希,下次访问时读取并自动登录。
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("utf-8"); String username = request.getParameter("username"); String password = request.getParameter("password"); User user = userService.login(username, password); if (user != null) { HttpSession session = request.getSession(); session.setAttribute("loginUser", user); response.sendRedirect(request.getContextPath() + "/index.jsp"); } else { request.setAttribute("loginError", "用户名或密码错误"); request.getRequestDispatcher("/login.jsp").forward(request, response); } }这段代码有两个层面值得注意。参数层面,第一行request.setCharacterEncoding("utf-8")解决的是POST请求体里的中文乱码——POST参数在请求体里,不设编码就会按平台默认编码解析,Windows中文系统默认GBK,跟页面的UTF-8一冲突就乱码。一行代码一个坑。逻辑层面,登录成功后用sendRedirect而不是forward,是为了解决表单重复提交问题——如果用了forward,用户按F5刷新时页面会再执行一次doPost,产生二次登录的效果;用redirect后刷新的是GET请求,安全得多。
相对应地,所有需要登录才能访问的页面——比如购物车、结算页、个人中心——用一个LoginFilter统一拦截。这个过滤器在doFilter里判断Session里有没有loginUser,没有就重定向到login.jsp,有就放行。这种思路比在每个Servlet里重复查Session要干净得多,后面要加“管理员才能访问”的拦截,就是在过滤器里多判断一次角色字段。
4.2 购物车:不用数据库表,一个Session Map就够用的方案
购物车这块有个有意思的设计取舍。课设级别的商城系统,购物车通常不建表,而是把当前用户加购的商品放进Session里的Map<宠物ID, 数量>。好处是不用每次刷新页面都查数据库,响应快;坏处是用户一关浏览器购物车就没了。这在毕业设计里不算缺陷,反而是答辩时的加分点——你能说清楚Session购物车和Cookie购物车的优缺点,并回答为什么不用Cookie存购物车:Cookie容量上限4KB,存不下品类多的购物车,而且每次请求都携带会导致流量浪费。
@SuppressWarnings("unchecked") protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { HttpSession session = request.getSession(); Map<Integer, Integer> cart = (Map<Integer, Integer>) session.getAttribute("cart"); if (cart == null) { cart = new HashMap<>(); session.setAttribute("cart", cart); } int petId = Integer.parseInt(request.getParameter("petId")); int num = Integer.parseInt(request.getParameter("num")); // 如果购物车已存在该宠物,数量累加 cart.put(petId, cart.getOrDefault(petId, 0) + num); response.sendRedirect(request.getContextPath() + "/cart.jsp"); }这段代码的妙处在getOrDefault这一句。第一次加购时Map里没有这个key,getOrDefault返回0,加num就是初始数量;第二次加购同一个宠物时返回旧数量,再累加。一行代码同时处理了新增和累加两种场景,不需要if判断key是否存在。参数层面,num从请求参数里来,前端页面可以设计成“购买数量”下拉选择或输入框;如果想做“购物车页面直接改数量”,只需要把数量参数name统一好,后端不用改逻辑。
购物车页面展示时,从Session里取出Map,遍历key集合查pet_info表得到宠物信息,价格乘数量算出单项小计。这里顺手能算一遍总金额,存到request域里给页面展示。这步对刚入门的人提一个要求:算金额时尽量在Servlet里用BigDecimal算,不要在前端页面用JSTL标签直接乘——不同JDK版本对浮点数乘法结果精度不同,用BigDecimal.from(price).multiply(BigDecimal.valueOf(num))才能保证金额不出现0.30000000000000004这种结果。
4.3 订单提交:事务里包裹的减库存和插入操作
下单是整个系统里唯一必须用数据库事务的地方。用户点了“提交订单”,后端要做的事有三件:往orders表插一条订单主记录、往order_detail表插n条订单明细、把pet_info表对应宠物的库存减去购买数量。这三步里任何一步失败,都会导致数据不一致:要么订单建了库存没减形成超卖,要么库存减了订单没生成用户钱白付。
Connection conn = null; try { conn = DBUtil.getConnection(); conn.setAutoCommit(false); // 1. 插入订单主表 String sqlOrder = "insert into orders(user_id, total_price, status, create_time) values(?,?,?,?)"; // 2. 获取自增主键id,用于订单明细的外键关联 PreparedStatement ps = conn.prepareStatement(sqlOrder, Statement.RETURN_GENERATED_KEYS); ps.setInt(1, userId); ps.setBigDecimal(2, totalPrice); ps.setString(3, "待付款"); ps.setTimestamp(4, new Timestamp(System.currentTimeMillis())); ps.executeUpdate(); ResultSet rs = ps.getGeneratedKeys(); int orderId = rs.next() ? rs.getInt(1) : 0; // 3. 循环插入订单明细,同时扣库存 for (CartItem item : items) { insertOrderDetail(conn, orderId, item.getPetId(), item.getPrice(), item.getNum()); updateStock(conn, item.getPetId(), item.getNum()); } conn.commit(); } catch (Exception e) { conn.rollback(); throw new RuntimeException("订单保存失败", e); } finally { conn.setAutoCommit(true); conn.close(); }这段代码里,Statement.RETURN_GENERATED_KEYS是PreparedStatement的一个参数,用途是执行insert之后能通过getGeneratedKeys拿到数据库自动生成的主键。不用这个的话,你就得先select max(id)再插明细,并发下必然出错。setAutoCommit(false)到commit()再到异常时rollback(),是事务的标准三步,这个结构在ibatis、MyBatis里被SqlSession的commit和rollback封装了,但手写JDBC能让我们看清事务的底层原理。
事务写完,经典追问是“如何避免两个用户同时买最后一只宠物导致库存变负”。手写JDBC的可靠解法是在updateStock的SQL里加条件:update pet_info set stock = stock - ? where id = ? and stock >= ?,这样数据库行锁会保证同一条记录的更新串行化,第二个事务执行更新时stock已经不满足条件,影响行数为0,代码判断执行结果如果是0就抛出“库存不足”异常,触发整个事务回滚,用户的订单不会保存。这个细化点放答辩或者和生产环境对接时都属于加分能力。
4.4 后台管理:商品增删改查的完整闭环
除了前台用户浏览下单,这套系统通常还带一个管理员后台,承载商品信息的添加和上下架。后台的代码结构和前台是同一套DAO,区别在权限控制和页面布局。管理员的判断靠用户表的role字段,0是普通用户,1是管理员,在LoginFilter里加一行角色判断就够了。商品添加功能用上传组件把图片保存到webapp/upload目录,数据库中只存相对路径,页面里用<img src="${pet.image}">展示——这行的前提是图片在webapp的upload目录下,Tomcat会把webapp目录直接映射为上下文根路径。
到这里,系统从用户注册到管理员改商品价格的整条业务链路就完整了。对这些功能的掌握程度,决定了你能不能自信地回答“这个项目你做了什么”这个毕业答辩必考题。挣分的话术是把事务扣库存和Session购物车这两个细节讲透,这两个点随便哪一个,都足以证明代码不是从网上复制粘贴。
5. 常见问题与避坑指南:Javaweb项目移植到新机器的六个高发故障
把别人的Javaweb项目跑通的核心是环境一致性,但每台开发机的JDK路径、MySQL版本、Tomcat版本都不可能完全一样。我拆这个宠物商城资源时踩过的坑,基本覆盖了Javaweb项目移植到新环境的高发故障,按现象、原因、解决列在下面,对应自己的现象照方抓药即可。
5.1 现象一:Tomcat能启动,但浏览器访问项目路径只有目录列表或404
这个现象太经典了。目录列表说明Tomcat没有识别到你的部署包,404说明部署包结构不对或上下文路径不匹配。原因通常是IDEA里Deployment那一步没配好,或者Artifact的类型选错了。解决方法是打开Run Configurations,看Deployment里是否已经添加了war exploded类型的Artifact,然后看Application context是否跟浏览器访问路径一致。一个原则记住:IDEA里红色的“+”号和Artifact列表为空,都是项目没被正确识别为Web项目,回到Project Structure把Web Facet补上。
5.2 现象二:登录页输入中文后,跳转后全部是问号或乱码
原因是传输过程中的编码链没统一。JSP页面显示用的UTF-8,Tomcat解析URL参数用的却是ISO-8859-1,提交表单后数据在Servlet里收到的就是乱码。解决方法是先确认三处编码都是UTF-8:第一处页面顶部的<%@ page contentType="text/html; charset=UTF-8" %>,第二处request.setCharacterEncoding("utf-8")在Servlet的doPost开头,第三处Tomcat的conf/server.xml里给Connector增加URIEncoding="UTF-8"。三处都对齐之后,中文不会乱。
5.3 现象三:控制台报ClassNotFoundException: com.mysql.jdbc.Driver
看到这个异常先看两个地方,第一是MySQL的驱动jar包有没有放在WEB-INF/lib下面——老式Javaweb项目不用Maven,jar包都是手工往lib目录塞的,漏了自然找不到类。第二是MySQL版本,如果你装的是MySQL 8.0以上,驱动类名已经改成了com.mysql.cj.jdbc.Driver,并且连接串要附带serverTimezone参数。这两个解决了,这个异常就不会再出现。
5.4 现象四:数据库导入后,项目能启动,但列表页报空指针或查不到数据
这个现象的原因一般是数据库名与jdbc.properties里配置的名字不一致,注意保持连接串jdbc:mysql://localhost:3306/数据库名中的库名和实际创建的库名完全一致。还有一种情况是SQL脚本执行时选了其他数据库,导致表建到了别的库里。解决方法是执行show databases;确认库存在,然后use 库名; show tables;确认表存在,两条命令就定位了问题。
5.5 现象五:页面能打开但图片不显示
原因是图片资源的磁盘路径与URL访问路径不一致。Javaweb中,图片放在webapp/upload目录下,浏览器访问http://localhost:8080/upload/xxx.jpg能显示;但如果代码里写的是D:/upload/xxx.jpg这种绝对磁盘路径,浏览器无法直接访问服务器文件系统,自然显示不了。解决方法是把图片存到webapp下,代码里用相对路径或通过虚拟路径映射,在server.xml里配一个<Context docBase="D:/upload" path="/upload"/>。
5.6 现象六:一个“从入门到放弃”级别的报错:JSP编译失败或ClassNotFoundException
这个报错常见于页面引用了某个类,但这个类没有被打进Artifact。原因是IDEA里Artifact的WEB-INF/classes目录没有关联到项目编译输出目录。解决方法是Project Structure - Artifacts - 选中当前Artifact - 在Available Elements里把项目编译输出拖到/WEB-INF/classes下。这一步做完重新构建,JSP就能正常编译。表格形式总结一下这六个问题的定位方向和解决动作:
| 现象 | 定位方向 | 解决动作 |
|---|---|---|
| 404或目录列表 | 部署配置 | 检查Deployment和Application context |
| 中文乱码 | 编码链 | 统一JSP、request、Tomcat三处UTF-8 |
| 驱动类找不到 | jar包 | 补充lib下驱动jar或换MySQL 8驱动类 |
| 数据查不到 | 库表路径 | 核对数据库名和表存在性 |
| 图片不显示 | 资源路径 | 改相对路径或配置虚拟目录 |
| JSP编译失败 | Artifact结构 | 关联编译输出到WEB-INF/classes |
这是一份快速排查表,你把它截图或存下来,运行期遇到问题先对号入座,能省下大量在搜索引擎里试错的时间。
6. 把课设项目改造成能写进简历的作品:三个低成本的进阶验证方向
项目跑通只是开始,绝大多数人拿着这个宠物商城项目去面试,遇到的问题不是“能不能运行”,而是“这个项目和网上的有什么区别”。下面给你三个改动成本极低但能显著拉高项目完成度的方向,每个都对应真实的工程能力点。
第一个方向是把JDBC手动获取连接改成数据库连接池。源码里DBUtil如果用的是DriverManager.getConnection,每次请求都新建物理连接,高并发下MySQL会报“Too many connections”。改成Druid连接池只需要换DBUtil的内部实现:初始化时用DruidDataSource创建一个池,之后getConnection从池里borrow,用完归还。这一改动从代码量上只影响一个类,但回答“数据库性能优化”这个问题时,你能说出连接池复用、最小连接数、最大连接数、空闲回收这些参数,比单纯说“用了连接池”有说服力得多。
第二个方向是给前端页面套一个现代化的CSS框架。课设项目的原版页面通常是JSP配HTML的裸样式或简单CSS,视觉效果停留在早期互联网时代。你可以引入Bootstrap,改动方式不是重写页面,而是在公共头文件里加一行Bootstrap的CDN链接,然后给表格、按钮、输入框补class。这个改动不需要动任何后端代码,完成之后界面质感和源项目差异一条街。用CDN的原因是课设项目不要求离线部署,简历里说“使用Bootstrap快速美化页面”也是加分的点。
第三个方向是给订单提交加一个库存不足的友好提示。源码里的下单逻辑,如果库存不够,现有做法是直接抛出异常在页面上显示英文异常堆栈或500页面。你可以改成一个工厂模式的提示:在Servlet里捕获库存不足异常后,request.setAttribute("msg", "您购买的宠物库存不足");然后forward到cart.jsp,页面顶部用一个alert区域的div显示msg。这个改动量不大,但让系统的完成度从“能跑”提升到“可用”。
这三个方向做完,你自己把项目跑一遍完整流程:注册一个新账号,用这个账号登录,浏览宠物列表,把至少两只宠物加入购物车,提交订单,再回后台看订单记录。验证的时候重点看控制台有没有异常,数据库里orders表和order_detail表是否同时新增了记录,库存数字有没有相应减少。这一条链走通,项目就算真正交付了。从那以后我每次拿到一个Javaweb项目源码,第一件事就是先走通这条链路再谈别的——数据能闭环,说明环境、配置、代码三者是一致的,后面所有改动才有意义。希望这份拆解能让你少走点弯路,直接把项目跑起来再谈改进。
本文还有配套的精品资源,点击获取