ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

SSM超市管理系统源码部署与二次开发实战指南

SSM超市管理系统源码部署与二次开发实战指南 简介一套基于SSM框架的超市管理系统完整源码适合Java Web初学者在真实业务场景中学习企业级分层开发思路也适合开发者作为课程设计或毕业设计的基础项目。压缩包内共有一千二百二十二个文件整体约十九兆大小包含大量Java源文件、JSP页面、HTML页面、CSS样式、JavaScript脚本、XML配置以及SQL数据库脚本前后端代码与数据库初始化语句齐全可直接导入开发工具运行调试便于快速搭建并启动项目。系统围绕超市日常运营实现了商品管理、库存监控、订单处理、客户维护和收银结算等功能模块清晰体现控制层、服务层与持久层之间的协作关系持久层采用映射配置完成数据库操作控制层负责请求转发与响应整体结构完整且易于扩展。通过阅读源码可理解SSM框架整合方式、项目目录结构、依赖配置以及典型业务逻辑写法也能掌握数据库脚本执行流程是课程设计或框架实战的实用参考材料。目前已有二百三十六人浏览学习。1. SSM 超市管理系统源码先看懂包里有什么再动手解压带「ssm项目源码」字样的压缩包里面通常是一套 Spring SpringMVC MyBatis 整合的 Java Web 工程外加一个 .sql 结尾的 MySQL 数据库脚本。超市管理系统对应商品、库存、销售、会员这类进销存业务本质是几张业务表配上增删改查页面。不少人拿到项目先启动 Tomcat却报 Table doesnt exist 或 404。原因很统一脚本没导入或 datasource 的库名、密码与本地 MySQL 对不上。能不能跑起来取决于 .sql 有没有正确落库。下面按动手顺序拆先导数据库脚本再对准 ssm 三层配置接着 IDEA Tomcat 部署排错最后给一套扩表改模块的方法适合毕业设计和接手老工程的人。2. 导入 mysql 数据库脚本把超市系统的表和演示数据落库压缩包里那个 .sql 文件是整套系统最容易忽略、也最影响成败的部分。它一般承担三件事建库、建表、灌演示数据。SSM 项目没有自动建表能力MyBatis 只负责读写不会帮你 CREATE TABLE所以脚本没导入后面所有查询都会报 Table supermarket.tb_product doesnt exist。先搞清楚脚本内容再决定导入方式。2.1 打开脚本先看三样东西用普通文本编辑器打开 .sql不要一上来就双击执行。重点看三样内容开头有没有 CREATE DATABASE 和 USE 语句有的话不用手动建库没有则需要自己先建库再导入建表语句的 ENGINE 和 CHARSET老项目常见 MyISAM 配 latin1中文乱码大多是从这一步埋下的INSERT 语句的规模决定导入时要等多久。另外留意脚本里有没有 CREATE PROCEDURE如果含存储过程导入账号还需要有 CREATE ROUTINE 权限。一段典型脚本的开头长这样-- 脚本头部的常见写法先建库再切库 CREATE DATABASE IF NOT EXISTS supermarket DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; USE supermarket; SET NAMES utf8mb4; DROP TABLE IF EXISTS tb_product; CREATE TABLE tb_product ( id INT PRIMARY KEY AUTO_INCREMENT COMMENT 商品ID, product_name VARCHAR(64) NOT NULL COMMENT 商品名称, category_id INT COMMENT 分类ID, sale_price DECIMAL(10, 2) DEFAULT 0 COMMENT 售价, stock INT DEFAULT 0 COMMENT 当前库存, status TINYINT DEFAULT 1 COMMENT 1上架 0下架 ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT商品表;这里 IF NOT EXISTS 表示脚本可以重复执行失败重导时不用先把旧库删掉SET NAMES 指定当前客户端连接的传输编码不写它中文容易在传输过程中变乱码AUTO_INCREMENT 主键是新增页面回填主键的依赖缺了它 MyBatis 的 useGeneratedKeys 拿不到自增 ID。如果脚本里是 MyISAM 或者 CHARSETutf8建议导入后手动改成 InnoDB 和 utf8mb4否则后续多张表并发写时容易出现锁问题。2.2 命令行导入的两种标准姿势本机已装 MySQL 的前提下我一般用命令行导入比图形工具更可控。先建库再导入mysql -uroot -p -e CREATE DATABASE IF NOT EXISTS supermarket DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; mysql -uroot -p supermarket supermarket.sql已经进了 mysql 客户端时用 source 效果一样mysql -uroot -p mysql SET NAMES utf8mb4; mysql SOURCE D:/work/supermarket.sql;参数说明-u 指定用户名-p 让客户端交互式提示输入密码-e 表示执行后面的 SQL 后立刻退出是 shell 重定向把文件内容按字节喂给 mysql 客户端。source 是 mysql 客户端内部命令路径里的分隔符要用正斜杠Windows 下写成 D:/ 而不是 D:\反斜杠会被当成转义字符。导入时如果看到 ERROR 1064 语法错误通常是脚本里的注释或写法与当前 MySQL 版本不兼容定位到报错行号附近看是不是用了 MySQL 8.0 才支持的语法。如果脚本开头没有 CREATE DATABASE建库时库名必须和后面 jdbc.properties 里写的保持一致这是新手翻车最高发的位置。提示脚本里如果有 CREATE DATABASE 但你想用另一个库名导入前先做一次全局替换否则表会落到脚本指定的库里。2.3 导入后必须做的三个验证导入成功不表示万事大吉我用三个查询确认结果USE supermarket; SHOW TABLES; -- 看表数量是否和脚本里的建表语句对得上 SELECT COUNT(*) FROM tb_product; -- 抽一张业务表确认演示数据导入了 DESC tb_product; -- 确认字段、类型、默认值和注释都在SHOW TABLES 检查脚本有没有完整执行如果中途某条 SQL 报错后续语句可能全部没跑SELECT COUNT(*) 验证 INSERT 批量插入有没有丢失数据DESC 看字段属性这一步能提前发现「脚本里 stock 默认值没写页面新增后库存是 null」这类问题。如果发现少表少数据直接重新执行一次脚本前提是脚本里有 DROP TABLE IF EXISTS否则重复建表会报 already exists。超市管理系统的表再多业务上也逃不出下面这几类常见表名职责对应的业务模块tb_product商品主表商品管理、库存查询tb_category商品分类分类树、下拉框tb_supplier供应商进货管理tb_stock_record出入库流水库存变动记录tb_sale_order销售单主表收银、订单tb_sale_order_item销售单明细销售明细、报表tb_user后台账号登录与权限tb_member会员资料会员管理这张对应关系表的作用是让你拿到 .sql 后能快速把数据库和业务页面连起来。后面改需求时改哪张表、动哪段 SQL都从这张表出发。2.4 本机没有 MySQL 的两条路安装版与 Docker 版没有 MySQL 环境时常见做法是装 MySQL 8.0 以上版本安装时字符集选 utf8mb4。这里不展开 mysql 安装配置教程只提醒两个点安装时设置的 root 密码要记牢后面 jdbc.properties 里要写同一个如果用 MySQL 8.0驱动类名要写成 com.mysql.cj.jdbc.Driver。另一条路是 Docker适合不想污染本机环境的场景docker run -d --name supermarket-mysql \ -p 3306:3306 \ -e MYSQL_ROOT_PASSWORD123456 \ -e MYSQL_DATABASEsupermarket \ mysql:8.0 docker exec -i supermarket-mysql mysql -uroot -p123456 supermarket supermarket.sql参数说明-e MYSQL_DATABASE 会在容器首次启动时自动建库省掉手动建库一步-p 3306:3306 把容器 3306 映射到宿主机本地 jdbc.url 直接连 localhost:3306 即可docker exec -i 配合重定向在容器内执行导入。容器默认字符集可能是 latin1导入前最好先 exec 进去执行 SET NAMES utf8mb4。用 Navicat for MySQL 或 MySQL Workbench 导入也可以但图形工具的「运行 SQL 文件」有时会忽略 USE 语句库选错是高频翻车点命令行方式更不容易出偏差。3. 对准 ssm 三层配置Spring、SpringMVC、MyBatis 的职责边界数据落库后下一个动作不是急着写代码而是确认工程里的配置文件能和本地环境对上。SSM 没有 Spring Boot 的自动装配每个 bean 都要显式声明一个路径写错启动时要么报 ClassNotFoundException要么报 Invalid bound statement。先分清三个框架的职责Spring 管对象创建和事务SpringMVC 管请求分发和视图MyBatis 管 SQL 执行。3.1 项目目录结构与三层代码的对应关系这类 ssm 工程的标准目录结构遵循 Maven 约定的 src/main 布局src/main/java/com/supermarket/ controller/ 商品、订单、用户的控制器 service/ 业务接口和实现 mapper/ MyBatis 数据访问接口 entity/ 对应数据库表的 JavaBean src/main/resources/ applicationContext.xml Spring 根容器 spring-mvc.xml SpringMVC 子容器 jdbc.properties 数据库连接参数 mapper/ MyBatis 映射文件 src/main/webapp/ WEB-INF/web.xml Servlet 入口配置 WEB-INF/jsp/ 登录、商品列表等页面理解这个结构的意义在于SSM 是父子容器applicationContext.xml 管 service、mapper 和事务spring-mvc.xml 只管 controller 和视图解析。如果两个文件把扫描包写重了事务代理容易被覆盖最常见的症状是「查询正常新增或删除静默不生效」。配置文件和职责的对应关系可以收成一张表配置文件容器角色关键声明改环境时动哪里web.xml入口DispatcherServlet、ContextLoaderListener、编码过滤器servlet 映射、contextConfigLocation 路径applicationContext.xml父容器数据源、SqlSessionFactory、事务、mapper 扫描properties 路径、实体包名spring-mvc.xml子容器controller 扫描、视图解析器、注解驱动扫描包名、jsp 前缀后缀jdbc.properties参数驱动、url、账号、密码库名、密码、时区参数mapper/*.xml数据层SQL、参数类型、返回类型表名、列名、resultType3.2 jdbc.properties 是第一个要改的文件拿到项目先打开 jdbc.properties不用管其他配置改了它才能连上刚才建的库jdbc.drivercom.mysql.cj.jdbc.Driver jdbc.urljdbc:mysql://localhost:3306/supermarket?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/ShanghaiuseSSLfalse jdbc.usernameroot jdbc.password123456参数说明com.mysql.cj.jdbc.Driver 是 MySQL 8.0 的驱动类名老工程里写的 com.mysql.jdbc.Driver 在 8.0 下也能跑但控制台会打印过时警告URL 里的 supermarket 要和第二章导入脚本时用的库名完全一致serverTimezone 必须显式指定否则 MySQL 8.0 驱动拿不到系统时区会直接抛异常useSSLfalse 关掉 SSL 握手告警本地开发没必要开。密码含特殊字符时要小心像 或 # 在 properties 里会被截断或当成注释建议用纯字母数字密码或者在密码外面不写引号直接替换成转义写法。3.3 applicationContext.xml 里四个必须对齐的配置Spring 根容器里和数据层相关的核心是四段声明context:property-placeholder locationclasspath:jdbc.properties/ bean iddataSource classorg.apache.commons.dbcp2.BasicDataSource destroy-methodclose property namedriverClassName value${jdbc.driver}/ property nameurl value${jdbc.url}/ property nameusername value${jdbc.username}/ property namepassword value${jdbc.password}/ /bean bean idsqlSessionFactory classorg.mybatis.spring.SqlSessionFactoryBean property namedataSource refdataSource/ property namemapperLocations valueclasspath:mapper/*.xml/ property nametypeAliasesPackage valuecom.supermarket.entity/ /bean bean classorg.mybatis.spring.mapper.MapperScannerConfigurer property namebasePackage valuecom.supermarket.mapper/ /bean逐个说明property-placeholder 负责把 jdbc.properties 的占位符替换成真实值location 写错会直接抛 Could not resolve placeholderdataSource 用 dbcp2 连接池如果 pom 里引的是 druid把 class 换成 com.alibaba.druid.pool.DruidDataSource 即可行为基本等价只是 Druid 额外带监控页sqlSessionFactory 是 MyBatis 和 Spring 的桥mapperLocations 指定映射文件位置路径写错时启动不报错但一调用 mapper 方法就抛 Invalid bound statementtypeAliasesPackage 让 XML 里可以直接写 Product 而不是全限定名MapperScannerConfigurer 把 mapper 接口注册成 beanbasePackage 没写对controller 里 Autowired 注入会直接报找不到类型。3.4 spring-mvc.xml 和 web.xml 的分工SpringMVC 子容器通常长这样context:component-scan base-packagecom.supermarket.controller/ mvc:annotation-driven/ bean classorg.springframework.web.servlet.view.InternalResourceViewResolver property nameprefix value/WEB-INF/jsp// property namesuffix value.jsp/ /bean mvc:default-servlet-handler/component-scan 只扫 controller 包别把 service 包加进来否则父子容器重复实例化事务代理容易失效annotation-driven 开启 RequestMapping 解析漏掉它所有请求都会 404视图解析器的 prefix 和 suffix 决定 Controller 里 return product/list 会去找 /WEB-INF/jsp/product/list.jsp这个路径必须和实际放 JSP 的位置一致否则报找不到视图。web.xml 里与这两个配置文件对应的注册关系是DispatcherServlet 的 init-param contextConfigLocation 指向 spring-mvc.xmlContextLoaderListener 的 context-param 指向 applicationContext.xml。装反的现象很有意思——启动不报错但所有 controller 请求全部 404因为 SpringMVC 容器里没有控制器。web.xml 里还要确认有没有 CharacterEncodingFilter没有的话 POST 提交的中文大概率乱码filter filter-nameencoding/filter-name filter-classorg.springframework.web.filter.CharacterEncodingFilter/filter-class init-param param-nameencoding/param-name param-valueUTF-8/param-value /init-param /filter filter-mapping filter-nameencoding/filter-name url-pattern/*/url-pattern /filter-mapping3.5 MyBatis 映射文件里别乱改表名最后一个配置点是 mapper 目录下的 XML。超市系统里查询商品列表的典型写法select idselectProductList parameterTypemap resultTypeProduct SELECT id, product_name, sale_price, stock, status FROM tb_product where if testkeyword ! null and keyword ! AND product_name LIKE CONCAT(%, #{keyword}, %) /if /where ORDER BY id DESC /selectnamespace 必须是 mapper 接口的全限定名id 必须和接口方法名一致这两处对不上启动能过但调用即报错resultType 写 Product 是因为配了 typeAliasesPackage没配就写全限定名where加if是 MyBatis 动态 SQL 的经典组合keyword 为空时 WHERE 子句不会生成LIKE 拼接用 CONCAT 而不是 %${keyword}%前者走预编译防注入后者是字符串替换别用后者。改字段时记住一个原则查询列和 resultType 的实体属性一一对应实体里没有的属性页面取不到值。如果列表页在大数据量下变慢检查 tb_product 上有没有对 product_name 这类用于查询的列建普通索引脚本里没有就手动补 ALTER TABLE tb_product ADD INDEX idx_name(product_name)。4. IDEA Tomcat 部署把 ssm 工程跑起来并处理启动故障配置都对上后进入部署环节。老 ssm 项目的部署方式和 Spring Boot 完全不同没有内置 Tomcat也没有 java -jar要手动加一个 Tomcat Server并把工程打成一个 Artifact 部署进去。常见做法是 IDEA 里配 Tomcat Local部署方式选 war exploded。4.1 导入工程后先做三件前置检查用 IDEA 打开解压后的项目文件夹右上角提示 Unlinked Maven Project 时点导入。等待依赖拉取的同时检查三件事Project Structure 里 Project SDK 是否切到项目要求的 JDK 版本老项目多半是 1.8Maven 设置里是否配置了本地仓库依赖下载失败先来这一层找原因pom.xml 里 spring、mybatis-spring、druid 等版本之间有没有冲突。前置检查做完再启动能省掉一半排错时间。4.2 配置 Tomcat 和 Artifact 的完整路径菜单 Run → Edit Configurations → 左上角 → Tomcat Server → Local然后按四步走Server 标签页里 Application server 指向本机 Tomcat 解压目录Deployment 标签页点 选 Artifact类型选 工程名:war explodedApplication context 改成 /supermarket和首页跳转路径保持一致确认 HTTP port 没有和本机其他服务冲突war exploded 是展开目录方式开发时改 JSP 和静态资源不用重启刷新页面就能看到效果war 包方式适合最后打包交付不适合开发调试。Application context 不一致时浏览器访问 http://localhost:8080/ 会 404必须带上下文路径才能进登录页。如果系统里其他服务占用了 8080在这里改一个端口即可。注意启动报错时找报错信息里的 Caused by那才是根因上面一长串框架异常大多是它的表象。4.3 五种高频启动报错与处理把老 ssm 项目部署中最容易碰到的报错整理成一张对照表报错关键字根因处理方向Table doesnt exist数据库脚本没导入或库名不对回到第二章重新导入核对 jdbc.url 库名Invalid bound statementmapper XML 没被扫描或 namespace 不对检查 mapperLocations 和 XML 的 namespaceAccess denied for user密码错误或用户无权限改 jdbc.properties或用 root 重新授权Port 8080 was already in use端口被占用杀进程或改 Tomcat 端口Unable to compile class for JSPJDK 版本过高或缺少依赖切 JDK 8补 tomcat-embed-jasper新手最容易混的是前两项Table doesnt exist 是数据库层面的事报错信息里能看到具体表名Invalid bound statement 是 MyBatis 映射层面的事报错信息里能看到接口方法名。看到关键字再动手不要盲目重启十次。4.4 端口占用和日志定位的两个命令组合Tomcat 端口被占是最常见的启动失败原因两个命令解决# Windows netstat -ano | findstr :8080 taskkill /PID 进程号 /F # Linux / macOS lsof -i:8080 kill -9 进程号 # 看最新启动日志 tail -f /path/to/tomcat/logs/catalina.outnetstat -ano 列出所有端口占用findstr :8080 过滤出 8080 的行最后一列是 PID用 taskkill /PID 强杀lsof -i:8080 在 macOS 和 Linux 上都能用能看到占用进程名。启动报错时不要只看 IDEA 控制台前几行Tomcat 自己的日志在 logs/catalina.outCaused by 开头那段才是值得看的根因。4.5 Maven 依赖拉不下来的换源处理老项目依赖多中央仓库网络不稳定时Maven 面板里一片红色依赖。在 ~/.m2/settings.xml 里加阿里云镜像mirror idaliyunmaven/id mirrorOfcentral/mirrorOf urlhttps://maven.aliyun.com/repository/central/url /mirrormirrorOf 写 central 表示只替换中央仓库不影响自己配过的私有仓库换完源回到 IDEA 右侧 Maven 面板点刷新。如果某个 jar 依然红色去本地仓库 ~/.m2/repository 下找到对应目录整个删掉再刷新避免留下半截损坏的文件。老项目如果用的是 Druid 连接池还要确认 druid 版本和 MySQL 8 驱动兼容版本太旧会在 getConnection 时直接抛异常。5. 二次开发技巧按业务表扩字段、扩模块的落地路径源码跑通只是开始实际需求大多是改业务。超市管理系统最常见的改动一是给现成表加字段二是复制一个最小模块做新功能。SSM 老工程没有代码生成器改动必须按固定顺序走漏一层就静默失败。5.1 最小改动给商品表加低库存预警字段给商品加「预警库存」是典型需求。第一步改表USE supermarket; ALTER TABLE tb_product ADD COLUMN warn_stock INT DEFAULT 0 COMMENT 低库存预警值 AFTER stock;然后按「实体 → Mapper XML → Service → JSP」顺序同步四层entity/Product.java 加 warnStock 属性ProductMapper.xml 里 insert、update、select 语句补 warn_stock 列Service 和 Controller 通常透传实体不用改productForm.jsp 加输入框productList.jsp 显示预警值。这个顺序是唯一不容易漏的路径改错任何一层页面要么 500 要么拿到 null。5.2 列表页直接显示预警状态显示端直接在 JSP 用 EL 判断不需要动 Controllerc:if test${product.stock product.warnStock} span classlabel label-danger库存预警/span /c:if前提是对应 select 语句查出 warn_stock且实体有 getWarnStock()。漏掉任何一个标签要么不渲染要么直接抛异常。5.3 验证链路页面 → 日志 → 数据库改完重启按一条链路验证登录 → 商品管理 → 新增商品并填预警值 → 保存 → 列表页看标签 → 用 SQL 查落库SELECT id, product_name, stock, warn_stock FROM tb_product ORDER BY id DESC LIMIT 5;列表没显示时先走这条 SQL再按 F12 看页面返回的 HTML 里有没有 warnStock 值逐段定位是查询没带出字段还是页面没渲染。5.4 复制模块的替换要点要整块新功能比如供货商管理直接在源码里找一个最简单的模块分类管理通常是复制五份controller、service、mapper 接口、mapper XML、JSP然后全局替换类名和表名。最隐性的是 mapper XML 里 namespace 和 id这两个必须和新接口的方法对应上否则启动正常、点开即报错。替换完把新表字段逐一比对漏掉的列在 XML 里补实体里补属性。最终判断标准只有一个从登录后的列表页点进新增填数据保存数据库能查到这条记录这条模块链路就算通了。本文还有配套的精品资源点击获取
返回列表