☰
SpringBoot+Vue+MySQL商铺管理系统:从需求到部署全流程实战
2026/10/6 9:31:34 网站建设 项目流程

每年到这个节点,就有大量同学在选题和实现之间反复纠结。像“太原学院商铺管理系统”这种题目,一眼看过去就是典型的校园信息化管理系统,但真正动手做的时候,很多人卡在“不知道管什么”“表怎么设计”“前后端怎么串起来”这几个地方。这篇文章我就用一套完整的SpringBoot+Vue+MySQL方案,把这个项目从头到尾拆开讲,从需求分析到数据库设计,从后端接口到前端页面,再到打包部署和答辩准备,每一步都给出可以直接落地的做法和参数,希望对正在做同类毕业设计的同学有帮助。

做这类系统最大的难点其实不是技术本身,而是需求边界不清晰。商铺管理系统听起来简单,但“管理”两个字可以拆出很多子功能。我见过不少同学一上来就建了十几张表,结果实现到一半发现根本做不完,最后答辩的时候漏洞百出。所以先别急着写代码,花两天时间把需求和表结构理清楚,后面会顺畅很多。

1. 项目需求分析与功能模块拆解

1.1 商铺管理系统到底要管什么

先说清楚这个系统的角色和业务场景。太原学院内的商铺,比如食堂旁边的奶茶店、便利店、打印店,这些都属于学校资产。学校需要一个平台来管理这些商铺的基本信息、经营者信息、合同周期、租金收缴情况,同时还要能发布通知公告、记录投诉建议。所以系统的用户角色至少要分成两类:管理员和商户经营者。

管理员负责商铺的录入、合同的签订与到期提醒、每月账单的生成与核销,以及公告的发布;商户经营者登录后可以查看自己的商铺信息、合同剩余期限、历史账单记录,还能在线发起请求或者查看通知。把角色和权限想清楚之后,功能模块就自然出来了:商铺档案管理、合同管理、账单管理、公告管理、用户权限管理这五个核心模块,再加上登录认证和首页统计。

很多同学在这个环节容易把商铺和合同混在一张表里,这是典型的错误。一个商铺可以被多个合同连续承租,合同到期后可能换经营者,也可能续租。如果字段全塞在一张表里,后续统计和历史追溯会非常痛苦。后面我会详细讲表结构怎么拆。

1.2 技术选型:为什么是SpringBoot+Vue+MySQL

这个组合现在基本是Java Web毕业设计的主流标配,不是没有道理的。SpringBoot的自动配置特性让后端开发省去了大量XML配置,内嵌Tomcat意味着写完代码直接java -jar就能跑,对刚接触企业级开发的同学来说非常友好。Vue则解决了后端渲染页面时代码耦合度高的问题,前端组件化开发,页面切换和交互体验都更接近真实项目。MySQL作为关系型数据库,完全能支撑这种量级的数据。

对比其他的方案,SSH(Struts2+Spring+Hibernate)时代已经过去,配置复杂且社区活跃度低;SSM虽然还在很多学校课件里出现,但使用SpringBoot后你会发现很多繁琐的配置都被简化了。前后端不分离的传统JSP方案虽然也能做,但答辩时容易被老师追问“为什么不用前后端分离”,场面会比较尴尬。所以选这套技术栈,既是市场的选择,也是让你少踩坑的选择。

1.3 数据库设计:核心表结构与关联关系

数据库设计是整个项目的基石,我建议用以下六张表:用户表、商铺表、商户表、合同表、账单表、公告表。其中用户表负责登录认证,角色字段区分管理员和商户;商户表记录经营者的基本信息,比如姓名、电话、身份证号(毕设里可做脱敏);商铺表记录商铺的编号、名称、位置、面积、月租金单价。

关键表结构如下:

  • tb_user:user_id主键,user_name,password,role(1管理员,2商户),关联商户ID
  • tb_shop:shop_id主键,shop_name,shop_no(商铺编号),floor(楼层位置),area(面积),status(0空闲 1出租 2停用)
  • tb_tenant:tenant_id主键,tenant_name,phone,id_card,user_id(关联登录账号)
  • tb_contract:contract_id主键,shop_id外键,tenant_id外键,start_date,end_date,monthly_rent,status(生效中/已到期)
  • tb_bill:bill_id主键,contract_id外键,bill_month,amount,status(0未缴 1已缴),pay_time
  • tb_notice:notice_id主键,title,content,create_time,publisher

设计表的时候要特别注意外键关联的合理性。一条合同记录应该同时关联商铺和商户,账单则关联合同而不是直接关联商铺,这样每个月生成账单的时候,只需要遍历生效中的合同,就能自动带出商户和商铺信息。合同到期提醒功能也不需要在业务代码里反复查询,一条SQL就能完成。

2. 后端SpringBoot核心功能实现

2.1 项目初始化与分层架构

新建SpringBoot项目的时候,建议Java版本选JDK 8或11,Spring Boot版本建议2.7.x,不要一上来就选3.x,因为3.x是基于Jakarta命名空间的,很多网上的老资料不适用,遇到问题排查起来很浪费时间。依赖方面需要引入Spring Web、Mybatis-Plus、MySQL Driver、Lombok、JWT相关库。

分层这块,我习惯拆成controller、service、mapper、entity、common五个包。entity对应每一张表的实体类,mapper层用MyBatis-Plus提供的BaseMapper,大部分CRUD根本不用写SQL,service层封装业务逻辑,controller层只负责接收参数和返回结果。common包中放统一返回结果类Result和异常处理类。

统一返回结果类是前后端协作的关键。我封装一个Result类,里面包含code(200成功、500失败)、message、data三个字段,所有接口都返回这个结构。前端axios拦截器里统一判断code,弹出提示。这样做的好处是数据格式规范,前端处理逻辑非常简洁。

application.yml中主要的配置有端口号、数据库连接信息、MyBatis-Plus的日志输出。数据库配置的坑比较多,注意URL要加useSSL=false&serverTimezone=Asia/Shanghai,避免时区报错;驱动类用com.mysql.cj.jdbc.Driver。

2.2 登录认证与JWT权限控制

登录认证这块,我推荐用JWT方案,比Session更适合前后端分离的项目。登录流程很简单:前端把用户名密码传到后端,后端先校验用户是否存在,再用BCrypt去校验密码,通过之后生成一个有效期为24小时的token返回给前端。前端把token存在localStorage里,每次请求在请求头中带上Authorization字段。

JWT生成的代码非常简单,使用jjwt库:

String token = Jwts.builder() .setSubject(user.getUserId().toString()) .claim("role", user.getRole()) .setExpiration(new Date(System.currentTimeMillis() + 24 * 60 * 60 * 1000)) .signWith(SignatureAlgorithm.HS256, secretKey) .compact();

关键点是那个secretKey,建议写进配置文件中,不要硬编码在代码里。校验token的逻辑我放在拦截器里,写一个WebMvcConfigurer注册拦截器,拦截所有/api/**的请求,排除登录接口。解析token时如果抛异常,就返回401。还有一点要注意,管理员和商户的权限是不同的,我习惯在拦截器解析token后把用户ID存到ThreadLocal或者Request attribute中,业务方法里通过方法参数直接拿。

2.3 核心业务接口开发与联调要点

业务接口中工作量最大的是商铺管理、合同管理和账单管理。商铺管理的增删改查没什么难度,直接用MyBatis-Plus的selectPage就能完成分页查询,重点在于条件搜索,比如根据商铺名称、状态、楼层进行筛选,这需要构造LambdaQueryWrapper。

合同管理里最有业务价值的逻辑是到期提醒。实现方式可以在合同表中添加一个status字段,再写一个定时任务(SpringBoot的@Scheduled注解)每天扫描一次合同表,把结束日期减去当前日期小于等于30天的合同状态标记为“即将到期”,同时生成一条待办记录。这个功能展示在管理员的首页,答辩时非常加分。

账单管理的核心是账单生成逻辑。我的做法是提供一个手动生成接口,管理员点击“生成当月账单”按钮,后端遍历所有生效中的合同,根据合同月租金生成账单记录,月份取当前月份。避免重复生成的逻辑是判断bill_month和合同ID的组合是否已存在。收款核销操作也很简单,修改账单状态为已缴,记录支付时间即可。

3. 前端Vue页面开发与交互实现

3.1 Vue项目搭建与环境配置

前端我使用的是Vue 3 + Vite + Element Plus的组合。Vite的启动速度比Vue CLI那套webpack方案快非常多,而且配置简单。创建项目只需要一条命令:npm create vite@latest shop-frontend,然后选择Vue模板,进入目录执行npm install安装依赖。

装Element Plus组件库和路由、axios:

npm install element-plus npm install vue-router@4 axios

main.js中按需引入Element Plus,需要注意样式文件的引入。我之前踩过一个坑,只引入组件不引入样式,页面排版完全错乱,排查了大半天。解决方法是全局引入:import 'element-plus/dist/index.css'。

项目的目录结构我建议这样组织:views存放页面级组件,components存放公共组件,router存放路由配置,api存放所有接口请求方法,utils存放封装好的axios实例。把请求集中放在api目录里是个非常良好的习惯,后期维护接口时你只需要改一个文件,而不是去每个页面里翻。

3.2 核心页面设计与路由权限控制

页面层面至少要开发七个页面:登录页、系统首页(仪表盘)、商铺管理列表、合同管理列表、账单管理列表、公告管理列表、个人中心。其中商铺管理和合同列表的页面结构类似:顶部是搜索条件区,中间是操作按钮,下面是一张表格,右侧是分页组件。

路由配置上要加入路由守卫。最简单的做法是判断localStorage里有没有token,没有就重定向到登录页。角色权限这块,可以给路由meta中添加role字段,管理员路由添加meta: { role: 1 },在守卫里判断当前用户角色是否为1,不是就拒绝访问。这样商户登录后看不到管理员的菜单和页面。

接口请求封装方面,axios实例要配置baseURL为/api,这样开发环境通过Vite的proxy代理转发到后端8090端口。关键配置在vite.config.js中:

server: { proxy: { '/api': { target: 'http://localhost:8090', changeOrigin: true } } }

3.3 前后端交互和常见报错处理

前后端联调时最容易出问题的就是字段不一致。比如后端返回的字段是createTime,前端却写成create_time,表格里就显示为空。解决方案有两个:一是在后端实体类上用@JsonProperty注解映射;二是在前端尽量使用驼峰命名对齐。我的习惯是后端统一返回驼峰格式,在application.yml中配置map-underscore-to-camel-case: true,这样数据库的下划线字段可以自动映射到实体类的驼峰属性。

跨域问题的处理分两类。开发环境用Vite的proxy来解决,基本不会出现跨域报错;但如果前端独立部署,后端的CORS配置就需要加上。在SpringBoot中写一个WebMvcConfigurer配置类,重写addCorsMappings方法,允许所有来源访问/api/**路径。不过毕设阶段不太推荐前后端分离部署,直接把构建产物放进SpringBoot更省事,这个后面讲。

另一个高频报错是axios请求拦截器忘记携带token,导致所有接口都返回401未认证。一定要在拦截器里配置:

instance.interceptors.request.use(config => { const token = localStorage.getItem('token') if (token) { config.headers.Authorization = token } return config })

4. 数据库配置与系统部署上线

4.1 MySQL安装与数据库初始化

数据库部分很多同学卡在环境安装上。如果你用的是Windows,下载MySQL 5.7.44或者8.0都可以。安装时选择自定义安装路径,字符集选utf8mb4。安装完成后需要手动配置环境变量,否则命令行无法直接使用mysql命令。最后一定要启动MySQL服务,然后打开命令行测试:mysql -u root -p,能进入代表安装成功。

初始化数据库有两种方式:一种是在Navicat中手动执行SQL脚本建库建表;另一种是在SpringBoot的配置中开启sql.init.mode=always并放置schema.sql文件。我更推荐第一种,因为手动建表能帮你理清表间关系,而且可以为后面插入测试数据做准备。测试数据非常重要,我建议为每个模块准备5条以上示例数据,尤其是商铺表中不同状态的记录,这样演示分页和条件搜索的时候不会显得空。

还要提醒一句,MySQL时区问题在配置数据库连接时就要处理,URL加上serverTimezone=Asia/Shanghai是最省心的处理方式。如果你的项目中有时间字段插入后差8小时的情况,优先检查数据库连接URL的参数,而不是盲目改代码。

4.2 前端打包整合进SpringBoot

前后端整合部署是毕设演示和答辩的必要步骤。首先在前端项目根目录执行npm run build,构建完成后会生成dist目录,里面包含index.html和静态资源。把dist目录里的所有文件直接复制到SpringBoot项目的src/main/resources/static目录下,重新启动后端项目,浏览器访问http://localhost:8090就能直接打开前端页面。

这里有两个细节需要注意。一是前端路由如果使用了history模式,刷新页面时会出现404,因为SpringBoot默认找不到对应的路径。解决办法是在后端写一个路由重定向Controller,把非API请求转发到首页,或者将Vue路由改为hash模式。我建议毕设直接改用hash模式,既简单又不用改后端配置。二是在打包前要检查前端环境变量中API请求的baseURL,生产环境必须直接使用相对路径,而不是写死localhost端口,否则打包后所有请求都会404。

4.3 项目演示与答辩准备经验

系统上线跑通之后,不要急着写论文,先自己按答辩评委的视角过一遍系统。我建议准备一份演示脚本,包含几个必操作流程:管理员登录、新增商铺、签订合同、生成当月账单、核销一笔租金、发布公告、退出登录、切换商户账号查看数据。每个操作都需要提前准备好测试数据,比如要能演示合同到期后状态自动变化,就提前把一条合同的结束日期改为明天。

答辩老师常问的几个方向要提前准备答案:为什么选这个题目、系统的角色权限如何实现、数据库怎么设计、JWT和Session的区别、遇到的最大困难是什么。回答的时候不要背概念,要结合你项目里的实际代码说。比如问权限设计,你们可以直接说“我在拦截器中解析token中的role字段,然后配置了路由守卫,前端也根据角色动态渲染菜单”,这样既具体又有说服力。

还有一个容易被忽视的点,就是项目的亮点包装。单纯的增删改查肯定不够出彩,所以前文提到的定时任务到期提醒、Excel导出功能、首页的ECharts统计图表,建议至少选一个做进去。尤其是首页统计,用ECharts展示商铺出租率、月度租金趋势,视觉效果非常直观,答辩时作为第一页展示最能吸引老师注意力。

5. 常见问题排查与避坑经验汇总

5.1 启动阶段常见报错速查

运行项目时遇到的报错,百分之八十集中在端口冲突、数据库连接失败、依赖冲突这三类。整理的速查表如下:

异常现象常见原因解决方案
Port 8090 was already in use端口被占用修改application.yml端口或杀掉占用进程
Access denied for user root数据库密码错误检查配置文件中的用户名密码
Unknown database xxx数据库不存在先在MySQL中执行建库语句
java.sql.SQLException: The server time zoneURL缺少时区参数连接串加serverTimezone=Asia/Shanghai
Failed to configure a DataSource缺少jdbc依赖检查pom.xml是否引入mysql驱动
前端npm install报错node版本过高或网络问题用Node 16 LTS版本,配置镜像源

5.2 开发调试阶段的坑点记录

后端联调时最常见的坑是Lombok失效,导致实体类的getter和setter找不到。检查一下IDEA是否安装了Lombok插件,以及编译选项中是否开启了注解处理。另一个高频问题是使用MyBatis-Plus之后,自定义SQL无法生效,因为默认的Mapper扫描路径写错了。确保启动类上的@MapperScan注解路径和实际的mapper包路径一致。

前端方面,Element Plus表格的重新渲染问题比较隐蔽。当你修改数据后刷新列表,数据源没更新,界面显示的还是旧数据。解决办法是重新调用接口获取数据,并把新数据赋值给ref变量。还有弹窗表单的内容不重置,解决办法是在关闭弹窗时调用resetFields()方法。这些小细节虽然不复杂,但直接影响演示效果,一定要提前测通。

5.3 时间规划与工作量把控建议

最后聊聊毕业设计的节奏。我的经验是不要试图做到大而全,把核心闭环做深比堆砌功能重要得多。以本系统为例,商铺、合同、账单这条主线必须全部打通,公告和用户管理是最基础的配套,统计图表是加分项。如果周期紧张,后期功能可以简化为列表展示,但主流程一定不能有逻辑漏洞。

代码写完之后,建议用三天时间专门检查业务流程。拿一张纸,把每个角色的操作路径写出来,按顺序走一遍系统。比如管理员从登录到发布公告再到退出,期间每一步的数据是否一致。这种以业务视角驱动测试的方式,比盲目的点击按钮更能发现问题,也会让你在答辩的时候更有底气。毕竟老师不关心你写了多少行代码,关心的是你系统跑起来业务是否合理。

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

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

立即咨询