☰
JavaWeb网上购物系统课设:JSP+Servlet与SSM部署答辩指南
2026/10/9 14:49:21 网站建设 项目流程

简介:这是一份基于JSP+Servlet+MySQL的网上在线购物系统期末课程设计项目,面向JavaWeb初学者和需要提交期末作业的学生。项目已在MyEclipse中整理完毕,内置前端页面、后端业务逻辑与数据库脚本,拿来即可运行;使用前只需修改课程报告中的学号姓名等个人信息,代码无需调整。压缩包共2000个文件,大小33.8MB,包括484个html、436个css、342个js等前端静态资源,77个java与77个class构成的Servlet控制层,43个jsp动态页面,以及jar依赖、sql脚本、xml配置等,结构清晰,便于对照学习。项目覆盖商品展示、购物车、订单、后台管理等典型电商模块,控制器、业务层和工具类分模块组织,适合快速理解JSP+Servlet+MVC开发流程,也可作为课程设计报告和答辩的实操基础。已有99人学习下载,适合拿来即用的期末课程设计参考。

1. 期末周拿到 JavaWeb 课程设计压缩包:网上在线购物系统该怎么下手

期末周还剩两天,你刚解压完一份「JavaWeb期末课程设计(JSP+Servlet)(mysql)-网上在线购物系统SSM+MyEclipse.rar」,里面一堆文件夹、若干个.java、一坨.jsp和一份从没打开过的.sql。这份网上在线购物系统课设包,本质上是一套包含手写 JSP+Servlet 版和 SSM 框架版两套实现的电商项目,数据库用 MySQL,工程文件由 MyEclipse 生成,只要环境对了就能直接部署到 Tomcat 跑起来。它最有价值的用法不是解压后原封不动交上去,而是花一个晚上把它跑通、读懂、再改掉其中一个模块——能讲清楚每个 Servlet 为什么存在,才是答辩拿高分的分水岭。这篇笔记就是按这个路径来的。

2. 读懂课设包的技术底牌:JSP+Servlet 与 SSM 的取舍

2.1 一套购物系统为什么会有 JSP+Servlet 和 SSM 两套写法

网上流传的 JavaWeb 期末课设包,解压后常见两种情况:要么是两个独立工程目录并列,一个叫shop_jsp、一个叫shop_ssm;要么是同一个工程里主代码用 JSP+Servlet 手写,局部模块引入了 Spring 系写法。标题里四个关键词并排出现,本质上是在告诉你:这份代码是「手写 MVC」和「框架版 MVC」的对照样本。

JSP+Servlet 版是 JavaWeb 课设的底线要求,也是答辩时最好讲的方案。请求先进 Servlet 的doGet/doPost,Servlet 调 DAO 层,DAO 用 JDBC 拼 SQL 访问 MySQL,最后forward到 JSP 渲染页面。整套流程没有黑匣子,断点打在哪、数据走到哪一步,全都能肉眼看见。缺点是代码量大,一个商品列表功能从 Servlet 到 DAO 要写四五个类,重复的 JDBC 样板代码到处都是。

SSM 版(Spring + SpringMVC + MyBatis)则把这些重复劳动压缩掉了。Controller 里一个方法就是一个接口,MyBatis 的 Mapper 接口加一条 XML 就能完成查询,事务由 Spring 声明式接管。代码少了,但要求你理解 IoC 容器、Mapper 代理、依赖注入这些概念——如果只是为了交课设,讲不清这些概念反而会被老师追问到卡壳。

我的建议很明确:时间不够就把主精力放在 JSP+Servlet 那套实现上,SSM 版当作一句加分话术来准备,例如「我还对比了 MyBatis 重构 DAO 层的方案,能减少大约 60% 的样板代码」。下表是两套方案的真实取舍。

对比项JSP+Servlet 版SSM 版
架构分层JSP + Servlet + DAO + JDBCJSP + Controller + Service + Mapper
核心依赖servlet-api、jstl、mysql-connectorspring-webmvc、mybatis、连接池
学习门槛低,每个请求路径都看得见中高,要先理解 IoC 与映射
答辩友好度高,能讲清每一步在干什么更高,但讲不清反而暴露短板
期末投入产出比优先跑通作为加分项展示

2.2 启动前先核验环境:JDK、Tomcat、字符集一个都不能少

说句血泪经验:课设包打开后满屏红叉,九成不是代码问题,是环境不匹配。MyEclipse 导出的工程对 JDK 版本、Target Runtime、字符集非常敏感,任何一项对不上,编译器都会先给你制造几十个假错误。

核验顺序按下面这张表来,从上到下一次过完,能省掉后面大半的排错时间。

检查项建议配置不匹配时的典型症状
JDK1.8(老工程也可用 1.7)源码编译报错、UnsupportedClassVersionError
Tomcat与 JDK 对应的 8.x / 9.x启动闪退、Context 加载失败
工程字符集UTF-8页面中文乱码、注释乱码
MySQL5.7 或 8.x驱动类找不到、时区报错
MyEclipse与导出版本相近即可工程无法识别、缺失运行时

具体操作不复杂。启动 MyEclipse 后,先打开Window -> Preferences -> Java -> Compiler,确认编译级别是 1.8;再到Window -> Preferences -> Servers -> Runtime Environments里添加本机的 Tomcat,路径别选到 Tomcat 的二级目录;最后选中项目按Alt+Enter,在Resource面板看Text file encoding是否为 UTF-8。这三步做完,再谈导入工程。

2.3 MySQL 侧的表结构:用户、分类、商品、订单、订单明细五张核心表

网上购物系统的答辩环节,老师最爱问的不是「页面怎么跳」,而是「表怎么设计的」。哪怕代码是下载的,表结构你得能画出来、讲明白。一个满足课设要求又不至于过度设计的库,通常只有五张核心表,再按需加一张管理员表就够了。

表名作用关键字段
user前台用户uid、username、password、nickname、create_time
category商品分类cid、cname
goods商品表gid、cid、gname、price、stock、pic、description
orders订单主表oid、uid、order_no、total、status、create_time
order_item订单明细item_id、oid、gid、quantity、price

这里有一个容易踩的命名问题:订单表不要叫order,ORDER是 SQL 保留字,你写SELECT * FROM order会直接语法报错。常见的处理是表名用orders,字段名order_no又加唯一索引,因为一个用户的一次下单要对应订单主表一条记录、明细表多条记录,order_no是人工可读的订单号,而oid是自增主键。

还有一个容易被问懵的问题:「购物车怎么不建表?」。课设级别的购物车通常不落库,而是存在 Session 里,理由在第 4 章会展开——用户没点结算之前,购物车只是临时状态,没有必要写数据库。你只要在答辩时把「临时状态用 Session、持久状态用表」这句话说出来,老师基本不会再追问。

3. 把 rar 变成本地可运行:数据库初始化、JDBC 配置与 Tomcat 部署

3.1 先让 MySQL 有数据:初始化库表的 SQL 脚本与字符集参数

绝大多数课设包都会附带一份.sql,但直接导入经常会因为编码不对出现中文乱码。正确做法是先建库,指定字符集为utf8mb4,再切库执行建表语句。utf8mb4是utf8的超集,商品名称里万一有 Emoji 或者生僻字也不会存坏。

下面是这套网上在线购物系统最基本的初始化脚本,按顺序执行即可:

-- 建库:指定 utf8mb4,避免中文乱码,排序规则选 utf8mb4_general_ci CREATE DATABASE IF NOT EXISTS shop_db DEFAULT CHARACTER SET utf8mb4 DEFAULT COLLATE utf8mb4_general_ci; USE shop_db; -- 用户表:username 唯一,password 存处理后密文,不存明文 CREATE TABLE user ( uid INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(50) NOT NULL UNIQUE, password VARCHAR(64) NOT NULL, nickname VARCHAR(50), create_time DATETIME DEFAULT CURRENT_TIMESTAMP ) ENGINE=InnoDB; -- 商品分类表 CREATE TABLE category ( cid INT PRIMARY KEY AUTO_INCREMENT, cname VARCHAR(50) NOT NULL ) ENGINE=InnoDB; -- 商品表:price 用 DECIMAL 存精确小数,不用 FLOAT CREATE TABLE goods ( gid INT PRIMARY KEY AUTO_INCREMENT, cid INT NOT NULL, gname VARCHAR(100) NOT NULL, price DECIMAL(10,2) NOT NULL, stock INT DEFAULT 0, pic VARCHAR(200), description TEXT, KEY idx_cid (cid) ) ENGINE=InnoDB; -- 订单主表:order_no 唯一,status 用 TINYINT 表示状态 CREATE TABLE orders ( oid INT PRIMARY KEY AUTO_INCREMENT, uid INT NOT NULL, order_no VARCHAR(32) NOT NULL UNIQUE, total DECIMAL(10,2) DEFAULT 0, status TINYINT DEFAULT 0, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, KEY idx_uid (uid) ) ENGINE=InnoDB; -- 订单明细表:一条订单对应多条商品记录 CREATE TABLE order_item ( item_id INT PRIMARY KEY AUTO_INCREMENT, oid INT NOT NULL, gid INT NOT NULL, quantity INT NOT NULL, price DECIMAL(10,2) NOT NULL, KEY idx_oid (oid) ) ENGINE=InnoDB;

这段脚本的逻辑核心是两点:一是所有表都用 InnoDB,因为下单时要靠事务保证扣库存和写订单的一致性,MyISAM 不支持事务,用了会埋雷;二是price全部用DECIMAL(10,2),商品金额精确到分,用FLOAT/DOUBLE会出现 0.1+0.2 不等于 0.3 的浮点误差,这在答辩现场演示时非常尴尬。执行方式可以直接在命令行mysql -u root -p < init.sql,也可以在 Navicat 之类的图形工具里打开文件后整段运行。

提示:如果你拿到的.sql文件是 Windows 记事本保存的,双击运行前先确认文件编码是 UTF-8 或 GBK 之一,否则中文注释和中文数据会以乱码形式写进表里。

3.2 JDBC 连接参数:驱动类、时区与 SSL 的三种报错根源

建好库表之后,代码能不能连上 MySQL,瓶颈几乎全在那串 JDBC URL 和驱动类名上。课设包里的JdbcUtils.java是连接入口,不同 MySQL 版本要用的驱动类不一样,这是新手最容易翻车的地方。

下面这个工具类是最常见、最稳的写法:

import java.sql.*; public class JdbcUtils { // useSSL=false 关闭 SSL 告警,serverTimezone 指定时区,编码指 UTF-8 private static final String URL = "jdbc:mysql://localhost:3306/shop_db?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai"; private static final String USER = "root"; private static final String PASSWORD = "改成你自己的数据库密码"; static { try { // MySQL 8.x 驱动类;5.x 用的是 com.mysql.jdbc.Driver Class.forName("com.mysql.cj.jdbc.Driver"); } catch (ClassNotFoundException e) { e.printStackTrace(); } } public static Connection getConnection() throws SQLException { return DriverManager.getConnection(URL, USER, PASSWORD); } public static void close(Connection conn, Statement stmt, ResultSet rs) { // 关闭顺序:rs -> stmt -> conn,防止连接泄漏 if (rs != null) { try { rs.close(); } catch (SQLException e) { } } if (stmt != null) { try { stmt.close(); } catch (SQLException e) { } } if (conn != null) { try { conn.close(); } catch (SQLException e) { } } } }

这段代码里最关键的三个参数分别是:characterEncoding=UTF-8保证中文正常存取;serverTimezone=Asia/Shanghai解决 MySQL 8.x 默认时区跟本地时区不一致导致的报错;useSSL=false关闭本地开发环境用不到的 SSL 握手。三个参数少任何一个,启动时都有可能抛出异常或者插入中文变问号。

注意:如果你的 MySQL 是 5.7,驱动类仍然写com.mysql.jdbc.Driver没问题;如果是 8.x,建议把代码改成com.mysql.cj.jdbc.Driver,同时把mysql-connector-java的 jar 换成 8.x 对应版本。驱动 jar 必须放在WEB-INF/lib下,而不是只放在项目的 Build Path 里,否则部署到 Tomcat 后运行时依然找不到类。

3.3 Tomcat 部署三步:导入项目、绑定运行时、确认 context-root

数据库就绪、连接类就绪,接下来是把工程跑在 Tomcat 上。MyEclipse 里导入课设工程和普通 Eclipse 稍有不同,步骤固定为三步,顺序错了会出现各种奇怪问题。

第一步,确认 MySQL 服务已经启动。Windows 下可以用命令行快速验证:

# 查看 MySQL 是否在运行 net start | findstr -i mysql # 如果没看到结果,按服务名启动,MySQL80 是 8.x 的默认服务名 net start MySQL80

第二步,导入工程。在 MyEclipse 里执行File -> Import -> Existing Projects into Workspace,目录选择解压后包含.project文件的那一层。如果导入时提示No projects are found,说明你选错了层级,往上一级或下一级找。导入后如果项目名带红色感叹号,执行Project -> Clean...让它重新编译一轮,大部分假红叉会消失。

第三步,绑定 Tomcat 运行时并启动。选中项目按Alt+Enter,在Targeted Runtimes里勾选本机已配置的 Tomcat;然后在Servers视图右键 Tomcat 选择Add and Remove...,把项目添加进去,最后启动 Tomcat。浏览器访问地址通常是:

http://localhost:8080/工程名/

这里最容易踩的是 context-root 和工程名不一致的问题。MyEclipse 默认 context-root 与工程名相同,但有的课设包在.settings里改过部署名。右键项目Properties -> Web Context Root能直接看到实际值,改完之后要重启 Tomcat 才会生效。如果你访问 404,先查这里,别急着怀疑代码。

4. 核心业务代码拆解:登录会话、购物车与下单事务的落地写法

4.1 用 Filter 拦截未登录用户:登录鉴权的两种边界情况

网上在线购物系统的受保护资源是购物车、订单确认、个人中心这类需要登录才能访问的页面。用 Servlet 一个个判断登录状态太蠢,最常见做法是写一个过滤器,把未登录请求统一挡回登录页。

public class LoginFilter implements Filter { @Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) res; // 注意 getSession(false) 不会主动创建 Session,避免给每个匿名用户都种一个 Session HttpSession session = request.getSession(false); if (session == null || session.getAttribute("loginUser") == null) { // 未登录:跳回登录页,并带上来源路径,登录后可以跳回来 response.sendRedirect(request.getContextPath() + "/login.jsp?redirect=" + request.getRequestURI()); return; } // 已登录:放行,继续走业务 Servlet chain.doFilter(request, response); } }

这段过滤器的关键细节是request.getSession(false)里的false。网上很多旧代码写成getSession(),会把所有游客都强制创建 Session,购物车逻辑一旦依赖 Session 就会混入大量空数据。放行条件判断的是 Session 里的loginUser属性,这个属性在登录成功时由 LoginServlet 写入。

在web.xml里配置过滤范围时要注意两个边界情况。第一个是过滤路径别覆盖到登录页本身,否则会死循环跳转;第二个是login.jsp里的静态资源(CSS、JS)最好也放行。常见配置如下:

<filter> <filter-name>LoginFilter</filter-name> <filter-class>com.shop.filter.LoginFilter</filter-class> </filter> <filter-mapping> <filter-name>LoginFilter</filter-name> <url-pattern>/cart/*</url-pattern> <url-pattern>/order/*</url-pattern> </filter-mapping>

4.2 购物车用 Session 存而不是建表:按商品 ID 合并数量的实现

第 2 章留下一个问题:购物车为什么不用表?原因很简单——购物车是用户浏览过程中的临时状态,用户可能加购后直接关浏览器,也可能逛了半天一件都没结算。为临时状态建表意味着每次加购都要写一次库,课设项目完全没必要。标准做法是把购物车对象放进 Session,用户登录时创建,会话过期自动销毁。

购物车结构上,key是商品 ID,value是购物车条目,这样同一个商品反复加购时会自动合并数量:

public class Cart { // 用商品ID作 key:加购同一商品时合并数量,而不是追加两条记录 private Map<Integer, CartItem> items = new HashMap<>(); public void add(Integer gid, CartItem newItem) { CartItem old = items.get(gid); if (old == null) { items.put(gid, newItem); } else { // 合并数量,保留原单价 old.setQuantity(old.getQuantity() + newItem.getQuantity()); } } public void remove(Integer gid) { items.remove(gid); } public void clear() { items.clear(); } // 遍历条目计算总价,结算时以这个为准 public double getTotal() { double total = 0; for (CartItem item : items.values()) { total += item.getPrice() * item.getQuantity(); } return total; } }

这里有两个容易写歪的地方。第一个是合并逻辑:有的同学加购时直接items.put(gid, newItem),把数量覆盖了,用户加两次购物车数量还是 1,这是典型的逻辑 bug。第二个是把总价的浮点运算直接double到底,合计金额出现 0.999999 之类的尾巴。稳妥的做法是金额都用BigDecimal,或者在CartItem里把价格字段直接用BigDecimal,getTotal()里也全程用BigDecimal,避免答辩演示时被老师看出浮点问题。

购物车的 Servlet 调用也比较固定:doPost里取gid和quantity参数,构造CartItem塞进Cart,然后session.setAttribute("cart", cart)。注意每次加购都要重新setAttribute,只改Cart对象内部状态而不写回 Session,页面刷新时读到的还是旧数据。

4.3 下单事务:扣库存与写订单必须绑定在同一个事务边界里

购物车只是热身,整个课设里最值得讲、也最容易被老师追问的,是下单操作。一次下单要做三件事:插入订单主表记录、批量插入订单明细、扣减商品库存。这三件事要么全成功,要么全回滚,否则就会出现「订单建了库存没减」或者「库存扣了订单没建」的脏数据。

用 JDBC 手写事务的常见写法是这样的:

Connection conn = null; try { conn = JdbcUtils.getConnection(); // 关闭自动提交,事务边界从这里开始 conn.setAutoCommit(false); // 1. 插入订单主表,返回自增主键 oid String insertOrder = "INSERT INTO orders (uid, order_no, total, status) VALUES (?, ?, ?, 0)"; PreparedStatement psOrder = conn.prepareStatement(insertOrder, Statement.RETURN_GENERATED_KEYS); psOrder.setInt(1, uid); psOrder.setString(2, orderNo); psOrder.setBigDecimal(3, total); psOrder.executeUpdate(); ResultSet keys = psOrder.getGeneratedKeys(); keys.next(); int oid = keys.getInt(1); // 2. 逐条插入订单明细 String insertItem = "INSERT INTO order_item (oid, gid, quantity, price) VALUES (?, ?, ?, ?)"; for (CartItem item : cartItems) { PreparedStatement psItem = conn.prepareStatement(insertItem); psItem.setInt(1, oid); psItem.setInt(2, item.getGid()); psItem.setInt(3, item.getQuantity()); psItem.setBigDecimal(4, item.getPrice()); psItem.executeUpdate(); } // 3. 扣库存:stock >= ? 条件防止超卖,影响行数为0说明库存不足 String deductStock = "UPDATE goods SET stock = stock - ? WHERE gid = ? AND stock >= ?"; PreparedStatement psStock = conn.prepareStatement(deductStock); for (CartItem item : cartItems) { psStock.setInt(1, item.getQuantity()); psStock.setInt(2, item.getGid()); psStock.setInt(3, item.getQuantity()); int rows = psStock.executeUpdate(); if (rows == 0) { // 库存不足,直接抛异常触发回滚 throw new RuntimeException("商品库存不足: " + item.getGid()); } } conn.commit(); } catch (Exception e) { if (conn != null) { conn.rollback(); } throw e; } finally { if (conn != null) { conn.setAutoCommit(true); conn.close(); } }

这段代码里最值得在答辩时强调的是UPDATE goods SET stock = stock - ? WHERE gid = ? AND stock >= ?这个写法。它把「库存判断」和「库存扣减」合并成一条原子 SQL,而不是先SELECT stock判断再UPDATE。后者在两个请求并发时会读到同一个库存值,导致超卖;前者依靠数据库行锁和条件更新,从根上避免这个问题。

提示:如果你手头课设包里的下单代码是先查库存再更新,建议花十分钟改成上面这条 SQL。这是整篇代码里性价比最高的一次改动,既能防止逻辑错误,又能在答辩时主动讲出「我考虑了并发超卖」,这一个点就能拉高评分。

5. 购物系统课设避坑指南:红叉、404、乱码等 5 个高频事故

5.1 项目导入后满屏红叉,启动时报 ClassNotFound

现象:工程导入 MyEclipse 后,项目名带红叉,展开全是红色波浪线;强行走Run on Server,Tomcat 控制台抛java.lang.ClassNotFoundException: com.mysql.cj.jdbc.Driver,或者报某个 Servlet 类找不到。

原因:绝大多数情况是 JDK 编译级别和 Tomcat 运行时版本与工程配置不一致,导致 MyEclipse 无法解析工程依赖;驱动类找不到则是mysql-connector-java.jar没被复制到WEB-INF/lib,只在 Build Path 里引用了源码路径,部署时没用上。

解决:先Project -> Clean清一次编译缓存;再检查Properties -> Java Compiler的编译级别和Properties -> Targeted Runtimes里的 Tomcat;最后打开WebContent/WEB-INF/lib目录,确认驱动 jar 真实存在,不存在就把驱动包直接拖进去,然后重新部署。

5.2 Tomcat 正常启动,访问项目却是 404

现象:Tomcat 启动日志里没有任何报错,访问http://localhost:8080/工程名/却显示 404,但访问 Tomcat 默认主页正常。

原因:工程没有被部署到 Tomcat,或者部署后的 context-root 和实际访问路径不一致。MyEclipse 里有多个 Tomcat 实例时,项目可能被部署到了另一个 Tomcat 上;context-root 被改过也是常见原因。

解决:在Servers视图双击当前 Tomcat,打开Modules页签看部署列表里是否有这个工程,Path 列就是 context-root。没有就点Add Web Module加上;路径不对就点Edit改成实际想要的路径。改完重启 Tomcat 再看一次。

5.3 数据库连不上:驱动类与时区是最常见的两类根源

现象:启动后访问商品列表,页面报 500,控制台堆栈里有Communications link failure或The server time zone value '�й���ʱ��' is unrecognized。

原因:前者通常是 MySQL 8.x 的驱动连接串没加serverTimezone参数,或者驱动 jar 版本和 MySQL 版本不匹配;后者是连接串里的时区参数值写错,用了系统不认的时区名。

解决:先把驱动 jar 升级到和 MySQL 大版本对应的版本,再确认连接串完整:serverTimezone=Asia/Shanghai是最通用的时区写法;如果 MySQL 服务器端口不是默认 3306,要在连接串里改成实际端口,localhost:3307这种端口错误同样会报连接失败。用户名和密码单独排查,root的密码如果含特殊字符,记得做 URL 转义。

5.4 中文乱码:页面、连接串、数据库三层编码不一致

现象:页面商品名称显示成???或者类似��的乱码;后台插入数据库的数据在 SQL 客户端里看也是乱码。

原因:三层编码不一致。JSP 页面没声明 UTF-8、JDBC 连接串缺characterEncoding=UTF-8、数据库表用的是latin1编码,这三处只要有一处对不上,中文就会在传输过程中变质。

解决:按顺序排查。第一步,打开所有 JSP,确认开头有pageEncoding="UTF-8";第二步,检查JdbcUtils里连接串有useUnicode=true&characterEncoding=UTF-8;第三步,用SHOW CREATE TABLE goods看表字符集,不是utf8mb4就执行ALTER TABLE goods CONVERT TO CHARACTER SET utf8mb4。另外web.xml里加一个字符集过滤器,统一把所有请求的编码设成 UTF-8,是最彻底的解决办法。

5.5 商品图片全部不显示:路径没有站在 Web 容器的视角写

现象:页面结构正常,文字都能显示,但所有商品图片都是裂图,查看浏览器控制台,图片资源报 404。

原因:课设代码里图片路径写了绝对磁盘路径,比如D:/upload/a.jpg,或者写在源码src目录下的图片发布后压根没被复制到部署目录。浏览器最终访问的路径是http://localhost:8080/工程名/xxx.jpg,这个路径只存在于 Web 容器的部署目录里,和源码目录不是一回事。

解决:把图片放到WebContent/upload/目录下,JSP 里用${pageContext.request.contextPath}/upload/xxx.jpg拼接,这样部署到哪个路径都能自适应。如果图片是运行时上传的,正确做法是在 Tomcat 里配置虚拟目录映射到磁盘路径,而不是直接在页面里写死D:/。这个坑改起来不难,但几乎是课设项目图片问题的通病。

6. 能跑只是及格,能讲才是加分:答辩验证清单与三个必做小改造

把系统跑通之后,别急着关机,先按下面的清单走一遍手工验证,每一行都代表答辩时老师可能现场点的操作。

验证场景操作方式预期结果
未登录访问购物车直接输入/cart/listURL跳转登录页,不报 500
普通用户越权修改订单 URL 中 oid无法查看他人订单
库存不足下单把某商品库存改成 1,购物车加 2 件结算提示库存不足,订单未生成
SQL 注入尝试搜索框输入' OR 1=1 --返回空结果,不报错
重复提交订单结算页快速点两次提交只生成一笔订单

这三个必须做的小改造,按投入产出比排序:

第一个,把 JSP 里所有的 JDBC 代码挪到 DAO 层。很多下载的课设把Connection直接写在 JSP 的<% %>里,答辩老师翻开页面源码一眼就能看出来,这一下印象分就没了。只需要复制粘贴到单独的GoodsDao.java,JSP 里改成调用 DAO 方法,半小时搞定。

第二个,把登录密码从明文改成哈希存储。如果课设包里的user表密码是明文,至少把注册逻辑改成存储哈希值,登录时比对哈希结果。不用引入框架,JDK 自带的MessageDigest就能算 SHA-256,代码量不超过十行,但「密码不落明文」这个意识在答辩里是实打实的加分项。

第三个,给商品列表加分页。SELECT * FROM goods LIMIT offset, size加两个参数就能实现,前端页面加一个上一页/下一页的链接。分页是老师最爱问的功能点之一,做了就能聊,没做就只能答「没做」。

最后说一个我的教训。之前帮一位同学看课设,功能全跑通了,但搜索框输入一个单引号直接报 SQL 语法错误,原因是代码里用的是字符串拼接 SQL。从那之后我养成一个习惯:课设代码里只要出现 SQL 拼接,一律改成PreparedStatement占位符;页面里只要输出用户输入的内容,一律做转义。这两条不改,系统跑得再顺也可能在关键时刻翻车。希望这篇笔记能帮你在期末周少走几条弯路,顺利把这份网上在线购物系统变成自己真正讲得清的课设。

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

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

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

立即咨询