ARTICLE DETAIL

资讯详情

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

JavaWeb课设甜品管理系统:从环境配置到答辩全解析

JavaWeb课设甜品管理系统:从环境配置到答辩全解析 简介这是一份基于 JavaWeb 的甜品管理系统期末项目源码适用于正在完成课程设计或期末大作业的高校学生也可作为 ServletJSPMySQL 三层架构开发的入门参考。项目涵盖用户登录注册、商品分类展示、购物车操作与订单管理等典型电商模块前后台页面均以 JSP 配合 CSS、JavaScript 实现配合 SQL 脚本即可完成数据库初始化。资源包为 zip 格式共 197 个文件大小约 6.05MB。主要文件类型包括 46 个 java 源码文件、24 个 JSP 页面文件、65 个 class 编译文件、6 个 jar 依赖库以及 1 个 SQL 数据库脚本另含 36 张 PNG 图片与 2 个 CSS 样式文件用于页面展示和交互布局整体目录结构清晰便于按模块理解。目前已有 98 人浏览学习。压缩包内提供可直接运行的完整工程与数据库初始化脚本所有源码均已严格测试能在配置好 JDK、Tomcat 和 MySQL 后直接部署DAO、Service、Servlet 分层清晰适合用来复习 JavaWeb 核心知识点、准备答辩或在此基础上二次开发。1. 甜品管理系统.zip一个JavaWeb课设项目的完整解剖期末前两周你手上多了一个“大三上学期的javaweb期末项目——甜品管理系统.zip”不管是从学长手里拷来的、从网盘里捡来的还是自己刚写完打包的摆在面前的都是同一个问题这个JavaWeb项目怎么在IDEA里跑起来跑起来之后又该怎么讲清楚。这类课设项目的技术栈高度统一JSP Servlet MySQL Tomcat可能带一点BootStrap或者原生CSS个别卷一点的会揉进MyBatis或Spring但主干仍然是经典的JavaWeb三层架构。甜品管理系统解决的问题很具体商品展示、用户登录注册、购物车与下单、后台管理。适合谁正在做JavaWeb课设的大三学生、想快速复现一个完整项目以应付答辩或实习面试的人以及那些拿到代码但跑不起来、想搞懂每一层在干什么的初学者。这篇笔记就沿着“跑通、看懂、会改、能答”的顺序往下拆。2. 跑通环境等于成功一半IDEA Tomcat MySQL 的最小配置路径环境配置是JavaWeb项目的第一道坎也是翻车率最高的地方。这门课的学生项目基本不会用Maven多数情况下是一个手工建立的Web项目依赖的jar包躺在web/WEB-INF/lib目录里。这意味着运行方式比SpringBoot项目老派得多需要本地装好JDK、Tomcat、MySQL然后在IDEA里把项目配置成Web应用程序再部署到一个外部Tomcat实例上。这个环节的难点不在于操作复杂而在于版本不匹配时会报出一堆看不懂的错——ClassNotFound、NoClassDefFound、UnsupportedClassVersionError每一行都够你查半小时。2.1 版本怎么选JDK 8、Tomcat 8.5、MySQL 5.7 的兼容逻辑先说结论JDK 1.8 Tomcat 8.5 MySQL 5.7是这类课设项目最稳的组合。为什么JDK 8是目前JavaWeb课程里默认的教学版本绝大多数教材和网上的代码都基于它编写语法上不会遇到lambda表达式之类的版本差异问题。Tomcat 8.5同时支持到Servlet 3.1规范对应WebServlet注解和传统的web.xml映射都能正常工作不会出现Servlet 4.0时代才有的新特性导致的不兼容。MySQL 5.7的驱动连接串写法最通用com.mysql.jdbc.Driver和com.mysql.cj.jdbc.Driver两个类都能找到不至于在驱动类上卡死。如果你打开项目的WEB-INF/lib目录里面通常能看到mysql-connector-java-5.1.x.jar和jstl.jar这类文件。这说明项目编写时就是按老环境设计的。用JDK 17去跑这种项目会直接报模块化错误或者IllegalAccessError因为Tomcat版本和JDK版本对不上。装了JDK 17的人也别急着卸载IDEA里可以给每个Project单独设置Project SDK和Language Level把当前项目指定为JDK 8即可。前提是你机器上装了JDK 8没有的话去下载一个别偷懒。Tomcat版本和IDEA版本也有搭配关系。IDEA 2021以上版本对Tomcat 8.5的支持完全没问题但如果你的Tomcat是10.x那就要注意了Tomcat 10把javax.servlet包改名成了jakarta.servlet老项目里的import javax.servlet.http.HttpServlet会直接编译失败。这个坑极其隐蔽因为你可能以为是代码写错了实际上是Tomcat版本太新。2.2 导入项目的四个步骤从解压到看见登录页第一步解压zip后检查目录结构。一个标准的JavaWeb课设项目内部应该是这样的dessert-system/ ├── src/ │ ├── com/xxx/dao/ │ ├── com/xxx/entity/ │ ├── com/xxx/servlet/ │ ├── com/xxx/service/ │ └── com/xxx/util/ ├── web/ │ ├── WEB-INF/ │ │ ├── lib/ │ │ └── web.xml │ ├── css/ │ ├── js/ │ └── *.jsp └── sql/ └── dessert_db.sql如果src下面没有代码只有WEB-INF/classes目录里有.class文件说明这是编译后的版本源码在别的地方或已经被误删。这种情况建议先跟给你项目的人确认没有源码的课设项目是没法改功能的答辩一问就露馅。第二步在IDEA中导入。File - New - Project from Existing Sources选中解压后的根目录选择Import project from external model - Eclipse或直接选Create project from existing sources都行。别选Maven因为这个项目大概率没有pom.xml选了会导入失败。导入完成后右键项目根目录选择Add Framework Support勾选Web Application让IDEA识别web目录。第三步配置Tomcat。Run - Edit Configurations - - Tomcat Server - Local在Deployment页签里点 - Artifact选项目名:war exploded。Application context填/或者项目名都行。这一步是IDEA运行javaweb项目配置里最关键的操作漏掉任何一环启动时都会提示No artifacts marked for deployment。然后在Server页签里确认Tomcat路径已经指向你本地安装的Tomcat目录。第四步配置数据库连接。找到src下的数据库工具类通常叫DBUtil.java或JdbcUtils.java打开后你会看到类似这样的代码private static final String URL jdbc:mysql://localhost:3306/dessert_db ?useSSLfalseserverTimezoneAsia/ShanghaicharacterEncodingutf8; private static final String USERNAME root; private static final String PASSWORD 123456;把root和123456改成你自己MySQL的用户名和密码然后在MySQL里执行sql/dessert_db.sql脚本完成建库建表。改完代码后务必Build - Rebuild Project重新编译不然Tomcat跑的还是旧的class文件。2.3 跑不起来先看这三个地方控制台、日志、端口配置完成只是第一步点完启动按钮才见真章。Tomcat启动失败时先别急着到处搜报错按顺序看三个地方。控制台输出的最后几行是最直接的线索。如果最后一行停在Deploying web application directory ...或者Initializing Spring root WebApplicationContext多半是项目部署期间出错了。这时往上翻日志找SEVERE、Exception、Caused by这三个关键词。Caused by后面的内容才是真正的根因前面一大堆堆栈信息只是包装层。如果控制台没有红色日志但访问http://localhost:8080时一直转圈或者白屏问题大概率不出在Tomcat本身而在项目的Artifact配置。IDEA的默认配置有时会把项目部署成空的访问根路径没有欢迎页。这时检查Deployment页签里Artifact的类型如果是war exploded模式要在启动配置里勾选Build before run。端口占用的处理方式相对固定。启动时报Port 8080 was already in use在Windows上执行netstat -ano | findstr 8080 taskkill /F /PID 这里替换成查到的PIDmacOS或Linux上执行lsof -i:8080 kill -9 PID改Tomcat端口的办法是编辑Tomcat安装目录下的conf/server.xml找到Connector port8080 .../改为其他端口但改完后记得访问地址也同步改否则又会出现connection refused的新问题。环境跑通后项目启动到看见登录页你的课设已经完成了一半。3. 数据库设计先行甜品管理系统的五张核心表与建表脚本JavaWeb课设的数据库设计直接决定代码好不好写。甜品管理系统听名字是个电商系统的垂直版业界常见的做法是参考黑马JavaWeb笔记里讲的“用户-商品-订单”三段式表结构去掉复杂的库存和支付模块保留核心的管理链路。五张表足够覆盖答辩时会被问到的大部分问题用户表、甜品分类表、甜品表、订单表、订单明细表。这五张表组成了一个从登录到下单再到后台管理的完整数据闭环。3.1 五张表的角色划分用户、甜品、分类、订单、订单明细用户表存账号信息甜品分类表做一级分组甜品表存具体商品及其价格库存订单表记录“谁在什么时候下了一单”订单明细表存“这一单里具体有哪些甜品各买了几份”。为什么要把订单拆成订单表和订单明细表因为一张订单包含多个商品用户下了一单买了“提拉米苏”和“杨枝甘露”这两条记录不能塞在同一个订单字段里否则查询“某甜品卖了多少份”时要对字符串做拆分效率低且不规范。拆成两张表后订单主表存一次下单行为的公共信息明细表存每行商品的快照各司其职。这个设计与黑马JavaWeb笔记中“订单模块”的思路一脉相承订单表和订单项分离才能支撑多用户下单、后台统计销量、按时间筛选订单等后续功能。同时用户表和订单表通过外键关联甜品表和订单明细表通过外键关联两层关联在答辩时怎么说都有得聊。3.2 建表与初始化脚本直接导入MySQL的SQL以下建表SQL可直接在MySQL中执行字符集务必指定为utf8mb4否则插入emoji甜品名时会直接报错或者乱码DROP DATABASE IF EXISTS dessert_db; CREATE DATABASE dessert_db DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; USE dessert_db; CREATE TABLE user ( id INT PRIMARY KEY AUTO_INCREMENT COMMENT 用户ID, username VARCHAR(50) NOT NULL UNIQUE COMMENT 登录名, password VARCHAR(50) NOT NULL COMMENT 密码, nickname VARCHAR(50) DEFAULT NULL COMMENT 昵称, role TINYINT NOT NULL DEFAULT 0 COMMENT 角色:0普通用户,1管理员 ) ENGINEInnoDB AUTO_INCREMENT1; CREATE TABLE category ( id INT PRIMARY KEY AUTO_INCREMENT COMMENT 分类ID, name VARCHAR(50) NOT NULL COMMENT 分类名称 ) ENGINEInnoDB AUTO_INCREMENT1; CREATE TABLE dessert ( id INT PRIMARY KEY AUTO_INCREMENT COMMENT 甜品ID, category_id INT NOT NULL COMMENT 所属分类, name VARCHAR(100) NOT NULL COMMENT 甜品名称, price DECIMAL(10,2) NOT NULL COMMENT 单价, stock INT NOT NULL DEFAULT 0 COMMENT 库存, image VARCHAR(255) DEFAULT NULL COMMENT 图片路径, description TEXT COMMENT 描述, CONSTRAINT fk_dessert_category FOREIGN KEY (category_id) REFERENCES category(id) ) ENGINEInnoDB AUTO_INCREMENT1; CREATE TABLE orders ( id INT PRIMARY KEY AUTO_INCREMENT COMMENT 订单ID, order_no VARCHAR(32) NOT NULL COMMENT 订单编号, user_id INT NOT NULL COMMENT 下单用户, total_amount DECIMAL(10,2) NOT NULL COMMENT 总金额, status TINYINT NOT NULL DEFAULT 0 COMMENT 状态:0待处理,1已发货,2已完成, create_time DATETIME NOT NULL COMMENT 下单时间, CONSTRAINT fk_orders_user FOREIGN KEY (user_id) REFERENCES user(id) ) ENGINEInnoDB AUTO_INCREMENT1; CREATE TABLE order_detail ( id INT PRIMARY KEY AUTO_INCREMENT COMMENT 明细ID, order_id INT NOT NULL COMMENT 所属订单, dessert_id INT NOT NULL COMMENT 甜品, quantity INT NOT NULL COMMENT 数量, price DECIMAL(10,2) NOT NULL COMMENT 下单时单价快照, CONSTRAINT fk_detail_order FOREIGN KEY (order_id) REFERENCES orders(id), CONSTRAINT fk_detail_dessert FOREIGN KEY (dessert_id) REFERENCES dessert(id) ) ENGINEInnoDB AUTO_INCREMENT1;这段SQL里有几个参数值得说明一下。DECIMAL(10,2)用于价格字段不要用FLOAT或DOUBLE因为浮点数在计算总和时会出精度误差答辩时如果你说“用DECIMAL是因为避免0.10.2不等于0.3的精度问题”会是加分项。status字段设置默认值0避免插入数据时忘记赋值。password字段在课设中直接存明文很常见但如果答辩老师问起来你要能说出“这里应该有加盐哈希我简化处理是为了展示业务逻辑”最好再补一句“BCrypt或MD5加盐都是可行的改进”。初始化数据建议至少插入两类测试账号和8条甜品记录INSERT INTO user (username, password, nickname, role) VALUES (admin, 123456, 管理员, 1), (student, 123456, 测试用户, 0); INSERT INTO category (name) VALUES (蛋糕), (饮品), (布丁); INSERT INTO dessert (category_id, name, price, stock, description) VALUES (1, 提拉米苏, 28.00, 50, 经典意式甜品), (1, 草莓慕斯, 25.00, 30, 当季草莓制作), (2, 杨枝甘露, 18.00, 100, 芒果西柚调配), (2, 珍珠奶茶, 12.00, 200, 手作珍珠), (3, 焦糖布丁, 15.00, 80, 现烤焦糖层), (3, 抹茶布丁, 16.00, 80, 宇治抹茶);初始化数据时把admin账号的role设成1这样后面的后台管理功能可以根据role字段决定是否显示“管理入口”。然后甜品的image字段可以填相对路径比如upload/cake1.jpgJSP页面再配置静态资源映射。3.3 为什么订单要拆成两张表状态字段和销量统计的关系答辩时老师大概率会指着订单表问“这个status字段你觉得够用吗”课设里常见的答案是0待处理、1已发货、2已完成但如果你能说出第三个状态“已取消”或“已退款”以及对应的业务场景就能展现自己的思考。更细颗粒度的状态设计可以增加字段来记录状态变更时间——但课设阶段不必引入“状态流水表”这种复杂度用status一个字段配合create_time就够了。如果加了普通用户下单、管理员后台改状态的功能你的系统就能支撑两类核心场景前端用户能查看“我的订单”后台能按状态筛选订单并且统计某甜品的销量。销量统计SQL是SELECT d.name, SUM(od.quantity) AS total_sold FROM order_detail od JOIN dessert d ON od.dessert_id d.id GROUP BY d.id ORDER BY total_sold DESC;看明白这段SQL答辩时被问“怎么统计哪款甜品卖得最好”你就可以直接答出来。整库设计到这个程度接下来写的DAO层代码就会顺很多因为每张表都有了清晰的职责边界增删改查的对象非常明确。4. 从登录到下单读懂代码分层的完整请求链路数据库建好之后再看JavaWeb项目的代码结构。黑马JavaWeb笔记里的教学项目通常采用Servlet JSP JDBC的组合实体类放在entity或bean包数据库访问写在dao包业务逻辑写在service包控制层用servlet包页面放在web目录下。甜品管理系统的代码结构大致如此也可能因为项目写得较早而混入一些把业务逻辑直接写在Servlet里的写法。读懂这条从浏览器到数据库的请求链路是答辩时展示项目能力的关键。4.1 三层架构的目录entity、dao、servlet、jsp各管一段打开src目录下的包结构先记住各层的职责边界。entity包里的类是对数据表的正向映射User.java对应user表Dessert.java对应dessert表字段名和表的列名保持一致性通常是private Integer id; private String name;这类基本类型包装类。dao包里是纯JDBC访问代码负责拼SQL、执行SQL、把ResultSet转成实体类对象不包含任何业务判断。servlet包里的代码接收HTTP请求、解析参数、调用dao或service、决定跳转到哪个JSP页面。JSP文件负责展示数据但好的写法中不会写大量Java代码块而是用JSTL和EL表达式取值。你需要关注的是包之间是否遵守了“Servlet不直接写SQL”这条边界线。如果打开LoginServlet.java后发现里面直接用DriverManager.getConnection拼SQL说明这个项目没有做分层但并不意味着它跑不起来——只是答辩时容易被问“你这个类职责是否清晰”。如果时间允许把这类代码往dao层挪一挪课设分数通常能上一个档。4.2 登录与SessionJavaWeb第一个绕不过去的功能登录功能几乎每个JavaWeb项目都有甜品管理系统的登录验证流程是用户在login.jsp输入用户名密码表单提交到LoginServletservlet从request中取出参数调用dao查询user表查到了就创建session没查到就转发回登录页并携带错误提示。示例代码如下WebServlet(/login) public class LoginServlet extends HttpServlet { private UserDao userDao new UserDao(); Override 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 userDao.findByUsernameAndPassword(username, password); if (user ! null) { HttpSession session request.getSession(); session.setAttribute(user, user); if (user.getRole() 1) { response.sendRedirect(request.getContextPath() /admin/dessert/list); } else { response.sendRedirect(request.getContextPath() /dessert/list); } } else { request.setAttribute(error, 用户名或密码错误); request.getRequestDispatcher(/login.jsp).forward(request, response); } } }这段代码是课设项目的标准写法几个参数值得解释。WebServlet(/login)注解是Servlet 3.0之后的映射方式省掉了web.xml里一长串servlet-mapping配置但项目里如果老代码还在用web.xml方式只要两处不重复映射同一个路径即可重复了Tomcat启动时会报Multiple mappings的错。request.setCharacterEncoding(UTF-8)这一行必须放在读取参数之前否则中文用户名会乱码。response.sendRedirect和request.getRequestDispatcher().forward()的差别前者是客户端重定向浏览器URL会变化后者是服务端转发URL不变这个差异在答辩时也常被问到。findByUsernameAndPassword在dao层的基本写法是把用户名和密码拼成SQL参数化查询不要用字符串拼接SQL否则SQL注入问题会直接让答辩翻车。4.3 甜品CRUD完整链路从JSP表单到数据库以“新增甜品”为例整条链路贯穿了JSP的表单页、servlet的接收、service的业务检查、dao的插入。这个链路值得完整走一遍因为明白了它就摸透了JavaWeb的方式。先看dao层public int insert(Dessert dessert) throws SQLException { String sql INSERT INTO dessert (category_id, name, price, stock, description) VALUES (?, ?, ?, ?, ?); try (Connection conn DBUtil.getConnection(); PreparedStatement ps conn.prepareStatement(sql)) { ps.setInt(1, dessert.getCategoryId()); ps.setString(2, dessert.getName()); ps.setBigDecimal(3, dessert.getPrice()); ps.setInt(4, dessert.getStock()); ps.setString(5, dessert.getDescription()); return ps.executeUpdate(); } }PreparedStatement的?占位符配合setXxx系列方法是防SQL注入的业界标准做法不要用Statement拼字符串。try-with-resources语法让Connection和PreparedStatement自动关闭避免连接泄漏——能看到这一步的代码风格通常不差。然后servlet层接收表单WebServlet(/admin/dessert/add) public class DessertAddServlet extends HttpServlet { private DessertDao dessertDao new DessertDao(); Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding(UTF-8); Dessert dessert new Dessert(); dessert.setCategoryId(Integer.parseInt(request.getParameter(categoryId))); dessert.setName(request.getParameter(name)); dessert.setPrice(new BigDecimal(request.getParameter(price))); dessert.setStock(Integer.parseInt(request.getParameter(stock))); dessert.setDescription(request.getParameter(description)); dessertDao.insert(dessert); response.sendRedirect(request.getContextPath() /admin/dessert/list); } }这类代码在课设里很常见但存在两个隐患一是没有做非空和数字格式校验用户输入非法字符时parseInt会抛NumberFormatException二是没有做权限校验任何知道URL的人都能直接调/admin/dessert/add接口。改进方向是在dao层返回自增主键ps.getGeneratedKeys()在servlet层先判断session里的用户角色。做到这一步你就已经把最典型的CRUD流程讲透了。前端JSP的消费列表展示也要配合起来一般是点进去看到列表页的表格数据来自request.setAttribute(list, dessertDao.findAll())这种写法——这也是最基础的JavaWeb口味。5. JavaWeb课设避坑指南四个让项目跑不起来的典型问题这部分是血泪经验。JavaWeb项目的坑不在代码本身而在环境、配置和路径的处理上。四个问题覆盖了绝大多数翻车现场每一条都是“现象→原因→解决”的完整格式。建议先把这章存下来跑不通的时候回来翻。5.1 数据库连接失败时区、密码、驱动三连坑现象Tomcat启动不报错但访问列表页时页面直接报Communications link failure或者Unknown database。原因三个高频因素。第一是MySQL 8.x以后连接串里必须加serverTimezone参数MySQL 5.7则不需要两个版本的配置差异在换环境时最容易踩中。第二是密码不匹配项目里写死的密码和你本地MySQL的密码不一致改了DBUtil.java后没有rebuild。第三是驱动类找不到ClassNotFoundException: com.mysql.jdbc.Driver通常是因为WEB-INF/lib目录下没有mysql-connector的jar包或者jar包放在了IDEA的Library里但没有打包进Artifact。解决先确认MySQL服务是否启动mysql -u root -p能不能连进去。再检查连接串如果本地MySQL是5.7就保持useSSLfalsecharacterEncodingutf8如果是8.x就加上serverTimezoneAsia/Shanghai驱动类换成com.mysql.cj.jdbc.Driver。最后在IDEA右侧Project Structure - Artifacts - WEB-INF/lib里确认jar包已经打进去。这个坑调试起来最费时间因为Tomcat日志不一定在控制台里打出完整堆栈有时只显示一个Unable to get connection容易以为代码写错了。5.2 404与500URL映射和lib目录里缺jar包现象项目启动后访问http://localhost:8080/直接404访问某个具体的/login页面也404或者打开页面显示500 internal server error。原因404的根源通常是映射问题。项目启动配置里Application context设置成了/dessert-system但JSP里的action路径写的是/login前端请求发到/loginTomcat在根路径下找不到对应Servlet于是404。另一个是Servlet注解映射写错——比如WebServlet(/login)和实际请求的/DessertServlet不一致。500的话往往是代码运行时抛出的异常比如查数据库失败的空指针、JSP代码里调用了不存在的变量。解决先看浏览器地址栏里的URL和项目部署路径是否匹配。如果部署路径带项目名JSP里所有跳转都应当带上request.getContextPath()前缀不要写死/login因为改成/dessert-system/login才算和Application context对应上。然后看控制台的Exception信息500基本都能在后几行找到Caused by。java.lang.NoClassDefFoundError出现时不要怀疑代码优先处理jar包缺失问题。JSTL的jar包尤其容易漏JSP页面用了c:forEach但lib里只有jstl.jar没有standard.jar启动时不一定报错页面渲染时才会挂掉。5.3 中文乱码Tomcat 8前后处理逻辑完全不同现象登录时输入中文用户名存进MySQL后变成一串问号后台添加甜品名称在列表页显示乱码前端页面本身显示中文正常但提交后乱。原因这是JavaWeb里最经典的编码链路问题。Tomcat 8.0以上默认URIEncodingUTF-8GET请求的中文参数基本不会乱码但只要代码里忘了request.setCharacterEncoding(UTF-8)POST请求中文一定乱码。还有一个隐蔽环节JSP页面顶部的pageEncoding、HTML的charset、以及MySQL表结构的character_set_client三层字符集只要有一层不是utf8就会在某一环节产生乱码。之前建表时用了utf8mb4但如果你直接在MySQL命令行执行SQL而客户端没有设置utf8同样会乱。解决在三层各自检查。代码里强制加request.setCharacterEncoding(UTF-8); response.setContentType(text/html;charsetUTF-8);JSP页面顶部确认% page languagejava contentTypetext/html; charsetUTF-8 pageEncodingUTF-8%。数据库连接串加上characterEncodingutf8。MySQL的my.cnf里三处character_set_serverutf8mb4。改完所有配置一定重启Tomcat再测一次因为改编码后不重启连接池里可能还存有老连接问题看起来像是没改一样。5.4 端口被占用与Tomcat启动失败现象点击启动Tomcat控制台立刻红字报错堆栈里能看到Port 8080 required by Tomcat v8.5 Server at localhost is already in use或java.net.BindException: Address already in use。原因另一个Tomcat实例在后台跑着没关掉或者开发工具里有其他中间件占了8080端口。IDEA里常见的是上次调试完直接关闭项目但Tomcat进程没退出尤其在使用Jrebel这类热部署插件时旧进程会被挂住。解决用之前提到过的netstat -ano | findstr 8080查占用进程并杀掉。但这里有个更干净的办法给IDEA配置一个自定义的Tomcat端口管理。编辑Tomcat安装目录下的conf/server.xml把Connector端口从8080改成8081、8082之类的空闲端口。改完后启动配置里的URL会自动变化不用手动改。如果改了端口依然报Address already in use说明/conf/server.xml里有多处端口配置Connector、AJP、redirectPort用grep -n port conf/server.xml全部列出来看一下。注意AJP端口8009也要同步改掉它和HTTP端口是独立的。6. 答辩前做点加法验证接口并规划购物车扩展的快捷路径项目能跑、代码能讲离高分还差一步展示你还“能改”。两个方向性价比最高的做法一是基于现有表结构扩展购物车功能二是用Postman这类接口工具验证后端逻辑让答辩时拿数据说话而不是只靠嘴巴描述。6.1 基于现有表结构扩展购物车购物车没必要新建表。常见做法是直接用Session实现临时购物车——把用户添加到购物车的甜品放在一个MapDessert, Integer里key是甜品对象、value是数量整体存进session。这属于黑马JavaWeb笔记里提到过的“Session实现购物车”方案好处是不用动数据库坏处是刷新丢失。实现时在甜品列表页加一个“加入购物车”的按钮提交到CartServlet逻辑代码大概是HttpSession session request.getSession(); MapInteger, Integer cart (MapInteger, Integer) session.getAttribute(cart); if (cart null) { cart new HashMap(); } int dessertId Integer.parseInt(request.getParameter(id)); cart.put(dessertId, cart.getOrDefault(dessertId, 0) 1); session.setAttribute(cart, cart); response.sendRedirect(request.getContextPath() /cart.jsp);这段代码的核心是一个Map容器key存甜品id、value存购买量每次点击把数量加1重新放进session。这套逻辑在答辩时说清楚“为什么用Map”比贴十行代码更有说服力。到了结算环节再读数据库算价格、写orders表和order_detail表整个链路一下就闭合了。6.2 用Postman验证接口答辩拿出数据说话答辩的时间往往很短与其现场用浏览器慢慢点不如提前在Postman里验证好几个核心接口。打开Postman新建一个请求输入登录接口的URL选择POST在Body里以form-data或x-www-form-urlencoded方式填上usernameadminpassword123456发送后观察返回码。登录成功后把session id记录再访问甜品列表接口确认能返回JSON或页面数据。如果项目接口返回的是JSP页面而不是JSON数据也没关系Postman同样能验证——看HTTP状态码和响应内容里是否包含预期文本。比如添加甜品接口发送后返回302重定向就说明插入成功返回200且页面里有错误信息就说明校验没通过。这套验证习惯值得养成毕竟等答辩现场再去查分页问题远不如提前用工具把数据录下来。自从我拿到了别人的课设项目每次接手都先跑一遍接口再改代码这个习惯帮我在好多次演示中避免了现挂的尴尬。希望这篇笔记能帮你少走一段弯路把项目攥在自己手里顺顺当当拿下这学期的JavaWeb课设。本文还有配套的精品资源点击获取
返回列表