☰
JavaWeb购物商城课设:从数据库设计到部署避坑的全流程指南
2026/10/9 9:10:30 网站建设 项目流程

简介:一套完整的JavaWeb购物商城课程设计源码与数据库包,面向正在准备期末大作业或课程设计的计算机专业学生。项目覆盖购物商城常见核心功能,包括用户登录注册、商品浏览查询、购物车管理、订单结算等,界面简洁、操作流畅,代码中附有详细注释,即使基础薄弱的新手也能看懂并快速完成部署,可作为高分参考方案。压缩包共129个文件,约19.29MB,涵盖Java源码、JSP页面、SQL数据库脚本、CSS/JS前端样式、JAR依赖库及Eclipse工程配置等,其中11个Java类与17个JSP页面构成主要业务逻辑,45张PNG图片保障界面效果,配套数据库脚本包含建表语句与示例数据,可一键导入使用。已有350人学习下载,适合需要借鉴完整项目结构、学习Servlet/JSP开发或直接作为期末提交材料的读者。系统功能完善、管理便捷,实际应用价值较高,是一份可信赖的满分大作业参考资源。

1. JavaWeb购物商城课设:为什么满分大作业拼的不是功能数量

拿到“JavaWeb课程设计-购物商城项目源码+数据库”这个标题时,多数人的第一反应是找一份能跑的源码,改个名字交上去。但真正拿过满分的人清楚,课程设计评审老师看的从来不是功能堆了多少,而是三件事:项目能不能一键跑起来、数据库设计是不是符合课程阶段要求、答辩时你能不能把代码讲明白。购物商城恰好是JavaWeb课设里最典型、也最容易拿高分的选题——它覆盖了用户登录注册、商品展示、购物车、订单生成这条完整业务链,每一环都能对应到Servlet、JSP、JDBC这些课程核心知识点。

本篇按我实际做课设和帮学弟学妹改项目的经验,把这份作业从技术选型、数据库设计、项目部署到避坑排错完整拆开。目录结构、代码、SQL脚本、踩坑记录都给到可直接复现的程度。新手照着走能跑通,熟手也能从边界参数和常见翻车点里找到对自己有用的东西。

2. 技术栈与项目结构:Servlet + JSP + Bootstrap 为什么是课设最优解

2.1 选型理由:为什么先别急着上 Spring Boot

很多同学一上来就想用 Spring Boot + Vue 前后端分离,觉得显得水平高。但课程设计有一套隐性评分标准:项目难度要匹配课程进度。JavaWeb 课程教的是 Servlet、JSP、Filter、JDBC 这些基础组件,你交一个 Spring Boot + MyBatis Plus 的项目,老师大概率会追问“你的 Filter 在哪写的”“JSP 放哪了”——答不上来反而扣分。更现实的问题是,Spring Boot 内嵌 Tomcat 的教学演示和你课程里学的部署方式脱节,答辩容易被问到细节崩溃。

我一般建议课设直接用 Servlet + JSP + Bootstrap 这套组合。原因有三:第一,每个类都能对应到课本概念,Controller 就是 Servlet,视图就是 JSP,数据访问就是 JDBC,答辩时老师问什么都接得住;第二,部署方式简单,一个 WAR 包丢进 Tomcat 就能跑,不会在环境问题上耗掉大量时间;第三,Bootstrap 提供了足够好看的默认样式,商品卡片、导航栏、登录表单一套模板全搞定,不需要自己写 CSS。

运行环境选型上,最稳妥的搭配是 JDK 8 + Tomcat 8.5 或 9.0 + MySQL 5.7。JDK 8 的原因在于大多数课程机房还停留在这个版本,Tomcat 9 对 Servlet 4.0 的支持也够用,MySQL 5.7 的 sql_mode 配置没 8.0 那么严格,不容易出现“连接成功了但 SQL 报错”的诡异情况。如果你电脑上装的是 MySQL 8.0 也没关系,后面我会讲驱动和时区参数的配置方法。

2.2 标准分层:按 DAO、Service、Servlet、JSP 拆,而不是把代码全塞进一个类

购物商城课设最常见的反面教材,是一个UserServlet.java里同时写了数据库查询、业务判断、页面跳转,300 行代码一个类搞定。初看觉得效率高,实际上答辩时老师让你加一个“用户下单后扣库存”的功能,你会发现自己根本不知道从哪下手。越早按分层写,后期改起来越舒服。

标准的分层结构长这样:

src/main/java/com/shop/ ├── dao/ // 数据访问层,只负责 SQL 和结果集映射 │ ├── UserDAO.java │ ├── ProductDAO.java │ └── OrderDAO.java ├── service/ // 业务逻辑层,处理登录校验、下单事务 │ ├── UserService.java │ ├── ProductService.java │ └── OrderService.java ├── servlet/ // 控制层,接收请求、调用 service、转发视图 │ ├── LoginServlet.java │ ├── RegisterServlet.java │ ├── ProductListServlet.java │ └── CartServlet.java ├── util/ // 工具类,DBUtil.java 管理连接 └── entity/ // 实体类,User.java、Product.java、Order.java

webapp 目录下放 JSP 和静态资源,按功能再分子目录:

webapp/ ├── jsp/ │ ├── login.jsp │ ├── register.jsp │ ├── product_list.jsp │ └── cart.jsp ├── css/ bootstrap.min.css ├── js/ jquery.min.js, bootstrap.min.js └── WEB-INF/web.xml

请求走向是:浏览器 → Servlet → Service → DAO → MySQL,数据返回再反向逐层交给 JSP 渲染。这个结构下,DAO 只管selectUserByUsername这一类单条语句,Service 负责把“查用户 + 比对密码”串成完整登录逻辑,Servlet 只做参数取值和页面转发。各层各自独立,改 JSP 样式不影响 Java 代码,换数据库驱动也不用手动改动所有类。

2.3 开发环境配置:不把 IDEA 和 Tomcat 调好,后面全是坑

我见过至少一半的项目翻车不是代码有问题,而是 IDEA 里没把项目配置成 Web 工程,导致 Tomcat 启动时报错或者 404。这里给出我每次配置的标准动作,适用于 IDEA 2021 之后的版本。

在 IDEA 里导入项目后,第一步确认 Project Structure 里的 Modules 是否识别了 Web 目录。路径是File -> Project Structure -> Modules -> 选中项目 -> 点 “+” -> Web,把 Web Resource Directory 指向src/main/webapp。如果这一步不设置,IDEA 根本不知道这是个 Web 项目,后面部署自然无从谈起。

第二步是配置 Artifacts。展开Project Structure -> Artifacts -> 点 “+” -> Web Application: Exploded -> From Modules,IDEA 会自动打包出一个 WAR 结构。这一步的目的是让 Tomcat 能直接加载编译后的 class 文件和 JSP。

第三步才是配置 Tomcat。点右上角Add Configuration -> “+” -> Tomcat Server -> Local,在 Deployment 标签里点击加号选 Artifact,Application context 填/shop,这样访问路径就是http://localhost:8080/shop。端口默认 8080 不用改,如果机器上 8080 被占用,改到 8088 再重启 Tomcat 即可。

Java 编译输出路径也顺手检查一下。默认out目录有时候会被 Git 忽略,部署时 Tomcat 找不到 class 就会报 404。我习惯在 Project Structure 里把 Output path 指定为项目目录/out,保证与 Artifact 的配置一致。配好这一切,点 Debug 绿色按钮,Tomcat 控制台输出Server startup in xxx ms,才算真正进入了开发状态。

3. 数据库设计与初始化脚本:商品、用户、订单三张表做到能答辩的程度

3.1 表结构设计:外键怎么加、字段怎么定,直接影响答辩印象分

购物商城的核心表大致是五张:用户表user、商品表product、购物车表cart、订单表orders、订单项表order_item。课程设计的评价标准不是表越多越好,而是每张表的存在都有清晰理由,字段类型选择能说出依据。

用户表至少包含id、username、password、phone、address、created_time这些基础字段。密码字段用VARCHAR(32)存储,如果你用了 MD5 加密就是 32 位。id用INT AUTO_INCREMENT做主键,这是最稳妥的自增主键方案。商品表要包含id、name、price、stock、image、description,其中price用DECIMAL(10,2)而不是FLOAT。这个细节会在答辩时被问到——浮点数存金额会产生精度误差,DECIMAL才是数据库里存钱的规范做法。

订单表orders要存id、user_id、total_price、status、order_time,user_id加外键关联到用户表。订单项表order_item存id、order_id、product_id、quantity、subtotal,order_id和product_id都加外键。购物车表可以先不建——很多课设用cart表存临时商品,但我更推荐用HttpSession存购物车,理由在后文避坑章节展开。先建表再插演示数据,是一次把数据库初始化做完,别让老师看你在答辩现场敲 SQL。

3.2 初始化 SQL 脚本:直接可执行的建表与演示数据

下面这份 SQL 是我放在项目src/main/resources/shop.sql里的标准初始化脚本,包含建库、建表和基础演示数据。复制到 Navicat 或命令行执行即可,执行前确认当前连接没有重名数据库。

CREATE DATABASE IF NOT EXISTS shop DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; USE shop; CREATE TABLE `user` ( `id` INT AUTO_INCREMENT PRIMARY KEY, `username` VARCHAR(20) NOT NULL UNIQUE, `password` VARCHAR(32) NOT NULL, `phone` VARCHAR(11) DEFAULT NULL, `address` VARCHAR(100) DEFAULT NULL, `created_time` DATETIME DEFAULT CURRENT_TIMESTAMP ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; CREATE TABLE `product` ( `id` INT AUTO_INCREMENT PRIMARY KEY, `name` VARCHAR(50) NOT NULL, `price` DECIMAL(10,2) NOT NULL, `stock` INT NOT NULL DEFAULT 100, `image` VARCHAR(200) DEFAULT NULL, `description` VARCHAR(500) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; CREATE TABLE `orders` ( `id` INT AUTO_INCREMENT PRIMARY KEY, `user_id` INT NOT NULL, `total_price` DECIMAL(10,2) NOT NULL, `status` TINYINT DEFAULT 0 COMMENT '0待付款 1已付款 2已发货', `order_time` DATETIME DEFAULT CURRENT_TIMESTAMP, CONSTRAINT `fk_order_user` FOREIGN KEY (`user_id`) REFERENCES `user`(`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; CREATE TABLE `order_item` ( `id` INT AUTO_INCREMENT PRIMARY KEY, `order_id` INT NOT NULL, `product_id` INT NOT NULL, `quantity` INT NOT NULL, `subtotal` DECIMAL(10,2) NOT NULL, CONSTRAINT `fk_item_order` FOREIGN KEY (`order_id`) REFERENCES `orders`(`id`), CONSTRAINT `fk_item_product` FOREIGN KEY (`product_id`) REFERENCES `product`(`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- 演示数据 INSERT INTO `user` (`username`, `password`) VALUES ('admin', 'e10adc3949ba59abbe56e057f20f883e'); INSERT INTO `product` (`name`, `price`, `stock`, `image`, `description`) VALUES ('Java核心技术 卷I', 89.00, 50, 'img/book1.jpg', 'Java基础经典教程'), ('Head First Java', 79.00, 30, 'img/book2.jpg', '入门推荐'), ('机械键盘', 299.00, 20, 'img/keyboard.jpg', '青轴 104键'), ('无线鼠标', 129.00, 40, 'img/mouse.jpg', '静音款');

这段脚本里有几个细节值得在答辩时讲:数据库和表的字符集统一用utf8mb4,这能同时兼容中文和特殊符号;金额字段全部用DECIMAL;订单状态用TINYINT存数字而不是字符串,减少存储开销,写代码时对应枚举值。外键用CONSTRAINT显式命名,规范且方便后续删除。

注意admin的密码字段存的是e10adc3949ba59abbe56e057f20f883e,这是字符串123456的 MD5 值。项目里注册功能也要用MD5加密后入库,这个前面说到的password VARCHAR(32)才能对得上。

3.3 JDBC 连接与增删改查封装:参数怎么配,代码才能跑通

数据库表建好之后,最关键的步骤是 JDBC 连接配置。很多项目跑到这一步报Access denied for user或Unknown database,基本原因都是配置文件里的参数与本地数据库不一致。我习惯建一个db.properties配置文件放在src/main/resources或src根目录,内容如下:

jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/shop?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai jdbc.username=root jdbc.password=123456

参数说明:useUnicode=true&characterEncoding=utf8保证中文不乱码;useSSL=false去掉 MySQL 8.0 的 SSL 警告;serverTimezone=Asia/Shanghai解决 MySQL 8.x 的连接时报时区错误。如果你用的是 MySQL 5.7,serverTimezone加不加都行;驱动类写法要注意版本差异——MySQL 5.x 用com.mysql.jdbc.Driver,MySQL 8.x 要换成com.mysql.cj.jdbc.Driver。这个坑每年都有人踩,报错信息是ClassNotFoundException的时候先查驱动类名。

连接工具封装成单例模式,避免每个 DAO 都重复写加载驱动代码。核心类DBUtil.java写法如下:

package com.shop.util; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; public class DBUtil { private static String driver = "com.mysql.jdbc.Driver"; private static String url = "jdbc:mysql://localhost:3306/shop?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai"; private static String username = "root"; private static String password = "123456"; static { try { Class.forName(driver); } catch (ClassNotFoundException e) { e.printStackTrace(); } } public static Connection getConnection() throws SQLException { return DriverManager.getConnection(url, username, password); } public static void close(Connection conn, PreparedStatement ps, ResultSet rs) { try { if (rs != null) rs.close(); } catch (SQLException e) { e.printStackTrace(); } try { if (ps != null) ps.close(); } catch (SQLException e) { e.printStackTrace(); } try { if (conn != null) conn.close(); } catch (SQLException e) { e.printStackTrace(); } } }

这里有个关键的工程习惯:所有资源必须用close()释放。虽然 Java 在连接对象被 GC 回收时会自动断开,但数据库连接是稀缺资源,频繁打开不关闭会把 MySQL 的连接数打满,项目跑几个小时就报Too many connections。这也是答辩老师喜欢问的点之一。

DAO 层以UserDAO为例,登录查询始终用PreparedStatement而不是Statement拼接字符串:

public User findByUsername(String username) { String sql = "SELECT * FROM user WHERE username = ?"; try (Connection conn = DBUtil.getConnection(); PreparedStatement ps = conn.prepareStatement(sql)) { ps.setString(1, username); ResultSet rs = ps.executeQuery(); if (rs.next()) { User user = new User(); user.setId(rs.getInt("id")); user.setUsername(rs.getString("username")); user.setPassword(rs.getString("password")); return user; } } catch (SQLException e) { e.printStackTrace(); } return null; }

?占位符配合setString赋值,根除了 SQL 注入,这是 JavaWeb 课设里必须体现的安全意识。ResultSet映射到User对象的这个代码模式,在商品查询、订单查询里完全复用,所以先把这个模板吃透,后面新增功能就是复制改表名和字段名的事。

4. 从源码到可运行:在 IDEA 里跑通购物商城的完整步骤

4.1 导入项目结构并配置 SDK 与依赖

拿到一份购物商城源码,不要急着点运行。先打开目录结构确认它是不是标准 Maven 工程。如果是 Maven 工程,项目根目录会有pom.xml;如果是普通 Web 工程,靠WEB-INF/web.xml识别。常见做法是 IDEA 里选File -> Open -> 选中项目目录 -> 提示是否加载 Maven 项目时点 OK,然后让 IDEA 自动下载依赖。

JavaWeb 课设通常需要三个依赖:Servlet API(javax.servlet-api)、JDBC 驱动(mysql-connector-java)、JSTL 标签库(jstl和taglibs-standard-impl)。不要自己下载 jar 包往WEB-INF/lib里塞,Maven 管理版本更省事,也避免把 Tomcat 自带的 servlet-api 与项目里的版本冲突。这里最容易踩的坑是:Tomcat 8.5 自带的是javax.servlet3.1/4.0,如果你用了jakarta.servlet的依赖,启动就报ClassNotFoundException。

非 Maven 工程的话,需要手动确认WEB-INF/lib下有mysql-connector-java-x.x.x.jar。很多源码作者会忘记提交依赖包,导致别人的机器上跑不起来。在 IDEA 里可以File -> Project Structure -> Libraries -> “+” -> Java手动添加。逻辑就是:源码里有的依赖优先用源码的,缺的再补。

4.2 配置 Tomcat 并完成部署全流程

这是最容易耗时间的环节,我称为“一次配好、后面不翻车”的关键节点。按以下顺序操作,能避开大部分 404 和端口占用问题。

打开Run -> Edit Configurations -> “+” -> Tomcat Server -> Local,先填 Tomcat 安装路径。注意 IDEA 新版不再自带 Tomcat 插件,如果你用的 2023.3+ 版本在菜单里找不到 Tomcat Server,先检查是否安装了 Smart Tomcat 插件,或者直接使用 Community 版配合Smart Tomcat也能跑。

配置界面里Deployment标签页点+ -> Artifact -> 选项目名:war exploded,然后Application context填/shop。这个 context 路径就是访问入口的一部分,后面所有跳转链接都要带这个前缀。同时切到Server标签页,把Open browser的下拉改成Default Browser,URL填http://localhost:8080/shop,不然启动后打开的地址不对,自己还不知道为什么。

一切就绪后点 Debug 启动,看控制台输出。正常流程是在Initializing Spring FrameworkServlet之类信息之前,出现一行INFO: Deployment of web application archive ... has finished in xxx ms。注意 Tomcat 默认端口 8080 如果被其它进程占用,启动会直接 Failed,解决办法是把 HTTP port 改成8081,并在浏览器手动访问http://localhost:8081/shop。

4.3 登录注册和商品列表的完整链路代码走读

跑通项目后,应该顺着一个用户操作完整走一遍代码,这是答辩环节的基本要求。以“用户登录”为例,讲解顺序是:浏览器提交表单 →LoginServlet收到请求 → 调用UserService.login()→UserDAO.findByUsername()查库 → 比对密码 → 跳转首页。

LoginServlet.java核心代码:

package com.shop.servlet; import com.shop.entity.User; import com.shop.service.UserService; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.io.IOException; @WebServlet("/login") public class LoginServlet extends HttpServlet { private UserService userService = new UserService(); @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.setCharacterEncoding("UTF-8"); String username = req.getParameter("username"); String password = req.getParameter("password"); User user = userService.login(username, password); if (user != null) { HttpSession session = req.getSession(); session.setAttribute("user", user); resp.sendRedirect(req.getContextPath() + "/product/list"); } else { req.setAttribute("errorMsg", "用户名或密码错误"); req.getRequestDispatcher("/jsp/login.jsp").forward(req, resp); } } }

参数说明:req.setCharacterEncoding("UTF-8")必须放在读取任何getParameter之前,否则用户输入的中文会乱码;@WebServlet("/login")是 Servlet 3.0 之后的注解写法,省掉了在web.xml里配置映射的步骤。sendRedirect是重定向,地址栏会变,forward是转发,地址栏不变且能通过request.setAttribute传值。这个区别也是答辩高频题。

商品列表环节,ProductListServlet查询所有商品并转发给 JSP,JSP 里用 JSTL 标签循环渲染:

<c:forEach items="${productList}" var="p"> <div class="col-md-4"> <div class="thumbnail"> <img src="${p.image}" alt="${p.name}"> <div class="caption"> <h3>${p.name}</h3> <p>价格:¥${p.price}</p> <p>库存:${p.stock}</p> <a href="${pageContext.request.contextPath}/cart/add?pid=${p.id}" class="btn btn-primary">加入购物车</a> </div> </div> </div> </c:forEach>

这里pageContext.request.contextPath是动态获取项目路径的 JSP 内置对象,作用是无论你的 Application context 配成/shop还是/mall,链接都能正确拼接。项目里所有静态资源引用和超链接都应该用这个方式,而不是写死/shop/xxx。写死了项目改名或换 context 就得全文替换,属于新手最容易在原源码上改出新问题的操作。

5. 购物商城部署常见问题排查:连不上库、乱码、404 的 4 条真实踩坑记录

5.1 数据库连接失败:驱动、时区、端口三类原因

现象一:Tomcat 启动正常,页面一调登录接口就报SQLException: Access denied for user 'root'@'localhost' (using password: YES)。原因不是密码写错就必须去翻数据库,大多数时候是 IDEA 里加载的db.properties不是项目用的那份。比如源码里是password=123456,你本地 root 密码是admin123,但改动文件后 IDEA 没重新编译资源文件,运行用的还是旧 classpath 下的配置。

解决:检查target/classes或out/production下同名 properties 文件的内容是不是最新值,清除后重新 Build 一次。另一个隐蔽原因是 MySQL 8.0 默认的caching_sha2_password插件,老版本驱动不认。换成com.mysql.cj.jdbc.Driver并更新驱动版本到 8.0.x 即可。

现象二:Access denied之前还经常报Could not create connection to database server,原因是一个容易被忽略的参数——serverTimezone=Asia/Shanghai。MySQL 8.x 对时区严格校验,连接串里不带serverTimezone就会直接拒绝连接。解决方式是在 URL 末尾追加该参数,这是 javaweb 连接 mysql 数据库时最容易漏掉的细节。

现象三:Connection refused。端口不通时优先思考是不是 MySQL 实际监听端口不是 3306,本机装了多个 MySQL 实例是常见情况。用命令行netstat -ano | findstr 3306查一下端口占用,确认后修改连接串端口即可。

5.2 页面全部中文乱码:请求、响应、数据库三层都要处理

购物商城这种带商品名称、用户中文名的项目,乱码出现的位置分三层:请求参数乱码(用户注册输入姓名变问号)、响应输出乱码(JSP 页面中文乱码)、数据库存取乱码(Java 传进 MySQL 变问号)。

第一层解决:JSP 文件顶部写<%@ page contentType="text/html;charset=UTF-8" language="java" %>,同时所有doPost方法第一行写req.setCharacterEncoding("UTF-8")。这步的作用是 POST 请求体按 UTF-8 解码,不写则默认按 ISO-8859-1 解析,中文必然变乱码。

第二层解决:Servlet 响应前设置resp.setContentType("text/html;charset=UTF-8")。JSP 本质上也是 Servlet,顶部声明了 contentType 就等同于设置了响应编码。

第三层解决:数据库连接串加characterEncoding=utf8,建库语句用utf8mb4。MySQL 里查看实际编码用SHOW VARIABLES LIKE 'character_set%';,如果character_set_database不是 utf8,执行ALTER DATABASE shop CHARACTER SET utf8mb4;再重启连接。血泪经验是三层缺一不可,而且如果依然乱码,重启 IDEA 和 MySQL 再测一次——热部署下编码改动有时不生效。

5.3 部署后全部 404:Artifact 没配置或 context 路径不一致

现象:Tomcat 正常启动,首页也能看到,但点击任何登录、注册链接都 404。最常见的根源是 IDEA 里配置的Application context是/,而项目 JSP 里所有链接写的是${pageContext.request.contextPath},运行时拼出来的路径与 Servlet 注解里的/login对不上。

解决:第一步核对Run/Debug Configurations里的 Deployment 标签里 Artifact 是否为空。如果 Artifact 为空,说明 Web 目录没被识别,Tomcat 部署的是一个空壳,页面能看到是因为 JSP 文件直接被系统目录服务加载,但任何 Servlet 请求都找不到类。处理方式回到Project Structure -> Artifacts重新生成 War Exploded。

第二步核对访问路径。所有跳转都从http://localhost:8080/shop/login进入,如果提示“源服务器没有返回任何内容”,是 Artifact 配置错了;如果 404 页面是 Tomcat 默认的白色页,就是路径不匹配。我一般用http://localhost:8080/shop/product/list做验证路径,因为它是一个 Servlet 转发 JSP 的完整链路,不会出现静态资源能开但动态请求全挂的误判。

5.4 添加购物车功能:HttpSession 方案与数据库方案怎么选

在写购物车时最纠结的是要不要建cart表。建表看起来更“数据库操作丰富”,但带来两个实际问题:一是购物车属于临时数据,存数据库需要反复增删改查,代码量翻倍;二是答辩时老师问“购物车为什么不支持游客”,用数据库就得给游客分配临时 user_id,这套设计复杂度对课设来说过了边界。

我一般推荐用HttpSession存购物车,用一个HashMap<Integer, Integer>,key 是商品 id,value 是数量。核心逻辑如下:

HttpSession session = req.getSession(); Map<Integer, Integer> cart = (Map<Integer, Integer>) session.getAttribute("cart"); if (cart == null) { cart = new HashMap<>(); session.setAttribute("cart", cart); } int pid = Integer.parseInt(req.getParameter("pid")); cart.put(pid, cart.getOrDefault(pid, 0) + 1); resp.sendRedirect(req.getContextPath() + "/product/list");

这套方案免了cart表和配套 DAO,把重心留在“生成订单”这个更关键的业务环节。订单生成时程式中读取 session 里的 cart,循环计算总价,插入orders表后逐条插order_item,这条链路能完整讲清楚事务概念,比单纯展示一张 cart 表的增删改查更有答辩含金量。

6. 答辩前把项目调到“满分”状态:三分钟验证清单与两个加分小技巧

项目跑通只是及格线。在最终提交之前,我会按以下顺序做一次全流程回归验证:清空浏览器缓存,用admin / 123456登录;注册一个新用户,确认用户名、手机号、地址中文不乱码;逐个商品点击“加入购物车”,购物车页面确认数量累加;提交订单,确认订单表新增记录、商品库存减少;退出登录,再访问购物车页面,确认被拦截跳转登录页。这一套跑完不出问题,才是安全的提交状态。

加分技巧有两个,都能在少改代码的前提下提升答辩印象。

第一个是给密码字段加一个简单的 MD5 加密。注册和登录时用MD5类工具函数处理明文密码再比对,然后在答辩时主动向老师说明“数据库里存的是摘要而不是明文”,这比页面加十个动画都有效。

第二个是在订单生成时用一个事务注解或手动setAutoCommit(false),保证“插入订单表 + 插入订单项表 + 扣减库存”三步要么全成功要么全回滚。只要代码里出现了conn.setAutoCommit(false)和conn.commit(),你就把一个 CRUD 项目拉开到了企业级设计思路。

最后说句实在话:一份课设源码拿到手,别直接交,把它从头到尾跑一遍、把每一层代码都读通。你能不看书讲出“登录请求从 JSP 到 Servlet 再到 DAO 最后返回的完整链路”,比源码本身更能拿分。这个习惯我保持到现在做项目也一直在用,希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询