简介一套完整可运行的JavaWeb超市订单管理系统源码与数据库打包资源面向正在完成JavaWeb课程设计的高校学生也适合需要参考完整管理系统的入门开发者可用于课程设计提交、项目实训或毕业设计前期参考。压缩包内共162个文件以Java源码、JSP页面、JavaScript脚本、CSS样式和SQL数据库脚本为主辅以XML配置及图片资源目录结构清晰导入Eclipse或IDEA后即可直接部署运行整体包体仅374KB非常轻量。已有310人学习下载不少学习者将其作为课程设计的主要参考。资源包含完整项目源码和数据库初始化脚本功能模块覆盖超市订单管理常见需求可帮助读者快速理解JavaWeb分层开发思路与数据库表设计。无论是课程设计答辩还是项目实训这套代码都能提供有力支持也便于后期扩展或二次改造。1. 一份能拿 95 分的 javaweb 课程设计源码到底该怎么用很多人的 javaweb 课程设计是到答辩前一周才开始找素材的能像“超市订单管理系统”这种业务场景贴近真实、技术又没超出大纲的题目属于最稳的选择。而当我拿到这份名为“javaweb超市订单管理系统源码数据库”的包时我第一件事不是看代码而是先确认三件事项目是不是标准的三层结构数据库脚本能不能一次导入成功登录到订单列表这条主链路能不能跑通。只要这三样过关剩下的都是查漏补缺。这篇文章就按我自己的检查顺序来把这个项目从结构到运行再到答辩前怎么打磨完整拆一遍。如果你是拿这份源码做课程设计照着走就行如果你是想找一份能真正讲清楚的 javaweb 教学案例这篇也能省你不少时间。2. 拆开看再动手项目结构、技术选型与数据库设计2.1 为什么课程设计要用 JSPServletMySQL选型就是给自己留退路很多同学一上来就放 Spring Boot Vue 的前后端分离项目但 javaweb 课程设计的评分往往要求展示当学期教学内容JSP、Servlet、Filter、JDBC 这些才是硬指标。这个项目用的是最经典的“JSP Servlet DAO”三层结构表现层是 JSP 页面控制层是 Servlet数据层是 DAO JDBC。好处有两个一是代码结构一眼望到底老师翻源码就能看到你用到了课上哪个知识点二是没有框架的黑匣子出了问题你只要能定位到 SQL 语句的位置就能排掉八成故障。技术栈方面常见完整配置是 JDK 8 或 11 Tomcat 8.5/9 MySQL 5.7/8.0 IDEA 2024 之前的任意版本。这个组合没什么花哨的东西但要注意MySQL 8.0 以上需要驱动版本 8.x并且连接串里要加 serverTimezone 参数否则一启动就报时区错误这个细节后面避坑章会展开。依赖管理上这门课一般没教 Maven所以“源码 数据库”这种压缩包的常见做法是直接在 WEB-INF/lib 下放 jar 包。打开项目后优先检查 lib 目录里有没有 mysql-connector-java、jstl、standard 这三个关键 jar。如果包里的 lib 不完整去对应版本下载后放进 lib 目录即可不用额外配置构建工具IDEA 会直接把 lib 识别成依赖。2.2 五张核心表的关系超市订单系统的数据库设计长什么样这个项目的表不多但覆盖了用户、角色、供应商、订单、地址五个常用维度是典型的课程设计粒度既不至于只有一张表没法讲也不至于搞十几张表增加答辩负担。常见表结构如下表名用途关键字段smbms_user用户表userCode、userName、userPassword、gender、birthday、phone、userRolesmbms_role角色表roleCode、roleNamesmbms_provider供应商表proCode、proName、proContact、proPhone、proAddresssmbms_bill订单表billCode、productName、productCount、totalPrice、isPayment、providerIdsmbms_address地址表contact、addressDesc、postCode、tel表与表之间的关联是典型的“外键 逻辑关联”smbms_bill 的 providerId 指向 smbms_provider 的 id取订单列表时把供应商名称 join 出来smbms_provider 的 createdBy 指向 smbms_user 的 id表示这个供应商是谁录入的smbms_user 的 userRole 指向 smbms_role 表的 id一般 1 表示管理员2 表示普通用户。这里刻意不建物理外键也说得通因为课程设计里要频繁增加测试数据物理外键在删数据时容易绊住手很多老师也默认接受逻辑外键。订单表是核心字段设计里有个容易被答辩提问的点productUnit计量单位和 productCount数量分开存是为了让同一商品能以不同单位出现在不同订单里totalPrice 字段直接冗余存储而不是实时计算原因是在真实业务里历史订单的单价会随调价变化存快照才是正确的做法。能把这个讲清楚比代码里多写两个接口更显业务素养是 95 分和 85 分的分水岭之一。2.3 初始化数据库SQL 脚本导入的三种方式和默认账号标题里既然带“数据库”包里一般会有 sql 目录或者在根目录放 .sql 文件常见文件名是 smbms.sql 或 init_db.sql。导入方式不需要额外装数据库工具如果你笔记本上只有 MySQL 命令行直接用重定向就行mysql -u root -p D:/smbms.sql参数说明-u 指定用户名-p 表示需要输入密码输入后会把 D 盘根目录下 smbms.sql 文件里的建表语句和 insert 语句按顺序执行。注意如果文件里没有 CREATE DATABASE 语句需要先手动建库再导入mysql -u root -p -e CREATE DATABASE smbms DEFAULT CHARACTER SET utf8mb4; mysql -u root -p smbms D:/smbms.sql第二条命令里的 smbms 是目标数据库名意思是把 sql 文件导入到这个库。如果脚本里自己写了 USE smbms; 语句那两条命令二选一即可但显式指定库名更稳妥不会受脚本内部注释干扰。用 Navicat 的同学就简单多了连接 - 右键 - 运行 SQL 文件选到脚本后执行刷新就能看到五张表。导入后建议执行一条查询确认数据SELECT u.userCode, u.userName, r.roleName FROM smbms_user u LEFT JOIN smbms_role r ON u.userRole r.id;能看到三条以上用户记录就说明数据导入成功。默认账号一般写在 sql 文件的 insert 语句里常见的是 admin/123456 或 admin/admin123也有直接拿第一个 userCode 当登录名的做法。找不到就直接查表确认密码字段的格式SELECT userCode, userPassword FROM smbms_user LIMIT 1;如果密码是 32 位乱码字符说明登录模块做了 MD5 加密登录时系统会按相同方式比对如果是明文说明项目没做加密处理这本身可以写进答辩的“待改进”部分反而显得你很诚实。3. 落在 IDEA 里跑通主链路环境配置、导入项目与最小登录流程3.1 环境版本怎么搭JDK 8、Tomcat 9、MySQL 5.7 的不翻车组合这个项目年代跨度大数据库驱动和 Tomcat 的版本如果不匹配启动阶段就会给你颜色看。我给这份源码配环境时最常用的是 JDK 8 Tomcat 9.0 MySQL 5.7或者 MySQL 8.0 配 mysql-connector-java 8.0.x。JDK 版本不是越高越好JDK 17 上跑老项目经常遇到模块化导致的反射报错课程设计阶段没必要给自己找这种麻烦。Tomcat 选 9 的原因是它对应 Servlet 4.0与项目里 web.xml 的配置兼容尽量不要用 Tomcat 10因为 Tomcat 10 把包名从 javax.servlet 改成了 jakarta.servlet源码里如果是 javax 开头的 import部署到 Tomcat 10 上直接 500这是新手最容易翻车的地方。IDEA 版本不影响编译2022 到 2024 任意正式版都可以社区版能跑 Tomcat 但配置入口更深建议直接用 Ultimate 或者旗舰版省得卡在环境上。MySQL 装完后命令行执行以下命令验证服务状态mysqladmin -u root -p status正常会输出 Uptime 字样和当前连接数。如果提示无法连接检查 Windows 服务里 MySQL 是否启动运行 services.msc 查看。这个细节很多人栽过装完 MySQL 但服务被手滑点成禁用后面数据库连接池一直报错白白折腾半小时。3.2 把源码导入 IDEA打开项目、配置 Tomcat、解决依赖IDEA 里打开一个 javaweb 项目的动作很机械File - New - Project from Existing Sources选中项目根目录后一直 Next直到选到项目 SDK 再 Finish。关键点在于导入方式如果源码里没有 pom.xml就选 Create project from existing sources如果项目带 Maven 的 pom.xml就选 Import project from external model - Maven。这份带源码的压缩包如果是传统 lib 目录结构一般选前者不会触发自动下载依赖速度反而更快。项目结构里能看到 src 和 WebContent或 web两个目录后右键 WebContent - Add as Web Resource Directory把 web 根目录标记上。然后打开 Project Structure快捷键 CtrlAltShiftS检查三个位置Project SDK 是否为 1.8Modules - Sources 里 src 是否标成 SourcesArtifacts 里有没有 Web Application Exploded 类型的包。没有就手动加一个Output Layout 里要把 WEB-INF/lib 下的 jar 包全选进去。配置 Tomcat 的步骤是Run - Edit Configurations - 点左上角加号 - Tomcat Server - LocalApplication Server 指向本地 Tomcat 目录Deployment 页签里点加号把刚才建的 Artifact 加进来Application context 设为 /smbms之后浏览器访问路径就是 http://localhost:8080/smbms。这里有个小规律Application context 最好和项目里登录跳转路径保持一致否则登录成功后 redirect 会变成 404。最后打开 src 下的配置文件常见文件名是 db.properties 或 jdbc.propertiesdrivercom.mysql.jdbc.Driver urljdbc:mysql://localhost:3306/smbms?useSSLfalsecharacterEncodingutf8 usernameroot password123456参数说明driver 用 com.mysql.jdbc.Driver 对应 MySQL 5.7如果你换成驱动 8.x要改成 com.mysql.cj.jdbc.Driverurl 里再加 serverTimezoneAsia/Shanghai否则报时区异常。password 是数据库密码不是 Tomcat 的写完保存。这一步配错的表现是 Tomcat 启动正常但点登录时报 access denied for user非常典型。3.3 主链路最小演示启动 Tomcat 到登录成功为了确认环境没问题建议先走一条最简短的主链路验证数据库连接、Servlet 映射、Session 会话都正常。启动 Tomcat 的绿色三角按钮等 Console 里出现 Server startup in 字样后浏览器访问 http://localhost:8080/smbms/login.jsp页面里应该能看到登录表单。输入默认账号密码点登录后正常情况会跳转到首页 frame.jsp页面上能看到左侧菜单订单管理、供应商管理、用户管理。如果停在这一步说明三层之间的接口都通了。接下来按顺序测试点订单管理看列表能不能显示订单记录。点供应商名称看能不能打开该供应商的订单列表。点退出确认 Session 被清掉并回到登录页。这一步最常见的错误是页面能打开但列表空白一般是 SQL 脚本里没插业务数据或者查询语句 join 的表名与你自己脚本里的表名差个下划线。排查办法把浏览器地址栏里的 /smbms/ 去掉直接访问 http://localhost:8080/如果能打开 Tomcat 默认首页就说明程序和 Tomcat 本身没毛病回头改 SQL如果连默认首页都打不开就去检查 Tomcat 端口占用。4. 读源码时我重点检查的四个模块登录、分页、增删改、连接池4.1 登录模块Session 管控与验证码的实现逻辑很多课程设计评分差的根源是只有增删改查没有状态管理登录模块在答辩时的权重远高于其他功能。这个项目的登录流程一般是这样login.jsp 的表单提交到 LoginServlet 的 doPostservlet 拿参数后调用 Service 层的 login 方法Service 再调 DAO 层执行一条 select。关键代码如下WebServlet(/login.do) public class LoginServlet extends HttpServlet { private UserService userService new UserServiceImpl(); Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doPost(req, resp); } Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String userCode req.getParameter(userCode); String userPassword req.getParameter(userPassword); // 调用 Service 层做登录校验 User user userService.login(userCode, userPassword); if (user ! null) { req.getSession().setAttribute(USER, user); // 重定向到主框架页 resp.sendRedirect(req.getContextPath() /jsp/frame.jsp); } else { req.setAttribute(error, 用户名或密码错误); // 转发回登录页显示错误信息 req.getRequestDispatcher(/login.jsp).forward(req, resp); } } }逻辑说明这个 Servlet 做了三件事——接收表单参数调用业务层做密码比对根据结果决定跳转还是留在登录页。注意重定向和转发的区别登录成功用 sendRedirect浏览器地址栏会变成目标地址刷新不会重复提交表单登录失败用 forward地址栏不变但 request 作用域里的 error 信息能显示在 JSP 页面上。这两个动作是答辩高频问题建议背下来。验证码逻辑一般在同一模块里用单张图片输出实现前端 img 标签的 src 指向一个 CheckCodeServlet这个 servlet 用 BufferedImage 画随机数字再把验证码字符串写入 Session。用户提交登录时除了校验用户名密码还要比对用户输入和 Session 里存的验证码忽略大小写。验证码不是大纲必讲内容但项目里加上它答辩老师提问“你做过什么安全措施”时就有了第一手素材。4.2 订单列表分页与模糊搜索PageSupport 的分页设计思路订单量稍微大一点分页就是必然需求。这个项目里常见做法是自写一个 PageSupport 类持有每页条数、总记录数、总页数、当前页码、当前页数据 list 五个字段。查询时由 Controller 接收 pageIndex传给 Service 层再穿透到 DAO 层里的 limit 子句String sql SELECT b.id, b.productName, p.proName, b.productCount, b.totalPrice, b.isPayment FROM smbms_bill b INNER JOIN smbms_provider p ON b.providerId p.id WHERE 11 ; ListObject params new ArrayList(); if (productName ! null !.equals(productName.trim())) { sql AND b.productName LIKE ? ; params.add(% productName.trim() %); } sql ORDER BY b.creationDate DESC LIMIT ?, ?; params.add((pageIndex - 1) * pageSize); params.add(pageSize); PreparedStatement ps conn.prepareStatement(sql); for (int i 0; i params.size(); i) { ps.setObject(i 1, params.get(i)); }逻辑说明这里最值得学习的是 WHERE 11 的写法目的只是方便在后面追加多个查询条件而不用为每个组合单独写一套 SQL实际执行性能没有差别。LIMIT 的两个参数是偏移量和每页条数pageIndex 从 1 开始所以偏移量是 (pageIndex - 1) * pageSize。页面底部翻页按钮由 JSTL 的 c:forEach 根据 PageSupport 里的 totalPage 循环生成。这套设计在课程作业里算标准答案但它不是最优实现你要知道它的边界订单量过万时这样写会全表扫描性能扛不住不过课程设计规模完全够用。答辩时如果老师问大数据量怎么办标准回答是给 productName 和 providerId 加普通索引分页物理查询改成按主键 ID 切片能说出来就是加分项。4.3 新增、修改、删除订单事务边界与参数校验订单的增删改是 CRUD 四件套里的后半段代码形式上很像但有三个细节值得盯着看第一删除订单时要不要顺带处理关联的订单明细第二更新订单时 totalPrice 是重新计算还是用户手填第三delete 操作是物理删除还是逻辑删除。这个项目里常见做法是物理删除字段上用 modifyBy 记录最后操作人算是轻量级审计字段能过基本要求。删除功能的典型 DAO 代码如下public int deleteBillById(Connection conn, Integer id) throws SQLException { // 用 PreparedStatement 防止参数拼接导致 SQL 注入 String sql DELETE FROM smbms_bill WHERE id ?; PreparedStatement ps conn.prepareStatement(sql); ps.setInt(1, id); return ps.executeUpdate(); }逻辑说明注意这里把 Connection 作为参数传了进来而不是在 dao 内部自己开连接。原因是删除订单可能涉及多个表如果以后要扩展成删除订单同时删除退货记录必须保证两个操作在同一个事务里。所以 Service 层的标准写法是 conn.setAutoCommit(false)执行两个 dao 方法后 conn.commit()任何一步抛异常就 rollback。DAO 里的 executeUpdate 返回 0 时说明传进来的 id 不存在页面应提示该订单不存在而不是显示假成功。另一个答辩里很提气的点是用 PreparedStatement 参数绑定而不是字符串拼接。很多课程设计项目写的是 select * from smbms_bill where id id遇到带引号和反斜杠的输入就出问题PreparedStatement 的 setInt 天然挡住注入。如果有时间演示时故意输入1 OR 11再跟老师说因为用了预编译所以攻击无效现场效果非常直接。4.4 连接池选择课程设计阶段用 dbcp 还是不用数据库连接这块项目里常见有两种写法一种是每次查询都 DriverManager.getConnection用完关掉另一种是配置一个连接池。课程设计阶段用第一种足够代码容易看懂但如果你想让项目看起来更像工程实践可以在 src 下加一个 dbcp 连接池配置web.xml 里监听器负责初始化。连接池的核心参数有四个参数作用建议值initialSize启动时创建的连接数5maxActive最大活动连接数20maxIdle最大空闲连接数10minIdle最小空闲连接数5参数说明这四个值不是越大越好课程设计的并发量很小maxActive 设成 20 绰绰有余如果设太大MySQL 默认最大连接数是 151并发测试时反而会先耗尽连接报 Too many connections。答辩老师如果问连接池意义就答“减少频繁建连的开销”能说出这句话就说明你理解它。5. 避坑指南这份超市订单管理系统源码的 6 个高发问题5.1 Tomcat 一启动就 ClassNotFoundException现象IDEA 里点运行Console 出现 class not found: com.mysql.jdbc.Driver或者 Servlet 相关的类找不到。原因lib 目录下的 jar 包没有被打进 Web 应用的 WEB-INF/lib 下。很多导入的源码虽然结构里能看到 lib但 IDEA 没有把这个目录关联到 Artifacts部署时并不会带上 jar。解决Project Structure - Artifacts - 选中项目 - Output Layout 右侧列表里点加号 - 选择 Copy of - 选 lib 目录。改完重新 Build - Rebuild Project。如果还不行直接去部署输出目录看 WEB-INF/lib 下是否存在 mysql-connector-java-xxx.jar没有就手动拷贝进去再重启。5.2 启动后登录提示 Communications link failure 或 access denied现象控制台没有报错页面正常打开但一点登录就提示数据库连接失败。原因按顺序排查四个点。第一MySQL 服务没起来services.msc 里检查。第二连接库名和实际库名不一致脚本建的是 smbms配置文件里写的是 supermarket。第三MySQL 8 以上时区问题。第四最隐蔽的db.properties 文件是 ANSI 编码里面写了中文注释在 UTF-8 环境下解析时注释串行导致连接串被截断。解决把配置文件里的中文注释全删掉另存为 UTF-8 编码驱动用 mysql-connector-java-8.0.28.jarurl 末尾加 serverTimezoneAsia/Shanghai确认 url 里的库名与 SQL 脚本里的库名逐字一致注意 Linux 上 MySQL 库名严格区分大小写Windows 上不区分但不要留下隐患。5.3 登录成功但所有中文信息都成了问号现象列表里商品名、供应商名全是 ??但英文和数字正常或者页面整体乱码。原因三层编码没全打通。第一层是 JSP 页面本身的 pageEncoding第二层是 Servlet 里 req.setCharacterEncoding(UTF-8) 有没有在读取参数前执行第三层是数据库连接串里的 characterEncoding以及数据库和表本身的字符集是不是 utf8mb4。这个项目如果是从别人机器上拷来的很可能只对了其中一层。解决统一到 UTF-8。JSP 头部保持 pageEncodingUTF-8在 web.xml 里注册一个 CharacterEncodingFilter由它统一处理所有请求的编码。数据库如果已经用错误字符集插入过脏数据把表删掉重新导入脚本最省事别用 update 去改容易越改越乱。如果 Navicat 导出的建表语句带头有 DEFAULT CHARSETutf8mb4直接覆盖导入即可不用重复改库。5.4 点击第二页报 500分页参数丢失或类型转换错误现象第一页显示正常点击页码 2 后页面报 NumberFormatException: For input string: null。原因URL 里没有带 pageIndex 参数servlet 里直接执行了 Integer.parseInt(request.getParameter(pageIndex))而 getParameter 返回 nullparseInt 就抛异常。很多课程设计项目都是这么写的不判断空值。解决页面翻页链接里把上一次的查询条件带上产品名、供应商下拉框选中项、当前页码都要拼进 URL。servlet 端对 pageIndex 做一次空值兜底String idxStr req.getParameter(pageIndex); int pageIndex (idxStr null || .equals(idxStr)) ? 1 : Integer.parseInt(idxStr);如果翻页后搜索条件丢失就是页面里没有把当前产品名回显到翻页链接上按上面的方案在链接里加名值对即可。这类问题调参时要结合浏览器 F12 的 Network 面板看 URL 参数一目了然。5.5 IDEA 运行后浏览器访问 404Tomcat 管理页却正常现象Tomcat 默认首页能打开但 http://localhost:8080/smbms/ 直接 404或者 IDEA 启动 Tomcat 后自动打开的是 localhost:8080/ 而不是项目根路径。原因两件事没做对。一是 Artifacts 没打 war exploded或者打出来的包名和 Application context 对不上二是 web.xml 里没配 welcome-file默认访问根路径时找不到入口页面。解决在 Run/Debug Configurations 里找到这个 Tomcat 配置看 Deployment 页签的 Application context 值是不是 /smbms保持一致然后在 web.xml 的 welcome-file-list 里把 login.jsp 配进去。如果部署页面里是灰色不可用状态关掉设置面板后重新 Build - Rebuild Project 一次再回来看就有了这是 IDEA 的索引缓存问题属于玄学但通常有效。5.6 项目里密码字段是 32 位乱码登录不上现象数据库里 userPassword 是一串 32 位十六进制字符但你用 admin/123456 直接查表能看到记录用相同密码在页面登录却失败。原因登录时系统对输入密码做了 MD5 加密后再和数据库比对数据库里存的本来就是密文你看到的 123456 只是初始账号的注释说明实际库里存的是 123456 的 MD5 值。解决确认 LoginServiceImpl 里有没有调用 MD5 工具类常见写法是 Md5Util.getMd5(userPassword) 或 DigestUtils.md5Hex()。如果想换一个自己能记住的密码手动执行 SQL 更新UPDATE smbms_user SET userPassword MD5(newpass123) WHERE userCode admin;注意 MySQL 的 MD5() 函数返回小写 32 位字符串Java 端的工具类也要统一转换成小写比对否则两边大小写不一致会误判密码错误。5.7 明明导入成功列表页却没有供应商数据现象订单列表能打开但供应商名称那一列全为空或者点击供应商管理一片空白。原因smbms_provider 表是空的。某些脚本版本为了减少测试数据只插了用户和角色供应商和订单数据留空需要自己造数。解决插入两条常用的测试数据注意 providerId 要和订单表对应INSERT INTO smbms_provider (proCode, proName, proContact, proPhone, proAddress) VALUES (PRO-001, 北京华联超市供应商, 王经理, 13800000001, 北京市朝阳区); INSERT INTO smbms_provider (proCode, proName, proContact, proPhone, proAddress) VALUES (PRO-002, 上海百联食品, 李经理, 13800000002, 上海市浦东新区);执行完刷新页面。如果订单列表里 join 出的供应商名还是空多半是 join 字段对不上检查 bill 表的外键字段是 providerId 还是 provider_id保持一致即可。这个坑很多人踩过换字段名后一切正常。6. 从 85 到 95答辩前最值得改的三个地方高分和低分的差距往往不在功能数量而在细节完成度。这份超市订单管理系统跑通之后我建议你按优先级改三个地方。第一给密码加上 MD5 盐。现在的系统如果密码是明文在答辩时属于直接暴露的弱点。改起来其实不费事在 Service 层登录逻辑里把密码先经过工具类加密再比对同时修改 sql 脚本里初始密码的值。我一般这样改public User login(String userCode, String userPassword) { UserDao userDao new UserDaoImpl(); User user userDao.getUserByCode(userCode); if (user null) { return null; } // 对输入密码做 MD5再与库中密文比对 String inputPwd Md5Util.getMd5(userPassword); return inputPwd.equals(user.getUserPassword()) ? user : null; }参数说明Md5Util.getMd5 内部用 MessageDigest 计算摘要返回 32 位 hex 字符串。改成这段之后记得把数据库里 userPassword 字段的值也用同一加密规则更新一遍否则老账号全部失效。这一步不但提升了系统安全性还向老师展示了你有“不把明文密码放进数据库”的工程意识。第二把订单列表页加一个统计明细。不需要引入复杂图表库常见做法是在订单列表顶部用 JSTL 的 fmt:formatNumber 展示“订单总数”和“本月订单金额合计”。两条 SQL 就能完成但在答辩演示时显示的数据比空荡荡的列表直观得多印象分至少提一档。第三准备一条演示脚本并反复走三遍。我的习惯是先讲数据库结构再讲登录的 Session 控制然后讲订单分页最后讲增删改每换一个页面就点一下 F12 的 Network 面板指给老师看请求参数和响应时间。演示自然流畅比代码本身更能决定成绩。这套流程走下来我送走自己那届同学时的血泪经验是作品可以中庸但演示必须顺畅。宁可少做两个功能也要把主链路每个按钮点十遍确保不会在老师面前卡住。希望这些也能帮到你。本文还有配套的精品资源点击获取
