如果你是一名Java初学者或者正在为期末项目、课程设计、毕业设计寻找一个“麻雀虽小五脏俱全”的实战项目那么这篇文章就是为你准备的。超市管理系统这个听起来有些“经典”甚至“老套”的题目恰恰是检验你Java Web技术栈掌握程度的绝佳试金石。很多人以为它只是简单的增删改查CRUD但一个真正能跑通、能演示、能写在简历里的项目背后隐藏着从环境搭建、数据库设计、前后端交互到部署上线的完整工程化思维。本文将带你从零开始手把手实现一个功能完整的超市管理系统。我们不止于“半小时搞定”的噱头而是要深入剖析每个环节为什么选择这些技术数据库表如何设计才合理前后端数据如何流转遇到坑怎么快速排查最终你将获得一个包含商品管理、员工管理、供应商管理、销售统计等核心模块且代码结构清晰、易于扩展的项目。文末会提供完整的源码获取方式。1. 为什么超市管理系统是Java Web入门的黄金项目在开始敲代码之前我们先要搞清楚这个项目的价值。它绝不是一个过时的练习题而是凝聚了企业级应用开发核心思想的微型样板。第一技术栈全面且经典。一个标准的超市管理系统几乎覆盖了Java Web开发的所有基础环节后端Servlet/JSP或Spring MVC、JDBC或MyBatis、JavaBean。前端JSP、HTML、CSS、JavaScript、AJAX。数据库MySQL或Oracle。服务器Tomcat。工程管理Maven。通过这个项目你能将散落的知识点如Servlet生命周期、MVC模式、SQL编写、事务处理串联成一个有机整体。第二业务逻辑贴近现实易于理解。“进货-库存-销售”的流程非常直观这让你能更专注于技术实现而不是纠结于复杂的业务规则。你可以清晰地看到一条数据如一件商品是如何在系统中被创建、查询、修改、关联如与销售记录关联并最终被删除或归档的。第三具备足够的扩展性和深度。基础版本完成后你可以以此为起点进行无限深化加深技术深度将JDBC替换为MyBatis或JPA将原生Servlet/JSP升级为Spring Boot引入Redis缓存商品信息使用ECharts实现更酷炫的数据报表。扩展业务功能增加会员积分系统、促销活动模块、多仓库库存管理、移动端扫码入库等。对于面试官而言一个你能从头到尾讲清楚设计思路、技术选型和难点攻克的项目远比罗列一堆技术名词更有说服力。接下来我们就进入实战环节。2. 项目核心功能与系统设计我们的超市管理系统将包含以下核心功能模块这也是一个管理系统最典型的组成部分用户管理系统登录、注销、权限控制如管理员与普通收银员。商品管理商品的增、删、改、查以及分类管理。供应商管理维护商品供应商信息。库存管理记录商品入库采购、出库销售流水动态计算库存。销售管理模拟收银台功能生成销售单据。统计报表按日、月统计销售额、毛利分析畅销商品。系统架构设计MVC模式这是本项目的灵魂。我们将采用经典的JSP Servlet JavaBean模式这也是理解更高级框架如Spring MVC的基础。Model模型JavaBean/DAO对应数据库中的实体如Product,User和访问这些实体的类ProductDao,UserDao。负责业务数据和业务逻辑。View视图JSP用户看到的界面如商品列表页product_list.jsp、登录页login.jsp。负责展示数据。Controller控制器Servlet如ProductServlet、LoginServlet。接收用户请求来自View调用Model处理并将结果返回给View。这种分离使得代码结构清晰易于维护和测试。3. 开发环境与工具准备工欲善其事必先利其器。请确保你的电脑上已安装以下环境JDK版本 8 或 11推荐8兼容性最好。安装后配置JAVA_HOME环境变量。IDEIntelliJ IDEA终极版或社区版或 Eclipse。本文演示以IDEA为主。Web服务器Apache Tomcat 9.x。下载后解压即可。数据库MySQL 5.7 或 8.0。推荐使用图形化工具如Navicat或MySQL Workbench辅助操作。项目管理Maven 3.6。IDEA通常内置。在IDEA中配置Tomcat打开Run/Debug Configurations。点击选择Tomcat Server - Local。在Application server处点击Configure...选择你的Tomcat解压目录。在Deployment标签页点击选择Artifact添加你的Web项目。环境配置是第一个“拦路虎”如果遇到ClassNotFoundException或404错误十有八九是环境或部署问题。请务必先确保一个简单的Hello WorldJSP页面能在Tomcat上正常运行。4. 数据库设计与建表数据库设计是项目的基石。一个糟糕的表结构会让后续编码举步维艰。我们遵循第三范式进行基础设计核心表如下user用户表CREATE TABLE user ( id int(11) NOT NULL AUTO_INCREMENT COMMENT 用户ID, username varchar(50) NOT NULL COMMENT 用户名, password varchar(100) NOT NULL COMMENT 密码建议MD5加密存储, real_name varchar(50) DEFAULT NULL COMMENT 真实姓名, role varchar(20) NOT NULL DEFAULT cashier COMMENT 角色admin管理员, cashier收银员, create_time datetime DEFAULT CURRENT_TIMESTAMP COMMENT 创建时间, PRIMARY KEY (id), UNIQUE KEY uni_username (username) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT系统用户表;product商品表CREATE TABLE product ( id int(11) NOT NULL AUTO_INCREMENT COMMENT 商品ID, product_no varchar(50) NOT NULL COMMENT 商品编号唯一, name varchar(100) NOT NULL COMMENT 商品名称, category varchar(50) DEFAULT NULL COMMENT 分类, purchase_price decimal(10,2) NOT NULL COMMENT 进货价, sale_price decimal(10,2) NOT NULL COMMENT 零售价, stock int(11) NOT NULL DEFAULT 0 COMMENT 当前库存, supplier_id int(11) DEFAULT NULL COMMENT 供应商ID, create_time datetime DEFAULT CURRENT_TIMESTAMP COMMENT 创建时间, update_time datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 更新时间, PRIMARY KEY (id), UNIQUE KEY uni_product_no (product_no), KEY idx_supplier (supplier_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT商品信息表;supplier供应商表CREATE TABLE supplier ( id int(11) NOT NULL AUTO_INCREMENT, name varchar(100) NOT NULL COMMENT 供应商名称, contact varchar(50) DEFAULT NULL COMMENT 联系人, phone varchar(20) DEFAULT NULL COMMENT 电话, address varchar(200) DEFAULT NULL COMMENT 地址, PRIMARY KEY (id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT供应商表;stock_log库存流水表这是实现库存准确性的关键。CREATE TABLE stock_log ( id int(11) NOT NULL AUTO_INCREMENT, product_id int(11) NOT NULL COMMENT 商品ID, type varchar(20) NOT NULL COMMENT 类型purchase采购入库, sale销售出库, adjust库存调整, quantity int(11) NOT NULL COMMENT 变动数量正数为入库负数为出库, operator_id int(11) DEFAULT NULL COMMENT 操作员ID, remark varchar(200) DEFAULT NULL COMMENT 备注, create_time datetime DEFAULT CURRENT_TIMESTAMP COMMENT 创建时间, PRIMARY KEY (id), KEY idx_product (product_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT库存流水表;sale_order与sale_item销售订单与订单明细表这是一对多的关系是处理销售业务的标准设计。-- 销售订单主表 CREATE TABLE sale_order ( order_no varchar(50) NOT NULL COMMENT 订单号可生成唯一编号, total_amount decimal(10,2) NOT NULL COMMENT 订单总金额, cashier_id int(11) NOT NULL COMMENT 收银员ID, create_time datetime DEFAULT CURRENT_TIMESTAMP COMMENT 下单时间, PRIMARY KEY (order_no) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT销售订单表; -- 销售订单明细表 CREATE TABLE sale_item ( id int(11) NOT NULL AUTO_INCREMENT, order_no varchar(50) NOT NULL COMMENT 关联订单号, product_id int(11) NOT NULL COMMENT 商品ID, quantity int(11) NOT NULL COMMENT 销售数量, sale_price decimal(10,2) NOT NULL COMMENT 成交单价, subtotal decimal(10,2) NOT NULL COMMENT 小计金额, PRIMARY KEY (id), KEY idx_order (order_no), KEY idx_product (product_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT销售订单明细表;设计要点唯一约束如user.username,product.product_no防止数据重复。索引在经常查询的字段上建立索引如product.supplier_id,stock_log.product_id。数据类型金额使用DECIMAL避免浮点数精度问题。时间戳使用CURRENT_TIMESTAMP自动记录创建和更新时间。外键关系虽然上述SQL未显式声明外键考虑到性能和灵活性但在逻辑上必须维护product.supplier_id与supplier.id等关系的正确性。5. 项目骨架搭建与Maven配置我们使用Maven来管理项目依赖和构建。在IDEA中创建新项目选择Maven并勾选Create from archetype选择maven-archetype-webapp。关键的pom.xml依赖配置project xmlnshttp://maven.apache.org/POM/4.0.0 xmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd modelVersion4.0.0/modelVersion groupIdcom.supermarket/groupId artifactIdsupermarket-management/artifactId version1.0-SNAPSHOT/version packagingwar/packaging properties project.build.sourceEncodingUTF-8/project.build.sourceEncoding maven.compiler.source1.8/maven.compiler.source maven.compiler.target1.8/maven.compiler.target /properties dependencies !-- Servlet JSP API -- dependency groupIdjavax.servlet/groupId artifactIdjavax.servlet-api/artifactId version4.0.1/version scopeprovided/scope /dependency dependency groupIdjavax.servlet.jsp/groupId artifactIdjavax.servlet.jsp-api/artifactId version2.3.3/version scopeprovided/scope /dependency !-- JSTL 标签库用于在JSP中简化逻辑 -- dependency groupIdjavax.servlet/groupId artifactIdjstl/artifactId version1.2/version /dependency !-- MySQL 驱动 -- dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId version8.0.33/version /dependency !-- 数据库连接池Druid性能好监控功能强大 -- dependency groupIdcom.alibaba/groupId artifactIddruid/artifactId version1.2.20/version /dependency !-- 日志框架SLF4J Logback -- dependency groupIdorg.slf4j/groupId artifactIdslf4j-api/artifactId version1.7.36/version /dependency dependency groupIdch.qos.logback/groupId artifactIdlogback-classic/artifactId version1.2.12/version /dependency !-- JSON处理Gson -- dependency groupIdcom.google.code.gson/groupId artifactIdgson/artifactId version2.10.1/version /dependency /dependencies build finalNamesupermarket/finalName plugins !-- 编译插件 -- plugin groupIdorg.apache.maven.plugins/groupId artifactIdmaven-compiler-plugin/artifactId version3.11.0/version configuration source1.8/source target1.8/target /configuration /plugin /plugins /build /project项目目录结构创建标准的Maven Web项目结构src/main/java └── com.supermarket ├── controller (Servlet控制器) ├── service (业务逻辑层) ├── dao (数据访问层接口和实现) ├── model (JavaBean实体类) └── util (工具类如数据库连接、字符串处理) src/main/resources └── db.properties (数据库配置文件) src/main/webapp ├── WEB-INF │ ├── web.xml (部署描述符) │ └── lib (依赖jar包Maven管理则无需手动放) ├── css ├── js ├── images └── *.jsp (视图页面)6. 核心代码实现从数据库连接到业务逻辑我们以商品管理模块为例贯穿MVC三层展示核心代码。第一步模型层Model - 实体类与数据库连接src/main/java/com/supermarket/model/Product.java:package com.supermarket.model; import java.math.BigDecimal; import java.util.Date; public class Product { private Integer id; private String productNo; private String name; private String category; private BigDecimal purchasePrice; // 使用BigDecimal处理金额 private BigDecimal salePrice; private Integer stock; private Integer supplierId; private Date createTime; private Date updateTime; // 省略getter和setter方法以及toString方法 }src/main/java/com/supermarket/util/DBUtil.java(数据库连接工具类):package com.supermarket.util; import com.alibaba.druid.pool.DruidDataSource; import javax.sql.DataSource; import java.io.InputStream; import java.sql.Connection; import java.sql.SQLException; import java.util.Properties; public class DBUtil { private static DataSource dataSource; static { try { Properties props new Properties(); InputStream is DBUtil.class.getClassLoader().getResourceAsStream(db.properties); props.load(is); DruidDataSource druidDataSource new DruidDataSource(); druidDataSource.setDriverClassName(props.getProperty(jdbc.driver)); druidDataSource.setUrl(props.getProperty(jdbc.url)); druidDataSource.setUsername(props.getProperty(jdbc.username)); druidDataSource.setPassword(props.getProperty(jdbc.password)); // 其他连接池配置... dataSource druidDataSource; } catch (Exception e) { throw new RuntimeException(初始化数据库连接池失败, e); } } public static Connection getConnection() throws SQLException { return dataSource.getConnection(); } public static void close(Connection conn) { if (conn ! null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } }src/main/resources/db.properties:jdbc.drivercom.mysql.cj.jdbc.Driver jdbc.urljdbc:mysql://localhost:3306/supermarket_db?useUnicodetruecharacterEncodingUTF-8serverTimezoneAsia/Shanghai jdbc.usernameroot jdbc.passwordyour_password第二步数据访问层DAOsrc/main/java/com/supermarket/dao/ProductDao.java(接口):package com.supermarket.dao; import com.supermarket.model.Product; import java.util.List; public interface ProductDao { int addProduct(Product product); int deleteProductById(int id); int updateProduct(Product product); Product getProductById(int id); ListProduct getAllProducts(); ListProduct getProductsByName(String name); }src/main/java/com/supermarket/dao/impl/ProductDaoImpl.java(实现类):package com.supermarket.dao.impl; import com.supermarket.dao.ProductDao; import com.supermarket.model.Product; import com.supermarket.util.DBUtil; import java.sql.*; import java.util.ArrayList; import java.util.List; public class ProductDaoImpl implements ProductDao { Override public int addProduct(Product product) { Connection conn null; PreparedStatement pstmt null; String sql INSERT INTO product(product_no, name, category, purchase_price, sale_price, stock, supplier_id) VALUES(?,?,?,?,?,?,?); try { conn DBUtil.getConnection(); pstmt conn.prepareStatement(sql); pstmt.setString(1, product.getProductNo()); pstmt.setString(2, product.getName()); pstmt.setString(3, product.getCategory()); pstmt.setBigDecimal(4, product.getPurchasePrice()); pstmt.setBigDecimal(5, product.getSalePrice()); pstmt.setInt(6, product.getStock()); pstmt.setInt(7, product.getSupplierId()); return pstmt.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); return 0; } finally { // 关闭资源实际项目应使用try-with-resources或工具方法 DBUtil.close(conn); } } // 省略其他方法delete, update, query的实现... }第三步业务逻辑层Servicesrc/main/java/com/supermarket/service/ProductService.java:package com.supermarket.service; import com.supermarket.model.Product; import java.util.List; public interface ProductService { boolean addProduct(Product product); boolean deleteProduct(int id); boolean updateProduct(Product product); Product getProductById(int id); ListProduct getAllProducts(); ListProduct searchProducts(String keyword); }src/main/java/com/supermarket/service/impl/ProductServiceImpl.java:package com.supermarket.service.impl; import com.supermarket.dao.ProductDao; import com.supermarket.dao.impl.ProductDaoImpl; import com.supermarket.model.Product; import com.supermarket.service.ProductService; import java.util.List; public class ProductServiceImpl implements ProductService { private ProductDao productDao new ProductDaoImpl(); Override public boolean addProduct(Product product) { // 这里可以添加业务逻辑例如检查商品编号是否重复 if (productDao.getProductByNo(product.getProductNo()) ! null) { return false; // 编号重复 } return productDao.addProduct(product) 0; } // 省略其他方法实现... }第四步控制层Controller - Servletsrc/main/java/com/supermarket/controller/ProductServlet.java:package com.supermarket.controller; import com.supermarket.model.Product; import com.supermarket.service.ProductService; import com.supermarket.service.impl.ProductServiceImpl; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.List; WebServlet(/product/*) // 使用路径映射 public class ProductServlet extends HttpServlet { private ProductService productService new ProductServiceImpl(); Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String pathInfo req.getPathInfo(); // 获取 /add, /delete, /list 等路径 if (/list.equals(pathInfo)) { ListProduct productList productService.getAllProducts(); req.setAttribute(productList, productList); req.getRequestDispatcher(/WEB-INF/jsp/product_list.jsp).forward(req, resp); } else if (/edit.equals(pathInfo)) { String id req.getParameter(id); Product product productService.getProductById(Integer.parseInt(id)); req.setAttribute(product, product); req.getRequestDispatcher(/WEB-INF/jsp/product_edit.jsp).forward(req, resp); } // 处理其他GET请求... } Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.setCharacterEncoding(UTF-8); // 处理中文乱码 String pathInfo req.getPathInfo(); if (/add.equals(pathInfo)) { Product product new Product(); product.setProductNo(req.getParameter(productNo)); product.setName(req.getParameter(name)); // ... 设置其他属性 boolean success productService.addProduct(product); if (success) { resp.sendRedirect(req.getContextPath() /product/list); // 重定向到列表页 } else { req.setAttribute(errorMsg, 添加商品失败可能编号重复); req.getRequestDispatcher(/WEB-INF/jsp/product_add.jsp).forward(req, resp); } } // 处理其他POST请求更新、删除... } }第五步视图层View - JSPsrc/main/webapp/WEB-INF/jsp/product_list.jsp(商品列表页):% page contentTypetext/html;charsetUTF-8 languagejava % % taglib prefixc urihttp://java.sun.com/jsp/jstl/core % html head title商品管理/title link relstylesheet typetext/css href${pageContext.request.contextPath}/css/style.css /head body h1商品列表/h1 a href${pageContext.request.contextPath}/product/addPage新增商品/a table border1 cellspacing0 tr th编号/thth名称/thth分类/thth进货价/thth零售价/thth库存/thth操作/th /tr c:forEach items${productList} varproduct tr td${product.productNo}/td td${product.name}/td td${product.category}/td td${product.purchasePrice}/td td${product.salePrice}/td td${product.stock}/td td a href${pageContext.request.contextPath}/product/edit?id${product.id}编辑/a a hrefjavascript:if(confirm(确定删除吗)) location.href${pageContext.request.contextPath}/product/delete?id${product.id}删除/a /td /tr /c:forEach /table /body /html7. 核心业务销售与库存联动的实现这是项目的难点和亮点。销售商品时必须保证库存减少和生成销售记录这两个操作在一个数据库事务中完成否则会导致数据不一致比如卖了商品但库存没减。服务层实现销售逻辑 (SaleService):package com.supermarket.service.impl; import com.supermarket.dao.ProductDao; import com.supermarket.dao.SaleDao; import com.supermarket.dao.StockLogDao; import com.supermarket.model.SaleOrder; import com.supermarket.model.SaleItem; import com.supermarket.model.StockLog; import java.sql.Connection; import java.sql.SQLException; import java.util.List; public class SaleServiceImpl { private ProductDao productDao; private SaleDao saleDao; private StockLogDao stockLogDao; // 假设有一个获取数据库连接并管理事务的工具类 private Connection conn DBUtil.getConnection(); // 注意实际应用应从线程上下文获取连接 public boolean makeSale(SaleOrder order, ListSaleItem items) { // 关键开启事务手动控制 try { conn.setAutoCommit(false); // 关闭自动提交 // 1. 插入销售订单主表 saleDao.insertOrder(order); // 2. 循环插入销售明细并更新对应商品库存 for (SaleItem item : items) { saleDao.insertItem(item); // 更新商品库存减少 int affectedRows productDao.updateStock(item.getProductId(), -item.getQuantity()); if (affectedRows 0) { throw new RuntimeException(商品库存不足或不存在商品ID: item.getProductId()); } // 3. 记录库存流水出库 StockLog log new StockLog(); log.setProductId(item.getProductId()); log.setType(sale); log.setQuantity(-item.getQuantity()); // 出库为负数 log.setRemark(销售出库订单号 order.getOrderNo()); stockLogDao.insert(log); } // 所有操作成功提交事务 conn.commit(); return true; } catch (Exception e) { // 任何一步出错回滚事务 try { conn.rollback(); } catch (SQLException ex) { ex.printStackTrace(); } e.printStackTrace(); return false; } finally { try { conn.setAutoCommit(true); // 恢复自动提交模式 conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } }关键点setAutoCommit(false)、commit()、rollback()。这确保了“扣库存”和“记销售”要么同时成功要么同时失败数据永远一致。8. 项目运行、部署与测试数据库初始化运行前面提供的SQL脚本创建数据库和表。可以插入一些测试数据。配置数据库连接修改db.properties中的用户名和密码。IDEA中配置Tomcat并启动将项目添加到Tomcat服务器点击运行。访问应用浏览器打开http://localhost:8080/supermarket/login.jsp(假设你的应用上下文路径是/supermarket)。功能测试登录测试使用预先插入的用户如admin/123456登录。商品管理测试尝试添加、查询、修改、删除商品。销售测试在销售界面选择商品、输入数量完成销售。检查库存是否准确减少销售订单和流水是否生成。报表测试查看销售统计报表。9. 常见问题与排查指南QA在开发过程中你几乎一定会遇到以下问题问题现象可能原因排查方式解决方案访问JSP页面报404错误1. 项目未成功部署到Tomcat。2. URL路径错误。3.web.xml配置错误或Servlet注解未生效。1. 检查IDEA中Tomcat的Deployment选项卡确保项目Artifact已添加。2. 检查浏览器地址栏URL是否与应用上下文路径匹配。3. 检查WebServlet注解路径或web.xml中的url-pattern。1. 重新部署项目。2. 使用${pageContext.request.contextPath}获取正确路径。3. 清理Tomcat工作目录并重启。页面中文乱码1. JSP页面编码未设置。2. Servlet未设置请求/响应编码。3. 数据库连接字符集不对。1. 检查JSP文件头% page pageEncodingUTF-8%。2. 在Servlet的doPost方法开始处调用request.setCharacterEncoding(UTF-8)和response.setContentType(text/html;charsetUTF-8)。3. 检查MySQL连接URL是否包含characterEncodingUTF-8。统一所有环节的编码为UTF-8。数据库连接失败1. MySQL服务未启动。2.db.properties配置错误密码、端口、数据库名。3. 驱动版本与MySQL版本不匹配。1. 检查MySQL服务状态。2. 使用Navicat等工具测试连接信息。3. 查看Tomcat日志中的具体SQLException信息。1. 启动MySQL服务。2. 核对配置文件。3. 更换合适的JDBC驱动版本如MySQL 8.0使用com.mysql.cj.jdbc.Driver。插入数据失败但无报错1. 事务未提交。2. 程序捕获了异常但未打印或处理。1. 检查DAO层操作后是否调用了connection.commit()如果关闭了自动提交。2. 在catch块中打印e.printStackTrace()。1. 确保事务正确提交。2. 完善异常处理将日志输出到控制台或文件。页面显示“No suitable driver found”JDBC驱动未加载。检查项目的WEB-INF/lib目录下是否有mysql-connector-java-xxx.jar或Maven依赖是否下载成功。确保依赖正确。Maven项目可以执行mvn clean compile检查。10. 项目优化与扩展建议最佳实践完成基础版本后你可以从以下方向深化项目这会让你的项目在面试中脱颖而出引入前端框架将JSP视图替换为前后端分离架构。使用Vue.js或React构建前端后端Servlet提供RESTful API使用Jackson处理JSON。这更符合现代开发趋势。升级后端框架将原生Servlet替换为Spring Boot。你会体会到依赖注入、声明式事务管理、自动化配置带来的巨大便利。这是你从“会写代码”到“懂框架”的关键一步。完善权限控制实现基于角色RBAC的权限管理。使用过滤器Filter或拦截器对请求进行拦截检查用户会话和权限。加入分页功能商品列表、销售记录等数据量大的查询必须支持分页。在SQL中使用LIMIT并在前端传递页码和大小参数。数据验证在前端JavaScript和后端Java Bean Validation同时对用户输入进行验证防止非法数据入库。日志记录使用配置好的Logback在关键业务节点如登录、销售、库存变动记录操作日志便于问题追踪和审计。代码优化使用连接池我们已经用了Druid要理解其原理。DAO层模板化使用JdbcTemplate或MyBatis消除重复的JDBC代码。服务层事务管理使用Spring的Transactional注解代替手动事务控制。部署上线学习如何将项目打包成WAR文件部署到云服务器如阿里云ECS的Tomcat上并配置域名和Nginx反向代理。这个超市管理系统项目就像一副完整的骨架。你现在完成的是让它“站起来能走路”。而上述的优化建议则是为它注入血肉和灵魂让它能“跑起来干重活”。从环境搭建到数据库设计从CRUD到事务处理你走过的每一步都是未来构建更复杂系统的基石。建议你将此项目作为你的个人作品不断迭代和完善在GitHub上维护一个清晰的代码仓库这本身就是一份极具说服力的“能力证明”。
Java Web超市管理系统实战:从零搭建MVC架构与事务处理
如果你是一名Java初学者或者正在为期末项目、课程设计、毕业设计寻找一个“麻雀虽小五脏俱全”的实战项目那么这篇文章就是为你准备的。超市管理系统这个听起来有些“经典”甚至“老套”的题目恰恰是检验你Java Web技术栈掌握程度的绝佳试金石。很多人以为它只是简单的增删改查CRUD但一个真正能跑通、能演示、能写在简历里的项目背后隐藏着从环境搭建、数据库设计、前后端交互到部署上线的完整工程化思维。本文将带你从零开始手把手实现一个功能完整的超市管理系统。我们不止于“半小时搞定”的噱头而是要深入剖析每个环节为什么选择这些技术数据库表如何设计才合理前后端数据如何流转遇到坑怎么快速排查最终你将获得一个包含商品管理、员工管理、供应商管理、销售统计等核心模块且代码结构清晰、易于扩展的项目。文末会提供完整的源码获取方式。1. 为什么超市管理系统是Java Web入门的黄金项目在开始敲代码之前我们先要搞清楚这个项目的价值。它绝不是一个过时的练习题而是凝聚了企业级应用开发核心思想的微型样板。第一技术栈全面且经典。一个标准的超市管理系统几乎覆盖了Java Web开发的所有基础环节后端Servlet/JSP或Spring MVC、JDBC或MyBatis、JavaBean。前端JSP、HTML、CSS、JavaScript、AJAX。数据库MySQL或Oracle。服务器Tomcat。工程管理Maven。通过这个项目你能将散落的知识点如Servlet生命周期、MVC模式、SQL编写、事务处理串联成一个有机整体。第二业务逻辑贴近现实易于理解。“进货-库存-销售”的流程非常直观这让你能更专注于技术实现而不是纠结于复杂的业务规则。你可以清晰地看到一条数据如一件商品是如何在系统中被创建、查询、修改、关联如与销售记录关联并最终被删除或归档的。第三具备足够的扩展性和深度。基础版本完成后你可以以此为起点进行无限深化加深技术深度将JDBC替换为MyBatis或JPA将原生Servlet/JSP升级为Spring Boot引入Redis缓存商品信息使用ECharts实现更酷炫的数据报表。扩展业务功能增加会员积分系统、促销活动模块、多仓库库存管理、移动端扫码入库等。对于面试官而言一个你能从头到尾讲清楚设计思路、技术选型和难点攻克的项目远比罗列一堆技术名词更有说服力。接下来我们就进入实战环节。2. 项目核心功能与系统设计我们的超市管理系统将包含以下核心功能模块这也是一个管理系统最典型的组成部分用户管理系统登录、注销、权限控制如管理员与普通收银员。商品管理商品的增、删、改、查以及分类管理。供应商管理维护商品供应商信息。库存管理记录商品入库采购、出库销售流水动态计算库存。销售管理模拟收银台功能生成销售单据。统计报表按日、月统计销售额、毛利分析畅销商品。系统架构设计MVC模式这是本项目的灵魂。我们将采用经典的JSP Servlet JavaBean模式这也是理解更高级框架如Spring MVC的基础。Model模型JavaBean/DAO对应数据库中的实体如Product,User和访问这些实体的类ProductDao,UserDao。负责业务数据和业务逻辑。View视图JSP用户看到的界面如商品列表页product_list.jsp、登录页login.jsp。负责展示数据。Controller控制器Servlet如ProductServlet、LoginServlet。接收用户请求来自View调用Model处理并将结果返回给View。这种分离使得代码结构清晰易于维护和测试。3. 开发环境与工具准备工欲善其事必先利其器。请确保你的电脑上已安装以下环境JDK版本 8 或 11推荐8兼容性最好。安装后配置JAVA_HOME环境变量。IDEIntelliJ IDEA终极版或社区版或 Eclipse。本文演示以IDEA为主。Web服务器Apache Tomcat 9.x。下载后解压即可。数据库MySQL 5.7 或 8.0。推荐使用图形化工具如Navicat或MySQL Workbench辅助操作。项目管理Maven 3.6。IDEA通常内置。在IDEA中配置Tomcat打开Run/Debug Configurations。点击选择Tomcat Server - Local。在Application server处点击Configure...选择你的Tomcat解压目录。在Deployment标签页点击选择Artifact添加你的Web项目。环境配置是第一个“拦路虎”如果遇到ClassNotFoundException或404错误十有八九是环境或部署问题。请务必先确保一个简单的Hello WorldJSP页面能在Tomcat上正常运行。4. 数据库设计与建表数据库设计是项目的基石。一个糟糕的表结构会让后续编码举步维艰。我们遵循第三范式进行基础设计核心表如下user用户表CREATE TABLE user ( id int(11) NOT NULL AUTO_INCREMENT COMMENT 用户ID, username varchar(50) NOT NULL COMMENT 用户名, password varchar(100) NOT NULL COMMENT 密码建议MD5加密存储, real_name varchar(50) DEFAULT NULL COMMENT 真实姓名, role varchar(20) NOT NULL DEFAULT cashier COMMENT 角色admin管理员, cashier收银员, create_time datetime DEFAULT CURRENT_TIMESTAMP COMMENT 创建时间, PRIMARY KEY (id), UNIQUE KEY uni_username (username) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT系统用户表;product商品表CREATE TABLE product ( id int(11) NOT NULL AUTO_INCREMENT COMMENT 商品ID, product_no varchar(50) NOT NULL COMMENT 商品编号唯一, name varchar(100) NOT NULL COMMENT 商品名称, category varchar(50) DEFAULT NULL COMMENT 分类, purchase_price decimal(10,2) NOT NULL COMMENT 进货价, sale_price decimal(10,2) NOT NULL COMMENT 零售价, stock int(11) NOT NULL DEFAULT 0 COMMENT 当前库存, supplier_id int(11) DEFAULT NULL COMMENT 供应商ID, create_time datetime DEFAULT CURRENT_TIMESTAMP COMMENT 创建时间, update_time datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 更新时间, PRIMARY KEY (id), UNIQUE KEY uni_product_no (product_no), KEY idx_supplier (supplier_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT商品信息表;supplier供应商表CREATE TABLE supplier ( id int(11) NOT NULL AUTO_INCREMENT, name varchar(100) NOT NULL COMMENT 供应商名称, contact varchar(50) DEFAULT NULL COMMENT 联系人, phone varchar(20) DEFAULT NULL COMMENT 电话, address varchar(200) DEFAULT NULL COMMENT 地址, PRIMARY KEY (id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT供应商表;stock_log库存流水表这是实现库存准确性的关键。CREATE TABLE stock_log ( id int(11) NOT NULL AUTO_INCREMENT, product_id int(11) NOT NULL COMMENT 商品ID, type varchar(20) NOT NULL COMMENT 类型purchase采购入库, sale销售出库, adjust库存调整, quantity int(11) NOT NULL COMMENT 变动数量正数为入库负数为出库, operator_id int(11) DEFAULT NULL COMMENT 操作员ID, remark varchar(200) DEFAULT NULL COMMENT 备注, create_time datetime DEFAULT CURRENT_TIMESTAMP COMMENT 创建时间, PRIMARY KEY (id), KEY idx_product (product_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT库存流水表;sale_order与sale_item销售订单与订单明细表这是一对多的关系是处理销售业务的标准设计。-- 销售订单主表 CREATE TABLE sale_order ( order_no varchar(50) NOT NULL COMMENT 订单号可生成唯一编号, total_amount decimal(10,2) NOT NULL COMMENT 订单总金额, cashier_id int(11) NOT NULL COMMENT 收银员ID, create_time datetime DEFAULT CURRENT_TIMESTAMP COMMENT 下单时间, PRIMARY KEY (order_no) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT销售订单表; -- 销售订单明细表 CREATE TABLE sale_item ( id int(11) NOT NULL AUTO_INCREMENT, order_no varchar(50) NOT NULL COMMENT 关联订单号, product_id int(11) NOT NULL COMMENT 商品ID, quantity int(11) NOT NULL COMMENT 销售数量, sale_price decimal(10,2) NOT NULL COMMENT 成交单价, subtotal decimal(10,2) NOT NULL COMMENT 小计金额, PRIMARY KEY (id), KEY idx_order (order_no), KEY idx_product (product_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT销售订单明细表;设计要点唯一约束如user.username,product.product_no防止数据重复。索引在经常查询的字段上建立索引如product.supplier_id,stock_log.product_id。数据类型金额使用DECIMAL避免浮点数精度问题。时间戳使用CURRENT_TIMESTAMP自动记录创建和更新时间。外键关系虽然上述SQL未显式声明外键考虑到性能和灵活性但在逻辑上必须维护product.supplier_id与supplier.id等关系的正确性。5. 项目骨架搭建与Maven配置我们使用Maven来管理项目依赖和构建。在IDEA中创建新项目选择Maven并勾选Create from archetype选择maven-archetype-webapp。关键的pom.xml依赖配置project xmlnshttp://maven.apache.org/POM/4.0.0 xmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd modelVersion4.0.0/modelVersion groupIdcom.supermarket/groupId artifactIdsupermarket-management/artifactId version1.0-SNAPSHOT/version packagingwar/packaging properties project.build.sourceEncodingUTF-8/project.build.sourceEncoding maven.compiler.source1.8/maven.compiler.source maven.compiler.target1.8/maven.compiler.target /properties dependencies !-- Servlet JSP API -- dependency groupIdjavax.servlet/groupId artifactIdjavax.servlet-api/artifactId version4.0.1/version scopeprovided/scope /dependency dependency groupIdjavax.servlet.jsp/groupId artifactIdjavax.servlet.jsp-api/artifactId version2.3.3/version scopeprovided/scope /dependency !-- JSTL 标签库用于在JSP中简化逻辑 -- dependency groupIdjavax.servlet/groupId artifactIdjstl/artifactId version1.2/version /dependency !-- MySQL 驱动 -- dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId version8.0.33/version /dependency !-- 数据库连接池Druid性能好监控功能强大 -- dependency groupIdcom.alibaba/groupId artifactIddruid/artifactId version1.2.20/version /dependency !-- 日志框架SLF4J Logback -- dependency groupIdorg.slf4j/groupId artifactIdslf4j-api/artifactId version1.7.36/version /dependency dependency groupIdch.qos.logback/groupId artifactIdlogback-classic/artifactId version1.2.12/version /dependency !-- JSON处理Gson -- dependency groupIdcom.google.code.gson/groupId artifactIdgson/artifactId version2.10.1/version /dependency /dependencies build finalNamesupermarket/finalName plugins !-- 编译插件 -- plugin groupIdorg.apache.maven.plugins/groupId artifactIdmaven-compiler-plugin/artifactId version3.11.0/version configuration source1.8/source target1.8/target /configuration /plugin /plugins /build /project项目目录结构创建标准的Maven Web项目结构src/main/java └── com.supermarket ├── controller (Servlet控制器) ├── service (业务逻辑层) ├── dao (数据访问层接口和实现) ├── model (JavaBean实体类) └── util (工具类如数据库连接、字符串处理) src/main/resources └── db.properties (数据库配置文件) src/main/webapp ├── WEB-INF │ ├── web.xml (部署描述符) │ └── lib (依赖jar包Maven管理则无需手动放) ├── css ├── js ├── images └── *.jsp (视图页面)6. 核心代码实现从数据库连接到业务逻辑我们以商品管理模块为例贯穿MVC三层展示核心代码。第一步模型层Model - 实体类与数据库连接src/main/java/com/supermarket/model/Product.java:package com.supermarket.model; import java.math.BigDecimal; import java.util.Date; public class Product { private Integer id; private String productNo; private String name; private String category; private BigDecimal purchasePrice; // 使用BigDecimal处理金额 private BigDecimal salePrice; private Integer stock; private Integer supplierId; private Date createTime; private Date updateTime; // 省略getter和setter方法以及toString方法 }src/main/java/com/supermarket/util/DBUtil.java(数据库连接工具类):package com.supermarket.util; import com.alibaba.druid.pool.DruidDataSource; import javax.sql.DataSource; import java.io.InputStream; import java.sql.Connection; import java.sql.SQLException; import java.util.Properties; public class DBUtil { private static DataSource dataSource; static { try { Properties props new Properties(); InputStream is DBUtil.class.getClassLoader().getResourceAsStream(db.properties); props.load(is); DruidDataSource druidDataSource new DruidDataSource(); druidDataSource.setDriverClassName(props.getProperty(jdbc.driver)); druidDataSource.setUrl(props.getProperty(jdbc.url)); druidDataSource.setUsername(props.getProperty(jdbc.username)); druidDataSource.setPassword(props.getProperty(jdbc.password)); // 其他连接池配置... dataSource druidDataSource; } catch (Exception e) { throw new RuntimeException(初始化数据库连接池失败, e); } } public static Connection getConnection() throws SQLException { return dataSource.getConnection(); } public static void close(Connection conn) { if (conn ! null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } }src/main/resources/db.properties:jdbc.drivercom.mysql.cj.jdbc.Driver jdbc.urljdbc:mysql://localhost:3306/supermarket_db?useUnicodetruecharacterEncodingUTF-8serverTimezoneAsia/Shanghai jdbc.usernameroot jdbc.passwordyour_password第二步数据访问层DAOsrc/main/java/com/supermarket/dao/ProductDao.java(接口):package com.supermarket.dao; import com.supermarket.model.Product; import java.util.List; public interface ProductDao { int addProduct(Product product); int deleteProductById(int id); int updateProduct(Product product); Product getProductById(int id); ListProduct getAllProducts(); ListProduct getProductsByName(String name); }src/main/java/com/supermarket/dao/impl/ProductDaoImpl.java(实现类):package com.supermarket.dao.impl; import com.supermarket.dao.ProductDao; import com.supermarket.model.Product; import com.supermarket.util.DBUtil; import java.sql.*; import java.util.ArrayList; import java.util.List; public class ProductDaoImpl implements ProductDao { Override public int addProduct(Product product) { Connection conn null; PreparedStatement pstmt null; String sql INSERT INTO product(product_no, name, category, purchase_price, sale_price, stock, supplier_id) VALUES(?,?,?,?,?,?,?); try { conn DBUtil.getConnection(); pstmt conn.prepareStatement(sql); pstmt.setString(1, product.getProductNo()); pstmt.setString(2, product.getName()); pstmt.setString(3, product.getCategory()); pstmt.setBigDecimal(4, product.getPurchasePrice()); pstmt.setBigDecimal(5, product.getSalePrice()); pstmt.setInt(6, product.getStock()); pstmt.setInt(7, product.getSupplierId()); return pstmt.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); return 0; } finally { // 关闭资源实际项目应使用try-with-resources或工具方法 DBUtil.close(conn); } } // 省略其他方法delete, update, query的实现... }第三步业务逻辑层Servicesrc/main/java/com/supermarket/service/ProductService.java:package com.supermarket.service; import com.supermarket.model.Product; import java.util.List; public interface ProductService { boolean addProduct(Product product); boolean deleteProduct(int id); boolean updateProduct(Product product); Product getProductById(int id); ListProduct getAllProducts(); ListProduct searchProducts(String keyword); }src/main/java/com/supermarket/service/impl/ProductServiceImpl.java:package com.supermarket.service.impl; import com.supermarket.dao.ProductDao; import com.supermarket.dao.impl.ProductDaoImpl; import com.supermarket.model.Product; import com.supermarket.service.ProductService; import java.util.List; public class ProductServiceImpl implements ProductService { private ProductDao productDao new ProductDaoImpl(); Override public boolean addProduct(Product product) { // 这里可以添加业务逻辑例如检查商品编号是否重复 if (productDao.getProductByNo(product.getProductNo()) ! null) { return false; // 编号重复 } return productDao.addProduct(product) 0; } // 省略其他方法实现... }第四步控制层Controller - Servletsrc/main/java/com/supermarket/controller/ProductServlet.java:package com.supermarket.controller; import com.supermarket.model.Product; import com.supermarket.service.ProductService; import com.supermarket.service.impl.ProductServiceImpl; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.List; WebServlet(/product/*) // 使用路径映射 public class ProductServlet extends HttpServlet { private ProductService productService new ProductServiceImpl(); Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String pathInfo req.getPathInfo(); // 获取 /add, /delete, /list 等路径 if (/list.equals(pathInfo)) { ListProduct productList productService.getAllProducts(); req.setAttribute(productList, productList); req.getRequestDispatcher(/WEB-INF/jsp/product_list.jsp).forward(req, resp); } else if (/edit.equals(pathInfo)) { String id req.getParameter(id); Product product productService.getProductById(Integer.parseInt(id)); req.setAttribute(product, product); req.getRequestDispatcher(/WEB-INF/jsp/product_edit.jsp).forward(req, resp); } // 处理其他GET请求... } Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.setCharacterEncoding(UTF-8); // 处理中文乱码 String pathInfo req.getPathInfo(); if (/add.equals(pathInfo)) { Product product new Product(); product.setProductNo(req.getParameter(productNo)); product.setName(req.getParameter(name)); // ... 设置其他属性 boolean success productService.addProduct(product); if (success) { resp.sendRedirect(req.getContextPath() /product/list); // 重定向到列表页 } else { req.setAttribute(errorMsg, 添加商品失败可能编号重复); req.getRequestDispatcher(/WEB-INF/jsp/product_add.jsp).forward(req, resp); } } // 处理其他POST请求更新、删除... } }第五步视图层View - JSPsrc/main/webapp/WEB-INF/jsp/product_list.jsp(商品列表页):% page contentTypetext/html;charsetUTF-8 languagejava % % taglib prefixc urihttp://java.sun.com/jsp/jstl/core % html head title商品管理/title link relstylesheet typetext/css href${pageContext.request.contextPath}/css/style.css /head body h1商品列表/h1 a href${pageContext.request.contextPath}/product/addPage新增商品/a table border1 cellspacing0 tr th编号/thth名称/thth分类/thth进货价/thth零售价/thth库存/thth操作/th /tr c:forEach items${productList} varproduct tr td${product.productNo}/td td${product.name}/td td${product.category}/td td${product.purchasePrice}/td td${product.salePrice}/td td${product.stock}/td td a href${pageContext.request.contextPath}/product/edit?id${product.id}编辑/a a hrefjavascript:if(confirm(确定删除吗)) location.href${pageContext.request.contextPath}/product/delete?id${product.id}删除/a /td /tr /c:forEach /table /body /html7. 核心业务销售与库存联动的实现这是项目的难点和亮点。销售商品时必须保证库存减少和生成销售记录这两个操作在一个数据库事务中完成否则会导致数据不一致比如卖了商品但库存没减。服务层实现销售逻辑 (SaleService):package com.supermarket.service.impl; import com.supermarket.dao.ProductDao; import com.supermarket.dao.SaleDao; import com.supermarket.dao.StockLogDao; import com.supermarket.model.SaleOrder; import com.supermarket.model.SaleItem; import com.supermarket.model.StockLog; import java.sql.Connection; import java.sql.SQLException; import java.util.List; public class SaleServiceImpl { private ProductDao productDao; private SaleDao saleDao; private StockLogDao stockLogDao; // 假设有一个获取数据库连接并管理事务的工具类 private Connection conn DBUtil.getConnection(); // 注意实际应用应从线程上下文获取连接 public boolean makeSale(SaleOrder order, ListSaleItem items) { // 关键开启事务手动控制 try { conn.setAutoCommit(false); // 关闭自动提交 // 1. 插入销售订单主表 saleDao.insertOrder(order); // 2. 循环插入销售明细并更新对应商品库存 for (SaleItem item : items) { saleDao.insertItem(item); // 更新商品库存减少 int affectedRows productDao.updateStock(item.getProductId(), -item.getQuantity()); if (affectedRows 0) { throw new RuntimeException(商品库存不足或不存在商品ID: item.getProductId()); } // 3. 记录库存流水出库 StockLog log new StockLog(); log.setProductId(item.getProductId()); log.setType(sale); log.setQuantity(-item.getQuantity()); // 出库为负数 log.setRemark(销售出库订单号 order.getOrderNo()); stockLogDao.insert(log); } // 所有操作成功提交事务 conn.commit(); return true; } catch (Exception e) { // 任何一步出错回滚事务 try { conn.rollback(); } catch (SQLException ex) { ex.printStackTrace(); } e.printStackTrace(); return false; } finally { try { conn.setAutoCommit(true); // 恢复自动提交模式 conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } }关键点setAutoCommit(false)、commit()、rollback()。这确保了“扣库存”和“记销售”要么同时成功要么同时失败数据永远一致。8. 项目运行、部署与测试数据库初始化运行前面提供的SQL脚本创建数据库和表。可以插入一些测试数据。配置数据库连接修改db.properties中的用户名和密码。IDEA中配置Tomcat并启动将项目添加到Tomcat服务器点击运行。访问应用浏览器打开http://localhost:8080/supermarket/login.jsp(假设你的应用上下文路径是/supermarket)。功能测试登录测试使用预先插入的用户如admin/123456登录。商品管理测试尝试添加、查询、修改、删除商品。销售测试在销售界面选择商品、输入数量完成销售。检查库存是否准确减少销售订单和流水是否生成。报表测试查看销售统计报表。9. 常见问题与排查指南QA在开发过程中你几乎一定会遇到以下问题问题现象可能原因排查方式解决方案访问JSP页面报404错误1. 项目未成功部署到Tomcat。2. URL路径错误。3.web.xml配置错误或Servlet注解未生效。1. 检查IDEA中Tomcat的Deployment选项卡确保项目Artifact已添加。2. 检查浏览器地址栏URL是否与应用上下文路径匹配。3. 检查WebServlet注解路径或web.xml中的url-pattern。1. 重新部署项目。2. 使用${pageContext.request.contextPath}获取正确路径。3. 清理Tomcat工作目录并重启。页面中文乱码1. JSP页面编码未设置。2. Servlet未设置请求/响应编码。3. 数据库连接字符集不对。1. 检查JSP文件头% page pageEncodingUTF-8%。2. 在Servlet的doPost方法开始处调用request.setCharacterEncoding(UTF-8)和response.setContentType(text/html;charsetUTF-8)。3. 检查MySQL连接URL是否包含characterEncodingUTF-8。统一所有环节的编码为UTF-8。数据库连接失败1. MySQL服务未启动。2.db.properties配置错误密码、端口、数据库名。3. 驱动版本与MySQL版本不匹配。1. 检查MySQL服务状态。2. 使用Navicat等工具测试连接信息。3. 查看Tomcat日志中的具体SQLException信息。1. 启动MySQL服务。2. 核对配置文件。3. 更换合适的JDBC驱动版本如MySQL 8.0使用com.mysql.cj.jdbc.Driver。插入数据失败但无报错1. 事务未提交。2. 程序捕获了异常但未打印或处理。1. 检查DAO层操作后是否调用了connection.commit()如果关闭了自动提交。2. 在catch块中打印e.printStackTrace()。1. 确保事务正确提交。2. 完善异常处理将日志输出到控制台或文件。页面显示“No suitable driver found”JDBC驱动未加载。检查项目的WEB-INF/lib目录下是否有mysql-connector-java-xxx.jar或Maven依赖是否下载成功。确保依赖正确。Maven项目可以执行mvn clean compile检查。10. 项目优化与扩展建议最佳实践完成基础版本后你可以从以下方向深化项目这会让你的项目在面试中脱颖而出引入前端框架将JSP视图替换为前后端分离架构。使用Vue.js或React构建前端后端Servlet提供RESTful API使用Jackson处理JSON。这更符合现代开发趋势。升级后端框架将原生Servlet替换为Spring Boot。你会体会到依赖注入、声明式事务管理、自动化配置带来的巨大便利。这是你从“会写代码”到“懂框架”的关键一步。完善权限控制实现基于角色RBAC的权限管理。使用过滤器Filter或拦截器对请求进行拦截检查用户会话和权限。加入分页功能商品列表、销售记录等数据量大的查询必须支持分页。在SQL中使用LIMIT并在前端传递页码和大小参数。数据验证在前端JavaScript和后端Java Bean Validation同时对用户输入进行验证防止非法数据入库。日志记录使用配置好的Logback在关键业务节点如登录、销售、库存变动记录操作日志便于问题追踪和审计。代码优化使用连接池我们已经用了Druid要理解其原理。DAO层模板化使用JdbcTemplate或MyBatis消除重复的JDBC代码。服务层事务管理使用Spring的Transactional注解代替手动事务控制。部署上线学习如何将项目打包成WAR文件部署到云服务器如阿里云ECS的Tomcat上并配置域名和Nginx反向代理。这个超市管理系统项目就像一副完整的骨架。你现在完成的是让它“站起来能走路”。而上述的优化建议则是为它注入血肉和灵魂让它能“跑起来干重活”。从环境搭建到数据库设计从CRUD到事务处理你走过的每一步都是未来构建更复杂系统的基石。建议你将此项目作为你的个人作品不断迭代和完善在GitHub上维护一个清晰的代码仓库这本身就是一份极具说服力的“能力证明”。