ARTICLE DETAIL

资讯详情

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

基于JavaWeb的蛋糕店系统:课程设计部署与答辩

基于JavaWeb的蛋糕店系统:课程设计部署与答辩 简介基于 JavaWeb 的蛋糕店网站系统源码是一套面向 Java 课程设计、毕业设计与期末大作业场景的完整可运行项目直接解决了学生缺乏高质量参考项目的痛点适合作为课设模板或毕业设计蓝本。压缩包共 408 个文件含 58 个 JSP 页面、55 个 Java 源码、18 个 jar 依赖库和 1 个 SQL 数据库脚本并配有 CSS、JS 及大量商品图片素材JSP 负责页面展示Java/class 处理业务逻辑SQL 用于初始化数据整体仅 22.02MB结构清晰便于导入部署。项目已获导师指导并通过 97 分高分覆盖用户注册登录、商品展示、购物车、订单管理等典型电商模块后台维护功能完整代码按实体类、Dao、Service、Servlet 分层适合初学者理解 JavaWeb 分层开发与数据库操作。下载后无需修改即可运行可直接作为课程设计文档、答辩演示或二次开发基线尤其适合需要提交完整项目的毕业生与在校生目前已有 1740 人浏览学习。1. 这个蛋糕店网站系统到底能跑通什么课程设计的边界与价值下载一个名为“基于javaweb的蛋糕店网站系统源码课程设计.zip”的包是很多计算机专业学生在课程设计阶段的常规操作。这个zip解压之后通常不是一份需要复杂框架支撑的生产级系统而是一套把 JSP、Servlet、JDBC、MySQL 这些 JavaWeb 核心知识点串起来的完整案例覆盖用户注册登录、蛋糕分类展示、购物车、提交订单、后台管理订单状态这一整条业务链路。它最适合两类人一是正在做课程设计或毕业设计、需要快速拿到一个能跑通且答辩讲得清楚的项目的大学生二是刚学完 JavaWeb 基础、希望用一个完整案例把零散知识点连成体系的自学者。这里先说一个反直觉的结论这类课程设计拿高分的关键不在于用了多新的技术栈而在于你能不能把一次完整的请求从浏览器到 Servlet 再到数据库再返回页面的链路讲明白并且保证演示时不翻车。下面我就按“解压 zip → 配置环境 → 初始化数据库 → 读核心代码 → 排错 → 答辩准备”的顺序把这个方案讲透。2. JavaWeb 课程设计的技术栈拆解Servlet/JSP MySQL 的方案为什么现在还值得做2.1 技术选型为什么课程设计还在用 JSP Servlet 而不是 Spring Boot你可能会想现在外面找工作都要求 Spring Boot为什么课程设计还在用 JSP Servlet 这种“老古董”。我的看法是课程设计的考核点本来就不在框架熟练度而在基础知识的掌握程度。一个典型的 JavaWeb 课程设计评分表上几乎一定会有这些条目HTTP 请求处理流程、Servlet 生命周期、Session 会话管理、JDBC 数据库操作、MVC 分层思想。用 JSP Servlet这些知识点全部裸露在代码里你能直接看到请求从哪里进来、Servlet 如何被实例化、Session 什么时候创建、JDBC 的 Connection 怎么打开和关闭。Spring Boot 的问题在于封装得太干净了。内嵌 Tomcat、自动配置数据源、MyBatis 帮你把 SQL 结果映射成对象整个链路对新手来说是黑匣子。答辩时老师如果问一句“你的 Session 是怎么失效的”“请求是从哪一步进到 Controller 的”基础不扎实的人很容易答不上来。所以我给学生的建议一直是课程设计阶段老老实实用 JSP Servlet JDBC把每个环节都摸一遍以后学框架会快得多。这个蛋糕店网站系统就是典型的这种结构浏览器发起请求 → JSP 页面展示 → Servlet 接收参数和处理跳转 → DAO 层用 JDBC 访问 MySQL → 数据回填到 JSP 渲染。没有 Spring没有 MyBatis没有 Maven 第三方依赖管理全部用原生 javax.servlet 和 java.sql 完成。这恰恰是它适合当课程设计基线的原因每一层都能单独拿出来讲。2.2 源码包里的典型目录结构和运行入口解压 zip 之后你会看到一个标准的 Web 项目目录布局。不同作者写的包具体命名会有差异但核心骨架通常长这样cake-shop/ ├── src/ │ ├── com/cake/entity/ # 实体类User, Cake, Order, OrderItem │ ├── com/cake/dao/ # 数据访问层UserDao, CakeDao, OrderDao │ ├── com/cake/servlet/ # 控制器LoginServlet, RegisterServlet, CartServlet │ ├── com/cake/util/ # 工具类DBUtil 数据库连接 │ ├── com/cake/filter/ # 过滤器登录拦截 LoginFilter │ └── com/cake/service/ # 部分版本会有 Service 业务层 ├── web/ │ ├── index.jsp # 蛋糕列表主页 │ ├── login.jsp # 用户登录页 │ ├── register.jsp # 用户注册页 │ ├── cart.jsp # 购物车页面 │ ├── order.jsp # 订单确认页 │ ├── WEB-INF/ │ │ ├── web.xml # Web 部署描述文件 │ │ └── lib/ # mysql-connector-java 驱动 jar │ ├── css/ │ ├── js/ │ ├── images/ │ └── admin/ # 后台管理页面 └── sql/ └── cake_shop.sql # 建库建表 预设数据这里有几个关键点。web.xml是 Servlet 3.0 之前的项目入口负责声明 Servlet 映射、Filter 过滤器和欢迎页如果源码用了WebServlet注解web.xml 里可能只有少量配置甚至只有一个空壳。WEB-INF/lib目录里必须有 MySQL 驱动 jar否则运行时会直接报ClassNotFoundException这是后面最常见的翻车点。sql目录下的建库脚本决定了你能不能看到蛋糕图片和测试账号也是整个项目能否跑起来的前提。2.3 系统功能模块与数据表设计在动手部署前先把业务模块和表结构看懂这样后面改代码、答辩都是顺手的事。这个蛋糕店系统的功能模块一般可以分成两张表端功能模块核心操作用户端注册/登录用户名密码校验、Session 记录登录状态用户端蛋糕浏览首页展示蛋糕列表、按分类筛选用户端购物车加入购物车、修改数量、删除商品用户端订单确认订单、提交订单、查看我的订单后台管理员登录与用户表区分或单独 admin 表后台商品管理新增蛋糕、编辑价格库存、上下架后台订单管理查看订单、修改订单状态待付款/已发货/已完成配套的数据库表一般就是下面这四张核心表SQL 脚本长这样CREATE TABLE user ( id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(50) NOT NULL UNIQUE, password VARCHAR(50) NOT NULL, nickname VARCHAR(50), phone VARCHAR(20), address VARCHAR(100), create_time DATETIME DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE cake ( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(50) NOT NULL, category VARCHAR(20), price DECIMAL(10,2) NOT NULL, image VARCHAR(100), stock INT DEFAULT 100, status TINYINT DEFAULT 1 ); CREATE TABLE orders ( id INT PRIMARY KEY AUTO_INCREMENT, user_id INT NOT NULL, total_amount DECIMAL(10,2) NOT NULL, status TINYINT DEFAULT 0, create_time DATETIME DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE order_item ( id INT PRIMARY KEY AUTO_INCREMENT, order_id INT NOT NULL, cake_id INT NOT NULL, quantity INT NOT NULL, price DECIMAL(10,2) NOT NULL );为什么要这样设计几点经验金额字段一定要用DECIMAL(10,2)不要用double否则浮点精度问题会在算总价时暴露答辩现场演示出金额差一分钱非常尴尬。订单状态status用 TINYINT 数字比字符串好维护0 代表待付款、1 已付款、2 已发货、3 已完成、4 已取消这就是一个简单的状态机。还有一点是表名orders加了个 s因为order是 SQL 的保留字裸写会报语法错误很多新手第一次跑 SQL 脚本失败就栽在这里。3. 把 zip 包变成能跑的网站IDEA Tomcat MySQL 完整部署步骤3.1 环境准备JDK / Tomcat / MySQL 版本选型与 MySQL zip 安装拿到源码 zip 后先别急着解压先把本机环境对齐。这个项目的年代感决定了它对环境有一定挑剔最稳妥的推荐组合是JDK 1.8 Tomcat 8.5 MySQL 5.7 IDEA 2019 到 2023 之间的版本。如果你本机装的是 JDK 11 或 JDK 17部分老项目在 JSP 编译阶段会碰到模块限制或兼容问题能跑但折腾。MySQL 8.0 也能用但连接串要额外处理我会在第 5 章避坑里专门讲。如果你还没装 MySQL并且拿到的是 zip 免安装版而不是 exe 安装版操作流程是这样的把 zip 解压到D:\mysql-5.7.40然后在根目录新建一个my.ini[mysqld] basedirD:/mysql-5.7.40 datadirD:/mysql-5.7.40/data port3306 character-set-serverutf8mb4 default-storage-engineINNODB [client] default-character-setutf8mb4接着以管理员身份打开 cmd进入解压目录执行mysqld --initialize-insecure mysqld install net start mysql解释一下这三条命令。--initialize-insecure是初始化数据目录同时生成一个密码为空的 root 用户方便第一次登录mysqld install是把 MySQL 注册成 Windows 服务这样开机自动启动net start mysql是手动启动服务。注意my.ini里的basedir和datadir必须用反斜杠或正斜杠写清楚路径错了服务启动会闪退。初始化成功后登录命令是mysql -u root -p密码直接回车跳过。3.2 导入项目与配置 TomcatIDEA 里从解压到跑通的完整操作环境就绪后开始把 zip 包变成能运行的 Web 项目。整个过程我拆成四步每一步都有明确的验证点。第一步解压 zip 并用 IDEA 打开。注意选择File - Open选中解压后的文件夹而不是新建项目。如果源码里有.iml文件或.idea目录IDEA 会直接识别如果没有IDEA 会把它当普通 Java 项目打开需要手动添加 Web 支持。第二步配置 Project Structure。按CtrlAltShiftS进入项目结构左侧选 Modules在 src 目录上右键选择 Sources把它标成源码根目录然后点左上角的加号添加 Web 模块把 Web 资源目录指向web目录web.xml 路径指向web/WEB-INF/web.xml。这个动作的意思是告诉 IDEA“这是一个 Web 项目JSP 和静态资源从这个目录发布。”第三步配置 Artifacts。Project Structure 左侧选 Artifacts点加号选择Web Application: Exploded在弹出的界面里把web目录作为 Web Resource 目录。为什么要用 Exploded 而不是 war 包因为 Exploded 模式直接把编译后的类和页面发布到 Tomcat 的部署目录改完 JSP 刷新浏览器就能看到效果不用每次重新打 war 包。这一点在课程设计调试阶段特别省时间。第四步配置运行环境。点 IDEA 右上角的 Add Configuration加一个 Tomcat Server - Local在 Server 标签页里选本地 Tomcat 安装目录然后在 Deployment 标签页里点加号选择刚才的 ArtifactsApplication context 填/cake。最后把 Server 标签页的 URL 改成http://localhost:8080/cake/。这个 context path 就是将来访问项目的根路径后面所有页面链接都依赖这个值填错了会出现 404。3.3 初始化数据库建库脚本、连接配置和测试数据项目配置好后数据库的初始化是关键。用命令行或 Navicat 连接到本机 MySQL运行sql/cake_shop.sqlmysql -u root -p sql/cake_shop.sql这个脚本会完成三件事创建cake_shop数据库、新建四张业务表、插入几条蛋糕测试数据和测试账号。执行完可以再查一遍确认USE cake_shop; SHOW TABLES; SELECT * FROM cake;如果看到 cake 表里有数据说明建库成功。接着改项目的数据库连接配置。大多数源码会把连接信息写在一个DBUtil.java工具类里结构长这样public class DBUtil { private static final String URL jdbc:mysql://localhost:3306/cake_shop?useSSLfalsecharacterEncodingUTF-8; private static final String USER root; private static final String PASSWORD 123456; public static Connection getConnection() throws SQLException { try { Class.forName(com.mysql.jdbc.Driver); } catch (ClassNotFoundException e) { throw new SQLException(找不到数据库驱动, e); } return DriverManager.getConnection(URL, USER, PASSWORD); } }这里最常改动的三个参数是数据库名cake_shop、用户名USER、密码PASSWORD。注意 URL 里的characterEncodingUTF-8一定不能删否则后面中文乱码能折腾你一晚上。改完之后启动 Tomcat访问http://localhost:8080/cake/看到蛋糕列表页就说明整个链路已经通了。4. 核心代码怎么读、怎么改从用户登录到订单下单的链路4.1 登录与 Session 控制Filter 拦截器与密码校验系统跑通之后接下来要做的不是急着改功能而是把核心代码读通。以登录为例这是课程设计必问的环节。最常见的实现是一个LoginServlet接收 POST 请求用 DAO 查询数据库校验用户名密码通过后写入 SessionWebServlet(/login) public class LoginServlet extends HttpServlet { protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.setCharacterEncoding(UTF-8); String username req.getParameter(username); String password req.getParameter(password); UserDao dao new UserDao(); User user dao.findByUsernameAndPassword(username, password); if (user ! null) { // 登录成功把用户对象放进 Session标记登录状态 HttpSession session req.getSession(); session.setAttribute(loginUser, user); resp.sendRedirect(index.jsp); } else { // 登录失败回显错误信息转发回登录页 req.setAttribute(msg, 用户名或密码不正确); req.getRequestDispatcher(login.jsp).forward(req, resp); } } }这里要重点理解sendRedirect和forward的区别。sendRedirect是重定向浏览器地址栏会变成index.jsp相当于客户端重新发起一次新的请求所以 Session 里的数据能跨请求保持forward是服务端转发地址栏不变常用于把错误信息带回同一个页面。很多新手在这两种跳转方式之间混用导致页面刷新后重复提交订单后面订单模块我会再提到。Session 默认 30 分钟没有操作就会失效。如果想控制这个时间可以在web.xml里配置session-config session-timeout30/session-timeout /session-config只有登录校验还不够系统里还有购物车、下单、后台管理等页面不能让用户绕过登录直接访问。这时候需要一个过滤器统一拦截。常见写法如下WebFilter(/*) public class LoginFilter implements Filter { public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { HttpServletRequest request (HttpServletRequest) req; HttpServletResponse response (HttpServletResponse) resp; HttpSession session request.getSession(false); String path request.getRequestURI(); // 放行不需要登录的路径登录页、注册、主页、静态资源 if (path.endsWith(login.jsp) || path.contains(/login) || path.contains(/register) || path.endsWith(index.jsp) || path.contains(/css/) || path.contains(/images/)) { chain.doFilter(req, resp); return; } // 未登录用户跳回登录页 if (session null || session.getAttribute(loginUser) null) { response.sendRedirect(login.jsp); return; } chain.doFilter(req, resp); } }这段代码最值得学习的是白名单的思路。过滤器拦截的是所有请求但不等于所有请求都要登录。比如 css、图片、登录页本身如果被拦了就会出现“页面排版全乱了”“用户永远跳不回登录页”的怪问题。判断路径字符串的方式虽然朴素但在课程设计阶段够用且好讲。4.2 蛋糕列表与购物车JSP Servlet JDBC 的交互方式主页展示蛋糕列表是用户看到的第一屏代码链路一般是CakeListServlet从数据库查出列表放进 request 域转发到index.jsp用 JSTL 标签循环渲染。Servlet 端的核心逻辑WebServlet(/cakeList) public class CakeListServlet extends HttpServlet { protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.setCharacterEncoding(UTF-8); String category req.getParameter(category); CakeDao dao new CakeDao(); ListCake cakeList dao.findByCategory(category); req.setAttribute(cakeList, cakeList); req.getRequestDispatcher(index.jsp).forward(req, resp); } }页面端用c:forEach遍历避免在 JSP 里写 Java 小块脚本% taglib prefixc urihttp://java.sun.com/jsp/jstl/core % c:forEach items${cakeList} varcake div classcake-card img src${cake.image} alt${cake.name} h3${cake.name}/h3 p价格${cake.price}/p a hrefcart?actionaddcakeId${cake.id}加入购物车/a /div /c:forEach这个actionaddcakeId的 URL 写法是在 Servlet 里做业务分支的经典方式。也就是说CartServlet的doGet会先获取action参数再决定调用哪种操作String action req.getParameter(action); if (add.equals(action)) { // 加入购物车 } else if (update.equals(action)) { // 修改数量 } else if (clear.equals(action)) { // 清空购物车 }购物车数据不落地到数据库而是放在 Session 里用一个 Map 结构保存key 是蛋糕 idvalue 是数量。课程设计阶段这样实现完全没问题因为购物车是临时状态用户关掉浏览器就没了没必要建表存。如果你发现源码里用的是 List 而不是 Map也没关系逻辑等价只是修改数量的时候需要遍历查找。理解这一点答辩时就能解释“购物车为什么能跨页面同步是因为 Session 在同一个浏览器会话里是全局的”。4.3 下单与订单管理事务处理和状态字段设计下单是整个系统里唯一需要认真对待事务的模块。用户点击提交订单后端要完成的操作不是一条 SQL而是一串动作从 Session 里读出购物车、算出总金额、在orders表插入一条主记录、拿到新订单 id、再循环把每个商品插入order_item表、最后更新蛋糕库存。这一串环节里任何一步失败都会产生脏数据。常见的正确写法是手动开启事务Connection conn null; try { conn DBUtil.getConnection(); conn.setAutoCommit(false); // 关掉自动提交手动控制事务 // 1. 插入订单主记录获取生成的订单 id // 2. 遍历购物车插入 order_item 明细 // 3. 更新 cake 表库存stock stock - quantity conn.commit(); // 全部成功统一提交 } catch (SQLException e) { if (conn ! null) { conn.rollback(); // 任何一步异常全部回滚 } throw e; } finally { DBUtil.close(conn); }这里的关键是setAutoCommit(false)。默认情况下每条 SQL 执行完都会自动提交如果第 2 步插入明细失败第 1 步的订单头已经写进去了数据库里就会多出一条没有明细的“幽灵订单”。开启事务后要么全部成功要么全部回滚这是课程设计里很容易被忽视但答辩老师很爱问的考点。订单状态字段的设计在前面表结构里已经写过0 待付款、1 已付款、2 已发货、3 已完成。后台管理员的职责就是把这个数字往上涨一格同时记录修改时间。整个状态机没有分支逻辑就是一个顺序推进简单清晰。如果你想做得漂亮一点可以在orders表里加一个update_time字段每次状态变更都刷新当前时间这样后台里能看到每单走到哪一步、什么时候变的。5. 课程设计最常见翻车现场部署运行的 6 个高频报错与排查5.1 ClassNotFoundException: com.mysql.jdbc.Driver现象Tomcat 启动不报错但一访问查询页面就抛出ClassNotFoundException: com.mysql.jdbc.Driver或者页面直接 500。原因MySQL 驱动 jar 没有进入 Web 应用的运行时目录。很多新手在 IDEA 里通过 Project Structure 把 jar 添加到了 Libraries但那只是编译期可见发布到 Tomcat 时并不会自动复制进WEB-INF/lib。运行时 Tomcat 只在WEB-INF/lib里找驱动类。解决手动把mysql-connector-java-5.1.x.jar复制到项目的web/WEB-INF/lib目录下然后在 IDEA 里执行Build - Rebuild Project再重启 Tomcat。注意如果你用的是 MySQL 8.0驱动应换成 connector/J 8.x驱动类名可以写成com.mysql.cj.jdbc.Driver老代码里的com.mysql.jdbc.Driver也能兼容但会在日志里打一大段过时警告。5.2 页面全是问号或乱码现象商品名称、用户昵称在页面显示成???或者浏览器里是乱码。这个坑我在课程设计时踩过一晚上后来发现就是编码层没对齐。原因JavaWeb 里的中文要经过四道关卡JSP 文件本身的编码、Servlet 接收请求时的编码、数据库表字符集、JDBC 连接串的编码参数。四层里任何一层不一致中文就会在某个环节变成问号。解决一层层检查。JSP 页面头部确认pageEncodingUTF-8每个 Servlet 的doPost和doGet开头加上req.setCharacterEncoding(UTF-8)建表 SQL 指定DEFAULT CHARSETutf8mb4JDBC URL 带characterEncodingUTF-8。这里最容易被忽略的是 GET 请求Tomcat 8.5 默认对 GET 的 URI 编码是 UTF-8但如果你用的是老版本 TomcatGET 传到后端的中文也会乱需要在 server.xml 里给 Connector 加上URIEncodingUTF-8。5.3 Tomcat 端口被占用现象点启动按钮后 IDEA 弹窗报Address already in use: JVM_Bind或者控制台里写着Port 8080 was already in use。原因8080 端口被其他进程占用。可能是之前调试时 Tomcat 没被完全关闭也可能是其他软件占用常见的有 Nacos、其他开发服务器、甚至某次异常退出留下的孤儿进程。解决Windows 下打开 cmd 执行netstat -ano | findstr 8080看到最后一列的 PID 后执行taskkill /F /PID 进程号结束它。如果这个端口确实被其他重要程序占用直接把 IDEA 里 Tomcat 配置的 HTTP port 改成 8081记得访问地址也要同步改成http://localhost:8081/cake/。还有一个细节IDEA 里配置 Tomcat 时有个JMX port也可能被占用报错信息里端口号不同处理方式一样。5.4 Tomcat 能启动但访问 404现象Tomcat 正常启动控制台没有报错但浏览器访问http://localhost:8080/是 404。原因绝大多数情况是 Application context 配置和访问路径对不上。如果 Deployment 里设置的 context path 是/cake那么访问根路径http://localhost:8080/自然没有应用。还有一种是页面里的链接写死成了绝对路径比如a href/index.jsp这个路径会被解析成http://localhost:8080/index.jsp而不是http://localhost:8080/cake/index.jsp于是 404。解决先确认 IDEA 里 Deployment 标签页的 Application context 是/cake访问http://localhost:8080/cake/看是否正常。然后打开页面源码检查所有链接和表单 action改成相对路径或者用${pageContext.request.contextPath}拼接。比如a href${pageContext.request.contextPath}/cakeList蛋糕列表/a这样即使 later 改了 context path页面链接也不会失效。5.5 MySQL 8.0 连接失败与时区错误现象本机装的是 MySQL 8.0跑老项目时启动报The server time zone value Öйú±ê׼ʱ¼ä is unrecognized或者连接时提示Public Key Retrieval is not allowed。原因MySQL 8.0 的驱动和连接协议跟 5.x 不一样老连接串缺少serverTimezone参数驱动无法识别本机时区。日志里那段乱码其实是 GBK 编码的中文“中国标准时间”表示系统时区识别出了问题。Public Key Retrieval is not allowed是因为 MySQL 8.0 默认认证插件是caching_sha2_password客户端第一次连接需要向服务器索取公钥连接串里没允许这个行为。解决把 JDBC URL 改成完整版jdbc:mysql://localhost:3306/cake_shop?useSSLfalseallowPublicKeyRetrievaltrueserverTimezoneAsia/Shanghai如果不想改代码也可以在 MySQL 里把账号的认证插件改回mysql_native_passwordALTER USER rootlocalhost IDENTIFIED WITH mysql_native_password BY 你的密码; FLUSH PRIVILEGES;不过我还是建议直接改连接串因为这是通用解法换台电脑重新部署也不怕。5.6 刷新页面重复下单现象演示时用户提交订单成功后习惯性按了一下 F5结果数据库里出现了两笔一模一样的订单客户被扣了两次钱。原因提交订单用的是 POST 请求浏览器在刷新页面时会重新提交上一次的 POST 数据。如果 Servlet 没有做防重复提交处理同样的请求会再执行一次完整的下单逻辑。解决最简单的方案是遵循 PRG 模式下单成功后不用forward转发到订单成功页而是用sendRedirect重定向到一个订单查询页面。重定向之后浏览器地址栏变成一个新的 GET 请求刷新时只会刷新查询页不会重复触发下单。如果想更严谨可以在 Session 里存一个一次性 token下单前比对并清除这是后话课程设计阶段改用重定向已经足够讲原理时还能额外加分。6. 答辩前你要做的三个验证与改造让课程设计从「能跑」到「能讲」系统能稳定跑起来之后离高分还差一口气。这一口气就是把“能跑”变成“能讲”。我建议你在答辩前做三件事。第一件事准备一条完整的演示链路并按顺序走两遍。我的顺序是注册新用户 → 登录 → 浏览蛋糕列表 → 按分类筛选 → 加入购物车 → 改购物车数量 → 提交订单 → 退出登录 → 用管理员账号登录后台 → 把订单状态从待付款改成已发货。整个过程清空浏览器缓存走一遍确保每一步的跳转地址都正确。这里有个血泪教训演示时最怕的是临时输入提前把测试账号和相关数据准备好会比现场打字从容很多。第二件事在关键 Servlet 里加一行简单的日志输出。不需要引入日志框架System.out.println就够用。比如在LoginServlet里打印接收到的用户名、查询到的用户 id在OrderServlet里打印订单金额和订单 id。答辩时你讲到某个环节控制台正好打出对应的请求参数和 SQL 结果这个“看得见的链路”比任何流程图都有说服力。但注意演示前把没用的日志清掉不要整个控制台全是无关输出。第三件事挑两个安全相关的点做小改造这是答辩老师最喜欢追问的方向。第一个是密码不能明文存储至少要做 MD5 加盐。改造起来很简单UserDao里查用户时改用PreparedStatement的占位符密码存储和校验改成加盐后的散列值。第二个是防 SQL 注入如果源码里的 DAO 是用字符串拼接 SQL一定要改成预编译String sql SELECT * FROM user WHERE username ? AND password ?; PreparedStatement ps conn.prepareStatement(sql); ps.setString(1, username); ps.setString(2, password);对比直接拼接WHERE username username 预编译不仅防注入查询性能也更好这两点答辩时都可以展开讲。讲到最后说一句我自己的经验当年我做课程设计时最崩溃的不是功能写不出来而是明明代码和教程一模一样页面就是乱码。后来才发现不过是 JSP 头部少了一行编码声明。从那以后我做任何 JavaWeb 项目第一件事永远是先统一编码和数据库连接串再谈功能。很多你现在觉得玄学的问题追到根上都是这种基础配置没对齐。希望这篇笔记能帮你把 zip 包里的项目顺顺利利跑起来答辩时讲到每个模块都有底气。本文还有配套的精品资源点击获取
返回列表