简介:这是一套面向计算机相关专业毕业设计与JavaWeb实战练习的超市管理系统完整项目包,采用JSP、Servlet、JDBC技术栈,以MySQL为后台数据库,基于B/S结构开发,开发环境为JDK、Eclipse与Tomcat。系统划分员工与管理员两种角色,功能覆盖系统登录退出与密码修改、员工信息管理、商品信息管理、货架信息管理、商品类型管理、进货信息管理以及销售信息管理,各模块均支持增加与查询操作,业务链条较为完整。压缩包共68个文件,约3.5MB,包含19个java源文件、37个class编译文件、4个sql数据库脚本,以及jar依赖、图片资源与工程配置文件,源码、数据库脚本、软件工具和项目说明齐备,导入后可直接运行。目前已有799人学习下载,适合需要完整毕设方案、想梳理JavaWeb分层结构与数据库设计思路的学习者参考借鉴。
1. 拿到一份 Javaweb 超市管理系统源码,先别急着双击运行
很多同学拿到「基于Javaweb的超市管理系统源码+数据库(毕业设计).zip」这类压缩包,第一反应是解压、找 main 方法、点运行,然后被一堆 404、ClassNotFound、数据库连接失败糊一脸。这个标题背后其实是一套典型的 Javaweb 项目交付物:一份能跑起来的 Web 工程、一份可导入的 MySQL 脚本、一份让答辩老师看懂你干了啥的说明。它解决的不是「从零写一个超市系统」,而是「在有限时间里把一套完整案例跑通、改出个人痕迹、讲清技术栈」。适合两类人:一是被毕业设计卡住、需要一份可复现底稿的本科生;二是想拿一个完整案例练手 Javaweb 增删改查、JSP/Servlet 或 SSM 的初学者。下面我按自己带人做毕设的流程,把环境、导入、改代码、避坑、进阶一条线讲透,你照着走能少熬几个通宵。
2. 环境与工具链:IDEA 跑 Javaweb 项目前必须对齐的四件事
2.1 JDK、Tomcat、Maven 的版本三角关系
Javaweb 项目翻车,八成死在版本不匹配。常见做法是:JDK 用 1.8 或 11,Tomcat 用 8.5 或 9.0,Maven 用 3.6 以上。为什么不是越新越好?因为老项目里的 Servlet API 往往是 javax.servlet 而不是 jakarta.servlet,Tomcat 10 之后包名改成 jakarta,直接导致 ClassNotFound。我一般先看项目里WEB-INF/lib或pom.xml的依赖,再倒推 Tomcat 版本。
| 组件 | 推荐版本 | 判断依据 |
|---|---|---|
| JDK | 1.8 / 11 | 看 pom 里 source/target |
| Tomcat | 8.5 / 9.0 | 看 import 是 javax 还是 jakarta |
| Maven | 3.6+ | 能解析老仓库即可 |
| MySQL | 5.7 / 8.0 | 看脚本里的引擎和字符集 |
提示:如果项目没有 pom.xml,只有 lib 目录,那就是传统非 Maven 工程,别硬套 Maven 结构。
2.2 在 IDEA 里配置 Tomcat 并部署 war 的最小步骤
先确认项目结构:有src、WebContent或webapp、WEB-INF/web.xml。然后在 IDEA 里File → Project Structure → Modules把 src 标成 Sources,把 WebContent 标成 Web Resource Directory。接着Run → Edit Configurations → + → Tomcat Server → Local,在 Deployment 里加 Artifact,选war exploded。这一步的关键是 Application context 设成/或/sm,后面访问路径要和它一致。
# 检查端口占用,Tomcat 默认 8080 netstat -ano | findstr 8080 # 如果被占用,改 conf/server.xml 里的 Connector port逻辑说明:war exploded支持热更新,改 JSP 不用重启;war包则每次要重新部署。参数上,HTTP 端口和 JMX 端口别冲突,JMX 默认 1099,被占也会启动失败。
2.3 数据库脚本导入:字符集和引擎两个隐形雷
拿到.sql文件,别直接双击。先看头部有没有SET NAMES utf8mb4,再看建表语句的ENGINE=InnoDB DEFAULT CHARSET。MySQL 8.0 默认字符集是 utf8mb4,但老脚本常写 utf8,导入后中文变问号。我一般用命令行导入,方便看报错。
-- 先建库,字符集显式指定 CREATE DATABASE supermarket DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; USE supermarket; -- 再 source 脚本 SOURCE D:/supermarket.sql;逻辑说明:SOURCE是 MySQL 客户端命令,路径用正斜杠或双反斜杠。如果脚本里有DROP TABLE IF EXISTS,说明可重复导入。参数上,utf8mb4_general_ci对中文和 emoji 都友好,排序略快于 unicode_ci。
2.4 连接池配置:从 db.properties 到 Druid 的替换思路
项目里常见db.properties或jdbc.properties,里面写jdbc.url、username、password。如果用的是原生 JDBC,每次请求都新建连接,压测必崩。我一般会换成 Druid 或 HikariCP,但毕设阶段不折腾也行,先把maxActive调成 20 左右。
jdbc.driver=com.mysql.cj.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/supermarket?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai jdbc.username=root jdbc.password=123456逻辑说明:serverTimezone不写,MySQL 8.0 会报时区错误;characterEncoding=utf8要和库字符集一致。参数上,useSSL=false可去掉警告,生产再开。
3. 源码结构拆解:从 web.xml 到 DAO 层怎么读才不迷路
3.1 先看 web.xml 和注解,确定请求入口
Javaweb 项目有两种路由方式:web.xml 配置和注解。打开WEB-INF/web.xml,看有没有<servlet>和<servlet-mapping>。如果是注解,就搜@WebServlet。入口通常是 LoginServlet 或 IndexServlet。我一般先画一张请求链路:浏览器 → Filter → Servlet → Service → DAO → DB。
@WebServlet("/login") public class LoginServlet extends HttpServlet { protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException { // 1. 取参数 String username = req.getParameter("username"); // 2. 调 service // 3. 转发或重定向 } }逻辑说明:doPost处理表单,doGet处理地址栏。参数名要和 JSP 里name属性一致,否则取到 null。注意编码:req.setCharacterEncoding("UTF-8")要在取参数前调用。
3.2 分层结构:Controller、Service、DAO 各自该改哪里
毕设答辩常问「你做了什么」,如果你只改了 JSP 页面,老师一眼看穿。建议在 Service 层加一个业务方法,比如「库存不足时禁止下单」。DAO 层用 JDBC 或 MyBatis,看项目原样。常见做法是保留原 DAO,新增一个方法,这样改动小、可回溯。
public class GoodsService { private GoodsDao goodsDao = new GoodsDao(); public boolean reduceStock(int goodsId, int num) { Goods g = goodsDao.findById(goodsId); if (g.getStock() < num) { return false; // 库存不足 } return goodsDao.updateStock(goodsId, g.getStock() - num); } }逻辑说明:先查再判断再更新,三步缺一不可。参数上,goodsId和num要做非空和正数校验,否则负数会加库存。
3.3 前端页面:JSP 里 EL 表达式和 JSTL 的常见写法
JSP 页面里常见${user.username}和<c:forEach>。如果 EL 不解析,检查web.xml的版本是不是 2.4 以下,或者缺jstl.jar。我一般把列表页的表格列和数据库字段对一遍,防止字段名拼错。
<c:forEach items="${goodsList}" var="g"> <tr> <td>${g.id}</td> <td>${g.name}</td> <td>${g.stock}</td> </tr> </c:forEach>逻辑说明:items是 request 域里的 list,var是循环变量。参数上,如果显示乱码,在页面顶部加<%@ page contentType="text/html;charset=UTF-8" %>。
3.4 数据库增删改查:把 SQL 和 Java 参数对应起来
超市系统的核心表一般有:用户表、商品表、订单表、库存表。增删改查的 SQL 要防注入,用PreparedStatement。
String sql = "INSERT INTO goods(name, price, stock) VALUES(?, ?, ?)"; PreparedStatement ps = conn.prepareStatement(sql); ps.setString(1, goods.getName()); ps.setBigDecimal(2, goods.getPrice()); ps.setInt(3, goods.getStock()); ps.executeUpdate();逻辑说明:占位符从 1 开始,顺序和 SQL 一致。参数上,金额用 BigDecimal,别用 double,否则对账差几分钱。
4. 避坑与排查:Javaweb 超市管理系统跑不起来的五个血泪现场
4.1 现象:404,浏览器说路径找不到
原因:Application context 和访问 URL 不一致,或者web.xml里url-pattern写错。解决:在 IDEA 的 Tomcat 配置里看 Deployment 的 context,访问时带上;检查@WebServlet的值有没有斜杠。
4.2 现象:500,报 ClassNotFoundException: com.mysql.cj.jdbc.Driver
原因:MySQL 驱动 jar 没放进WEB-INF/lib,或者 Maven 依赖 scope 是 provided。解决:确认mysql-connector-java在 lib 下;Maven 项目改成 compile 或 runtime。
4.3 现象:中文乱码,页面显示问号
原因:数据库字符集、连接 URL、JSP 页面编码三者不一致。解决:库用 utf8mb4,URL 加characterEncoding=utf8,JSP 加pageEncoding="UTF-8",并在 Filter 里统一setCharacterEncoding。
4.4 现象:登录成功但跳转后 session 丢失
原因:重定向后 session 作用域不对,或者浏览器禁了 cookie。解决:用response.sendRedirect时带;jsessionid=xxx,或改用转发;检查 session 超时时间。
4.5 现象:导入 SQL 报 1067 Invalid default value
原因:MySQL 5.7 严格模式对datetime默认值0000-00-00不兼容。解决:在my.ini里去掉NO_ZERO_DATE,或把脚本里的默认值改成CURRENT_TIMESTAMP。
5. 进阶技巧:把毕设底稿改成能讲二十分钟的个人作品
5.1 加一个库存预警的定时任务
答辩时老师最爱问「有没有考虑并发」。你可以在 Service 里加一个ScheduledExecutorService,每十分钟扫一次库存,低于阈值就写日志或发站内信。代码不长,但能体现你懂线程池。
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(); scheduler.scheduleAtFixedRate(() -> { List<Goods> list = goodsDao.findLowStock(10); for (Goods g : list) { System.out.println("预警:" + g.getName() + " 库存 " + g.getStock()); } }, 0, 10, TimeUnit.MINUTES);逻辑说明:scheduleAtFixedRate按固定频率执行,参数依次是任务、初始延迟、间隔、单位。注意异常要捕获,否则任务会静默停止。
5.2 用 Postman 或 curl 做接口自测
别只点页面,用 curl 直接打 Servlet,能快速定位是前端还是后端问题。
curl -X POST http://localhost:8080/login -d "username=admin&password=123456" -v逻辑说明:-d是表单数据,-v看请求响应头。如果返回 302 且 Location 是主页,说明登录逻辑通了。
5.3 把数据库脚本和源码说明整理成答辩材料
我一般会做一张表,列出「我改动的文件、改了什么、为什么改」。比如把GoodsDao的查询改成带分页,把login.jsp加了验证码。这样老师问「你做了什么」时,你直接指表,不慌。
| 文件 | 改动 | 目的 |
|---|---|---|
| GoodsDao.java | 增加分页查询 | 避免全表扫描 |
| login.jsp | 增加验证码 | 防暴力登录 |
| db.properties | 换 Druid | 连接复用 |
5.4 一个我踩过的坑:别在答辩前夜换框架
有次我帮人把 JDBC 换成 MyBatis,结果 XML 映射写错,凌晨三点还在调。后来我定了个规矩:答辩前一周只做加法,不做替换。加一个功能、加一段注释、加一张表,都比换框架稳。源码是底稿,不是终点,你能讲清每一处改动的来龙去脉,比跑通一个花哨功能更值钱。希望帮到你。
本文还有配套的精品资源,点击获取