☰
SSM+MySQL+JSP水果商城毕设:系统拆解与避坑指南
2026/10/1 12:00:09 网站建设 项目流程

简介:一整套基于SSM框架(Spring+SpringMVC+Mybatis)与MySQL、JSP技术构建的水果蔬菜商城系统毕业设计项目,面向计算机专业毕业生、课程设计学生以及需要快速上手JavaWeb商城开发的初学者。系统完整覆盖客户端的登录注册、个人中心、购物车管理、订单查询,以及管理端的订单管理、客户管理、商品管理、类目管理、公告管理、留言管理模块,前后台功能齐全、界面美观、操作逻辑清晰。压缩包共2000个文件,包含451张jpg商品素材、411张png界面元素、302个css样式、227个js脚本、130个xml配置、77个jar依赖库,同时附有java源码、class字节码、jsp页面与sql数据库脚本,资源包整体227.54MB,下载后导入IDEA即可运行。项目采用Tomcat8.0+JDK1.8+MySQL5.7以上环境开发,已通过导师指导,可直接作为高分毕业设计提交,也适合课程设计或期末大作业场景。目前已有129人学习下载,可帮助读者快速理解电商类JavaWeb项目的完整开发流程与代码结构。

1. 这套 SSM+MySQL+JSP 水果商城:不是花架子,是能直接交差的毕设底子

做毕设最怕什么?不是不会写代码,而是写完了导师一句「功能太单薄」给你打回重做。这套基于 SSM(Spring+SpringMVC+Mybatis)+MySQL+JSP 的水果蔬菜商城系统,我拆完之后的第一感觉是:它把「客户能下单、管理员能管单」这条完整闭环给你搭好了,而且没有堆砌那些用不上的花哨模块。客户侧有注册登录、个人中心、购物车、订单管理,管理侧有商品、类目、公告、留言、客户、订单六块管理,功能划分很清爽,正好卡在本科毕设「工作量够但不过界」的甜点上。

更关键的是它跑在 Tomcat8.0 + JDK1.8 这套经典组合上,数据库要求 MySQL 5.7 以上,开发工具是 IDEA。这三个版本号凑在一起,意味着你在网上搜到的绝大多数 SSM 踩坑教程都适用,不用为了兼容新特性去折腾那些莫名其妙的依赖冲突。这篇笔记不聊虚的,直接讲这套系统怎么拆、怎么跑、验收到什么程度算真跑通了,以及那些我实际碰到的、光看报错信息根本猜不到的坑。

2. 系统解剖:SSM 三层架构在水果商城里的真实落点

2.1 从 SpringMVC 的请求流转看前台购物流程

这套系统不是把代码堆在一个 Servlet 里硬凑出来的,而是标准的 SSM 分层。SpringMVC 负责接收请求和跳转页面,Spring 管业务对象和事务,Mybatis 管数据库读写。以「用户加购物车」这个操作举例,请求路径大致是:浏览器点「加入购物车」→ JSP 页面提交表单 → DispatcherServlet 根据映射找到 CartController → Controller 调 CartService 接口 → ServiceImpl 里调 CartMapper 的 insert 方法 → Mybatis 执行 SQL 写入购物车表。每一层各干各的活,这意味着你答辩的时候可以很清楚地讲出「请求是怎么穿层的」,导师最吃这套。

我拆代码的时候特意看了下包结构,典型的 com.xxx.controller、com.xxx.service、com.xxx.mapper 三层。实体类对应数据库表字段,Mapper 接口配 XML 文件写 SQL,Service 层做业务判断,比如下单时先查库存够不够、扣库存和生成订单是不是在同一个事务里。这些点都是答辩时的高频提问区,代码里都有对应实现,不是空壳。

2.2 数据库五张核心表的关系网

商城系统说到底玩的是数据关系。这套系统的表设计不复杂,但五脏俱全:用户表(customer)存账号密码和收货信息,商品表(goods)关联类目表(category),订单表(orders)关联用户和商品,公告表(notice)和留言表(comment)算是辅助功能。订单和商品之间是典型的多对多关系,通过订单详情表(order_detail)做中间关联,一个订单可以包含多个商品,一个商品也可以出现在多个订单里。

表结构这块建议你拿到项目后先用 Navicat 打开看一遍,重点看外键关系和字段注释。我遇到过不少同学答辩时被问「订单状态字段为什么用 int 不用 varchar」,这套系统里订单状态就是数字枚举,0 代表待发货、1 代表已发货之类的,答的时候能讲清楚这个设计意图,比临时编一个合理得多。数据库文件在项目里一般是 .sql 格式,直接用 Navicat 导入即可,不需要手动建表。

2.3 角色权限:客户和管理员的两套界面逻辑

系统分两个角色,前台给客户用,后台给管理员用。客户登录后看到的是商品列表、购物车、个人中心这些,管理员登录后跳转的是管理后台,能对商品、订单、类目、公告、留言做增删改查。两套界面的入口是同一个登录页,根据账号角色跳不同首页,这个逻辑在 LoginController 里用 if 判断实现。

这里有个实操细节:管理员账号和客户账号是存在同一张 user 表里,靠 role 字段区分,还是分表存储?这套系统用的是后者,客户和管理员分属不同表。你在改的时候要注意别把管理员的登录校验逻辑和客户的混在一起,否则会出现客户账号能登后台的严重越权问题。

3. 从零复现:环境搭建与导入项目的完整步骤

3.1 版本匹配是第一步,别让环境坑了你

这套系统最友好的地方在于技术栈都是「老熟人」。JDK 必须用 1.8,不是 11 也不是 17,因为很多 SSM 项目用了 com.sun 开头的内部包,高版本 JDK 直接编译报错。Tomcat 用 8.0 或 8.5 都行,MySQL 建议 5.7,如果你机器上装的是 MySQL 8.0 也能跑,但要处理认证插件和驱动版本的兼容问题,具体坑在第 5 章讲。

我把推荐环境整理成了表,照着配别自由发挥:

组件推荐版本说明
JDK1.8(jdk-8u201 或更高)高于 1.8 可能出现编译报错或 maven 依赖不兼容
Tomcat8.0 / 8.57.0 对 JSP 支持稍老,9.0 不推荐配 JDK1.8
MySQL5.7.x8.0 可用但需要换驱动和改认证方式
IDEA2019 及以上均可社区版也能跑,但配置 Tomcat 不如专业版方便
Maven3.6.x项目若带 pom.xml 则必须配 Maven

3.2 数据库导入:Navicat 执行 SQL 脚本

拿到项目后先找 .sql 文件,一般在项目根目录或 db 文件夹下。打开 Navicat,新建数据库,字符集选 utf8mb4,排序规则选 utf8mb4_general_ci。选中数据库后右键「运行 SQL 文件」,选择项目里的 .sql 脚本执行。

# 如果你习惯命令行操作,也可以这样导入 mysql -uroot -p你的密码 -h127.0.0.1 --default-character-set=utf8mb4 CREATE DATABASE fruit_market DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; USE fruit_market; SOURCE D:/path/to/fruit_market.sql;

执行完可以检查一下表是否齐全,正常情况下应该有用户表、商品表、订单表、类目表、公告表、留言表和订单详情表。注意 MySQL 5.7 默认的 sql_mode 对 GROUP BY 语句比较严格,如果导入时报 ONLY_FULL_GROUP_BY 相关错误,需要修改 my.ini 里的 sql_mode。

提示:导入前确认 SQL 文件里的建库语句和你手动创建的数据库名一致,不一致的话改 SQL 文件第一行的数据库名,或者直接删除 CREATE DATABASE 语句只保留建表和 INSERT 语句。

数据库连接配置在 src/main/resources 下的 jdbc.properties 里。重点检查 url、username、password 三项,url 里通常带characterEncoding=utf8参数,这个是保证中文不乱码的关键。

jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://127.0.0.1:3306/fruit_market?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai jdbc.username=root jdbc.password=123456

3.3 IDEA 导入项目并配置 Tomcat

打开 IDEA,File → New → Project from Existing Sources,选择项目根目录下的 pom.xml(如果有)或直接选文件夹。如果项目不是 Maven 结构,就选普通 JavaWeb 项目,IDEA 会识别 web.xml 并自动标记 web 目录。

接下来是配置 Tomcat。点击右上角 Add Configuration → 点 + 号 → 选择 Tomcat Server → Local。在 Server 标签页的 Application server 处选择你本地装好的 Tomcat 8,Deployment 标签页点 + 号选择 Artifact,选 war exploded 模式。Application context 填/fruit_market或项目原名,这个就是访问路径。

# Tomcat 部署后的访问路径示例 http://localhost:8080/fruit_market/

配置完点击 Debug 按钮启动。如果控制台出现Artifact is being deployed, please wait说明部署中,出现Server startup in xxx ms就是启动成功了。首页能打开,这个项目才算环境搭完,后面才谈得上验收功能。

3.4 首次启动失败的快速定位法

第一次启动大概率不会一帆风顺。最常见的几个报错要能快速判断方向:ClassNotFoundException说明缺 jar 包,先检查 Maven 依赖有没有下载完整;Connection refused说明数据库没开或端口不对,检查 MySQL 服务是否启动;Access denied for user说明账号密码或权限配置错误。如果报 404 且日志里没有明显异常,先看部署的 Artifact 名称和访问 URL 是否匹配。

注意:IDEA 里部署 war exploded 时,如果改了 Java 代码,IDEA 默认会自动热部署,但改 JSP 文件有时不生效。碰到页面没更新的情况,Manually 触发 update 或者重启 Tomcat,别浪费时间反复刷新页面。

4. 功能验收:把客户购物和管理员发货这条链路走通

4.1 前台购物流程:从注册到下单的每一步验证

系统跑起来后,先走一遍完整的前台流程。打开首页,应该能看到商品列表,图片、价格、库存这些信息正常显示。点「注册」进注册页,填用户名、密码、手机号等字段,提交后看数据库 user 表里是否多了一条记录。然后用刚注册的账号登录,进个人中心确认信息能回显。

关于购物车,选一个商品点「加入购物车」,去购物车页面确认数量和价格计算是否正确。购物车一般会有「改数量」「删除」「结算」三个操作,逐个测。结算后进入订单确认页,填收货地址,提交订单,去个人中心的订单列表里查这笔订单,状态应该是「待发货」或「待付款」之类。这一条链路走通了,前台的核心功能就算验收通过。

<!-- 购物车页面的核心表单结构,仅供参考 --> <form action="cart/update" method="post"> <input type="hidden" name="goodsId" value="${goods.id}" /> <input type="text" name="quantity" value="${cart.quantity}" /> <button type="submit">更新数量</button> </form>

这个表单走的是 POST 请求,Controller 层接收 goodsId 和 quantity 后调 service 更新购物车表。注意看代码里有没有做库存校验,如果改数量超过库存,系统应该给出提示而不是直接成功。

4.2 后台管理:六块功能的增删改查逐个过

用管理员账号登录,进入后台。商品管理里应该有商品列表,支持新增、编辑、删除、上下架。新增商品时要上传图片(如果有文件上传功能),确认图片存到了指定目录且页面能访问。类目管理是商品分类的增删改查,注意删除类目时如果该类目下还有商品,系统应该限制删除或给出警告。

订单管理是最重要的一块。管理员要能看到所有客户订单,支持按状态筛选,能对订单进行发货操作。订单详情里要能看到客户买的什么商品、数量、金额、收货信息。公告管理是发通知用的,客户首页或个人中心能看到公告列表。留言管理是客户给平台的反馈,管理员可以查看和回复。

4.3 验证数据是否落库:三个必查的 SQL 命令

功能点完不代表数据真写进去了,某些页面显示「成功」但数据库里可能没数据,这种情况我遇到过不止一次。验证数据落库最简单的方式是用 Navicat 直接查表。

-- 1. 查用户表,确认注册的用户已写入 SELECT id, username, phone, create_time FROM customer ORDER BY id DESC LIMIT 5; -- 2. 查订单表,确认下单操作已生成订单 SELECT order_id, user_id, total_price, status FROM orders ORDER BY create_time DESC LIMIT 5; -- 3. 查购物车表,确认加购操作已写入 SELECT cart_id, user_id, goods_id, quantity FROM cart ORDER BY cart_id DESC LIMIT 5;

如果查询有结果,说明业务逻辑和数据库交互正常。如果页面提示成功但 SQL 查不到记录,优先检查 Mybatis 的useGeneratedKeys配置以及事务是否提交了。SSM 里常见的一个低级错误是 service 层开了事务但 mapper 执行报错被吞掉了,导致数据没写进去但页面显示正常。

5. 避坑指南:SSM+MySQL+JSP 组合的五个高频翻车点

5.1 MySQL 8.0 认证插件导致连接失败

现象:Tomcat 启动时报Unable to load authentication plugin 'caching_sha2_password'。

原因:MySQL 8.0 默认认证插件是 caching_sha2_password,而项目里的 mysql-connector-java 驱动是 5.1.x 版本,不支持这种认证方式。

解决:两个方案二选一。第一,把数据库连接驱动换成 mysql-connector-java 8.0.x,并在 JDBC URL 里加useSSL=false&serverTimezone=Asia/Shanghai;第二,不改代码,执行一条 SQL 把 root 用户的认证方式改回 mysql_native_password:

ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '你的密码'; FLUSH PRIVILEGES;

我一般直接用第二个方案,省事,而且不影响项目里其他依赖的版本。

5.2 JSP 页面中文乱码,改了 JSP 编码也没用

现象:页面上的中文商品名和公告全是问号或乱码,但数据库里中文是正常的。

原因:JSP 页面本身是 UTF-8,但 Tomcat 接收 POST 请求时默认用 ISO-8859-1 解码,导致中文字节被错误转换。

解决:项目里一般会配置 CharacterEncodingFilter,检查 web.xml 里有没有这个过滤器以及它的 url-pattern 是否覆盖了所有请求。如果配置了还不生效,检查 JSP 页面顶部的pageEncoding和contentType是否都是 UTF-8:

<!-- web.xml 里的字符编码过滤器,必须放在所有过滤器最前面 --> <filter> <filter-name>encodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> <init-param> <param-name>forceEncoding</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>encodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>

注意forceEncoding参数要设成 true,否则只对 GET 请求生效,POST 请求照样乱码。这个参数不看文档根本发现不了,属于经典玄学坑。

5.3 IDEA 热部署失效,改 JSP 页面不刷新

现象:改了 JSP 里的文本或样式,刷新浏览器还是旧内容,重启 Tomcat 才生效。

原因:IDEA 对 war exploded 模式下的 JSP 文件更新机制有时不触发自动编译。Tomcat 默认也有 JSP 缓存的设置,JSP 文件修改后未必立即重新编译。

解决:IDEA 设置里找到 Build → Compiler,勾选 Build project automatically,然后在 Tomcat 配置页面 Server 标签下找到 On frame deactivation,选择 Update classes and resources。如果还是不生效,直接在 Tomcat 配置里把 On update action 设为 Redeploy。血的教训:答辩前天改了一下午页面,最后发现改的哪个文件根本没被编译,全在改空气。

5.4 MySQL 5.7 的 ONLY_FULL_GROUP_BY 报错

现象:执行某些聚合查询时报Expression #1 of SELECT list is not in GROUP BY clause。

原因:MySQL 5.7 以后默认开启 ONLY_FULL_GROUP_BY 模式,SELECT 的字段必须严格出现在 GROUP BY 里或包含在聚合函数中。项目里的订单统计 SQL 如果没注意这个规则,就会报错。

解决:改 SQL 让字段符合规范,或者修改数据库配置关掉这个模式。

-- 查看当前 sql_mode SELECT @@sql_mode; -- 临时关闭 ONLY_FULL_GROUP_BY SET SESSION sql_mode = 'STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';

要永久生效就去 my.ini 的[mysqld]段下修改 sql_mode 配置,改完重启 MySQL。我建议优先改 SQL 而不是改数据库配置,因为答辩时老师会问为什么你的查询不按标准写法来。

5.5 Tomcat 8080 端口被占用

现象:启动 Tomcat 时控制台报Port 8080 required by Tomcat v8.0 Server at localhost is already in use。

原因:之前跑过的 Tomcat 实例没关干净,或者本机其他服务占了 8080。

解决:先找到占用进程并杀掉。

# Windows 下查找占用 8080 的进程 PID netstat -ano | findstr 8080 # 结束进程,把 PID 换成上一步查到的数字 taskkill /pid 你的PID /F

如果是 Linux 环境,用lsof -i:8080查占用进程。

6. 进阶改造:给订单列表加分页查询和简单的数据安全处理

系统跑通只是及格线,想在答辩时多拿分,有两个改动性价比最高:第一是给订单列表加分页,第二是给密码加密。分页是面试和答辩必问的点,密码加密则是导师一定会挑的刺——数据库里明文存密码,这在生产环境是严重安全隐患。

分页改造的思路是:利用 Mybatis 的 PageHelper 插件,在查询订单列表前先设置页码和每页条数,然后查询完用 PageInfo 包装结果集返回。PageHelper 的使用方式是在 Service 层查询语句之前调用静态方法:

// OrderServiceImpl 中查询订单列表加分页 import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageInfo; public PageInfo<Orders> getOrderList(int pageNum, int pageSize) { // 这一行必须放在 Mapper 查询方法之前 PageHelper.startPage(pageNum, pageSize); List<Orders> list = orderMapper.selectOrderList(); // 用 PageInfo 包装,里面包含了总条数、总页数等分页信息 return new PageInfo<>(list); }

Controller 层接收页码和每页条数两个参数,传给 Service。JSP 页面用 PageInfo 提供的 total、pageNum、pages 字段渲染分页按钮。这套组合拳打下来,答辩时讲到「分页查询怎么实现的」这块会非常扎实。

密码加密改造用 Spring 自带的 BCrypt 工具类就行,比 MD5 靠谱。核心是注册时加密存储,登录时校验密码:

// 注册时对密码做加密 import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(); String encodedPassword = encoder.encode(user.getPassword()); user.setPassword(encodedPassword); // 登录校验时对比明文和密文 if (encoder.matches(rawPassword, storedPassword)) { // 密码匹配,允许登录 }

这个改造需要动客户注册、客户登录、管理员登录三个地方,改完把数据库里已有的密码重置一下,重新注册新账号测试。从那以后我每次接手这类毕设项目,都会先检查密码和分页这两块,能用十分钟改完的绝不留到被老师问住再补。希望这篇拆解能帮你在有限的时间里把系统跑稳、把讲点备足。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询