简介:这份资源是一套基于 JavaWeb 的超市收银系统完整源码,面向计算机专业学生、JavaWeb 初学者及需要课程设计或毕业设计参考的开发者,帮助解决收银结算、库存管理与销售统计等实际业务场景的开发需求。压缩包共 147 个文件,约 1.61MB,以 60 个 Java 源文件与 29 个 JSP 页面为主体,配合 22 个 MyBatis 映射文件、16 个 CSS 与 7 个 JS 前端资源,另有 SQL 建表脚本、Maven 配置及说明文档,结构完整、层次清晰。系统覆盖商品管理、订单管理、用户管理与统计分析四大模块,支持商品增删改查、库存预警、多支付方式、订单日志记录以及管理员、收银员、顾客多角色权限控制。目前已有 97 人学习,读者可据此快速理解 JavaWeb 分层架构与前后端交互流程,并在此基础上二次开发或直接用于课程实践。
1. 从一份 JavaWeb 超市收银系统源码说起:它到底能跑出什么
很多人拿到「基于 JavaWeb 的超市收银系统」这类源码包,第一反应是双击、找 main、点运行,然后被 404、数据库连接失败、Tomcat 版本不匹配轮番教育。它本质上是一套典型的 JavaWeb 三层架构应用:Servlet 或 SpringMVC 接请求,Service 处理收银、库存、会员、退货等业务,DAO 层用 JDBC 或 MyBatis 落库,前端是 JSP 或 HTML+Ajax。它解决的不是「高并发秒杀」这种问题,而是把扫码、计价、找零、小票、库存扣减、日结这条线下门店最核心的链路用代码固化下来。适合谁?课程设计要交作业的学生、想拿一个完整 CRUD 项目练手 MyBatis 和 Servlet 的后端新人、以及需要给小型便利店做一套能改能扩的收银底座的独立开发者。源码本身不是终点,能不能在本地跑通、能不能改出第二个门店,才是分水岭。
2. 跑通前的环境选型:JDK、Tomcat、MySQL 版本怎么配不翻车
2.1 为什么 JavaWeb 老项目最容易死在版本上
JavaWeb 收银系统这类源码,绝大多数是 2018 到 2022 年之间的产物,那个时间点的技术栈组合非常固定:JDK 8、Tomcat 8.5 或 9、MySQL 5.7、Maven 3.6。你如果直接上 JDK 17 + Tomcat 10 + MySQL 8,大概率会遇到三类问题:javax.servlet包在 Tomcat 10 里被换成了jakarta.servlet,所有 Servlet 直接编译不过;MySQL 8 的驱动类名和时区参数变了,连接池报Unknown system variable;JDK 17 对反射和模块系统的限制让老版 C3P0、Druid 报非法访问。所以第一步不是急着导入 IDEA,而是先确认源码里的pom.xml或lib目录,看它依赖的是哪个 servlet-api 版本。
判断方法很简单:打开pom.xml,搜servlet-api,如果 groupId 是javax.servlet,就锁死 Tomcat 9;如果是jakarta.servlet,才用 Tomcat 10。数据库同理,看jdbc.properties或db.properties里的 URL,带serverTimezone的通常是 MySQL 8 写法,不带的多半是 5.7。
2.2 一套能直接抄的环境清单
下面这张表是我在 Windows 和 macOS 上都验证过的组合,针对「javax.servlet + MySQL 5.7 风格」的收银系统源码:
| 组件 | 推荐版本 | 说明 |
|---|---|---|
| JDK | 1.8.0_301 | 不要用 8u 之后的过高小版本,避免 TLS 差异 |
| Tomcat | 9.0.65 | 支持 javax.servlet,且比 8.5 稳定 |
| MySQL | 5.7.38 | 与老驱动兼容性最好 |
| Maven | 3.6.3 | 3.8+ 对 http 仓库拦截更严 |
| IDEA | 2021.3 | 对老项目索引更友好 |
安装完 JDK 后,务必确认JAVA_HOME指向 JDK 而不是 JRE,否则 Tomcat 启动会报No compiler is provided。MySQL 安装时字符集选utf8mb4,排序规则utf8mb4_general_ci,因为收银系统里商品名、会员名经常有中文和生僻字。
2.3 导入 IDEA 并让项目识别为 Web 应用
很多新手卡在「IDEA 里没有 Web 选项」。正确姿势是:先File -> Open选中源码根目录(有pom.xml的那层),等 Maven 依赖下载完,再File -> Project Structure -> Facets -> + -> Web,把web或webapp目录指为 Web 资源目录,web.xml路径指对。如果是非 Maven 的老式项目,还要在Modules -> Dependencies里手动加lib下的所有 jar。
# 验证 JDK 和 Maven 是否就位 java -version mvn -v # 在项目根目录执行,强制刷新依赖 mvn clean compile -DskipTestsmvn clean compile这一步非常关键,它能在你启动 Tomcat 之前就把编译错误暴露出来。如果这里报package javax.servlet does not exist,说明依赖没下全或者 Tomcat 版本选错了,先解决这个再往下走。参数-DskipTests是因为老项目的单元测试经常依赖外部环境,跳过能省时间。
3. 数据库初始化:建库、导表、改连接串的三步操作
3.1 从 sql 文件到可用的收银库
源码包里通常会有一个sql目录或根目录下的.sql文件,里面是建库建表语句加初始数据。不要直接复制粘贴到 Navicat 里一把梭,先看文件头部有没有CREATE DATABASE。如果没有,你得自己建库,库名要和连接串里的一致。
-- 常见收银系统的核心表结构(简化示意) CREATE DATABASE IF NOT EXISTS supermarket DEFAULT CHARACTER SET utf8mb4; USE supermarket; -- 商品表:收银扫码的核心 CREATE TABLE product ( id INT PRIMARY KEY AUTO_INCREMENT, barcode VARCHAR(50) UNIQUE NOT NULL COMMENT '条形码', name VARCHAR(100) NOT NULL, price DECIMAL(10,2) NOT NULL, stock INT DEFAULT 0, category_id INT ); -- 销售订单表:日结和报表的数据源 CREATE TABLE sale_order ( id INT PRIMARY KEY AUTO_INCREMENT, order_no VARCHAR(32) UNIQUE NOT NULL, total_amount DECIMAL(10,2), pay_type TINYINT COMMENT '1现金 2微信 3支付宝', create_time DATETIME DEFAULT CURRENT_TIMESTAMP );导入时注意两点:一是如果 sql 文件里用了ENGINE=InnoDB但你的 MySQL 默认引擎是 MyISAM,要显式指定;二是初始数据里的密码字段如果是 MD5,登录时要用对应算法,别自己改成明文。
3.2 连接串里四个必改参数
打开src/main/resources下的jdbc.properties或db.properties,逐项核对:
jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/supermarket?useUnicode=true&characterEncoding=utf8&useSSL=false jdbc.username=root jdbc.password=你的密码driver这一项,MySQL 5.7 用com.mysql.jdbc.Driver,MySQL 8 用com.mysql.cj.jdbc.Driver,写错直接ClassNotFoundException。url里的useSSL=false在老驱动上能避免一堆警告,characterEncoding=utf8保证中文不乱码。用户名密码改成你本地的,别照抄源码里的root/123456。
3.3 用一条查询验证数据库真的通了
在写 Java 代码之前,先用 Navicat 或命令行执行一条查询,确认表和数据都在:
SELECT p.name, p.price, p.stock FROM product p WHERE p.barcode = '6901234567890';如果这条能查出商品,说明库、表、数据、字符集都没问题。查不到就回头检查 sql 是否导入到了正确的库,以及 barcode 是否真的存在。这一步能帮你把「数据库问题」和「Java 代码问题」提前隔离开,省下大量瞎猜时间。
4. 启动与联调:Tomcat 部署、扫码收银链路怎么验证
4.1 在 IDEA 里配置 Tomcat 运行
Run -> Edit Configurations -> + -> Tomcat Server -> Local,在Deployment标签页点+ -> Artifact,选war exploded形式。Application context建议设成/或/supermarket,要和源码里 JSP 的链接前缀一致。Server标签页里,On Update action选Update classes and resources,这样改 Java 代码不用重启。
启动后如果控制台刷出Server startup in xxx ms,说明 Tomcat 起来了。访问http://localhost:8080/,能看到登录页就成功了一半。如果报 404,先检查web.xml里的welcome-file和实际首页文件名是否一致。
4.2 收银主链路的四个验证点
收银系统的核心链路是:登录 -> 扫码加购 -> 结算 -> 扣库存。逐个验证:
第一,登录。用 sql 里的初始账号,通常是admin/123456。如果登录失败,看控制台有没有NullPointerException,多半是 Service 层没注入或者密码加密方式不匹配。
第二,扫码。在收银界面输入一个真实存在的 barcode,看商品名和价格是否自动带出。这一步走的是product表的查询,如果带不出,检查前端 Ajax 的 URL 和后端 Servlet 的@WebServlet或web.xml映射是否一致。
第三,结算。选支付方式,点结算,看是否生成订单号并跳转小票页。订单号一般用时间戳加随机数,如果重复会报唯一索引冲突。
第四,扣库存。结算后回product表查该商品 stock 是否减 1。如果没减,看 Service 里扣库存的 SQL 是不是漏了WHERE stock >= 1的条件,这个条件能防止超卖。
// 扣库存的典型写法,注意 WHERE 条件 public int reduceStock(int productId, int qty) { String sql = "UPDATE product SET stock = stock - ? WHERE id = ? AND stock >= ?"; // 参数顺序:扣减数量、商品ID、扣减数量 return jdbcTemplate.update(sql, qty, productId, qty); }这段代码的关键在AND stock >= ?,它把「检查库存」和「扣减库存」合并成一条原子 SQL,避免先查后扣导致的并发超卖。返回值为 0 说明库存不足,Service 层要抛业务异常并回滚订单。
4.3 用日志定位前后端断点
老项目日志往往只配了log4j.properties或logback.xml,级别设成DEBUG能看到 SQL 和请求参数。如果前端点了没反应,先按 F12 看 Network 里请求是否发出、状态码是多少。500 就去 Tomcat 控制台找堆栈,404 就查 URL 映射,400 多半是参数类型对不上。这套排查顺序比盲目改代码高效得多。
5. 避坑与排查:源码跑不起来时先看这五条
5.1 启动报 ClassNotFoundException: com.mysql.jdbc.Driver
现象:Tomcat 一启动就抛这个异常,应用直接挂掉。原因:MySQL 驱动 jar 没放进WEB-INF/lib,或者 Maven 依赖 scope 写成了provided。解决:确认pom.xml里 mysql-connector 的 scope 是runtime或默认,非 Maven 项目就把 jar 复制到web/WEB-INF/lib下,并在 IDEA 的 Artifact 里确认它被包含进输出。
5.2 页面中文全是问号或乱码
现象:商品名显示成???。原因:数据库字符集、连接串字符集、JSP 页面编码三者不一致。解决:库和表用utf8mb4,连接串加characterEncoding=utf8,JSP 头部加<%@ page contentType="text/html;charset=UTF-8" %>,三处统一后再重启。
5.3 登录后一直跳回登录页
现象:输入正确账号密码,还是回到 login。原因:Session 没保持住,或者拦截器 Filter 把静态资源也拦了。解决:检查web.xml里 Filter 的url-pattern,排除.css、.js、.png;再看浏览器是否禁用了 Cookie,Session 依赖 JSESSIONID。
5.4 扫码后价格不显示
现象:输入条码,商品名出来了但价格是空。原因:前端拿的字段名和后端返回的 JSON key 不一致,比如后端返回price,前端读的是productPrice。解决:F12 看接口返回的原始 JSON,把前端字段名对齐,或者在后端 VO 里加@JsonProperty。
5.5 结算时报 Duplicate entry for key 'order_no'
现象:偶尔结算失败,报唯一索引冲突。原因:订单号生成规则用了秒级时间戳,同一秒内多笔订单会重复。解决:订单号改成时间戳 + 随机数 + 收银员ID,或者直接用数据库自增主键加日期前缀。
6. 从能跑到能改:二次开发与数据校验的进阶手法
跑通只是及格线,真正让这套源码产生价值的是改出你自己的门店逻辑。我一般会先做两件事:一是把收银小票的打印格式改成自己需要的,二是加一个日结报表的导出。小票打印通常走JasperReports或纯 HTML 打印,找到receipt.jsp改字段即可。日结报表则是加一个SaleReportServlet,按create_time分组统计total_amount。
-- 日结报表核心查询:按支付方式汇总 SELECT DATE(create_time) AS sale_date, pay_type, COUNT(*) AS order_count, SUM(total_amount) AS total FROM sale_order WHERE create_time >= CURDATE() GROUP BY DATE(create_time), pay_type;这条 SQL 能直接喂给前端表格,pay_type在前端映射成「现金/微信/支付宝」。注意CURDATE()只取当天,如果要查历史就换成参数传入。
改代码时最容易忽略的是数据校验。收银系统里金额和库存是敏感字段,前端校验只是体验,后端必须再校验一次。比如结算接口要校验total_amount是否等于购物车各项之和,防止前端被篡改。我习惯在 Service 层加一个validateOrder方法,把金额、库存、支付方式三项都过一遍,不通过就抛异常回滚。
还有一个实用技巧:给product表的barcode加唯一索引后,扫码查询会走索引,速度明显提升。如果商品量大,再给category_id加普通索引,分类筛选就不卡了。这些索引调整不需要改 Java 代码,但对收银体验的提升立竿见影。
最后说个我踩过的坑:有次改完代码,IDEA 热部署没生效,页面还是旧的,我排查了半小时才发现是 Artifact 没重新构建。后来我养成习惯,改完 Java 代码先Build -> Rebuild Project,再点 Tomcat 的重新部署按钮,省下不少后悔药。这套源码值不值得投入,取决于你是只想交个作业,还是想把它当成一个能持续迭代的收银底座。如果是后者,先把上面这些环境、数据库、链路验证做扎实,后面每加一个功能都会顺很多。希望帮到你。
本文还有配套的精品资源,点击获取