SpringBoot+Vue全栈项目实战:从零搭建超市管理系统毕业设计

发布时间:2026/7/21 7:59:15
SpringBoot+Vue全栈项目实战:从零搭建超市管理系统毕业设计 如果你是一名计算机相关专业的毕业生此刻正对着“毕业设计”四个字一筹莫展那么这篇文章就是为你准备的。你可能已经学了几年Java、SpringBoot、Vue但面对一个需要从前端到后端、从数据库到部署的完整项目时依然感到无从下手。市面上的教程要么过于简单要么直接甩给你一个看不懂的源码包中间缺失的“从0到1”的搭建过程恰恰是新手最需要、也最容易卡壳的地方。今天我们不谈空泛的理论直接动手。我将带你从零开始一步步构建一个功能完整的“鲜享超市管理系统”。这篇文章的核心价值在于它不仅仅是一个项目源码的搬运而是一份详尽的“施工图纸”和“避坑指南”。我会把每个环节为什么这么做、可能遇到什么问题、如何解决都讲清楚。目标是让你在完成这个项目后不仅能交出一份合格的毕设更能真正理解一个现代Java Web应用是如何被构建起来的。我们将采用目前企业中最主流、也最适合毕设的技术栈SpringBoot Vue MyBatis-Plus MySQL。这套组合拳能让你快速搭建起一个结构清晰、易于维护的项目。下面就让我们开始这场从零开始的实战之旅。1. 项目全景与核心价值为什么选择这个项目在开始敲代码之前我们首先要搞清楚做这个项目到底能收获什么。一个超市管理系统看似普通实则“麻雀虽小五脏俱全”它几乎涵盖了企业级应用开发的所有核心模块。1.1 技术覆盖面广直击毕设痛点权限管理 (RBAC)不同角色如管理员、店长、收银员拥有不同的菜单和操作权限。这是毕设中体现系统设计深度的关键点。商品与库存管理包含商品的增删改查、分类管理、库存盘点、入库出库流水。涉及数据库表设计、事务控制等核心知识。订单与销售管理模拟用户下单、支付可模拟、订单状态流转。这是理解业务逻辑和状态机设计的绝佳案例。数据统计与报表销售统计、商品销量排行等。会用到复杂的SQL查询或MyBatis-Plus的聚合功能是展示数据分析能力的亮点。1.2 技术栈主流且实用后端 (SpringBoot)简化了传统SSM框架繁琐的配置让你专注于业务逻辑。集成MyBatis-Plus后单表CRUD几乎无需手写SQL极大提升开发效率。前端 (Vue)组件化开发响应式数据绑定。相比于传统的JSPVue能让前端界面更优雅、交互更流畅是当前前端开发的绝对主流。前后端分离这是现代Web开发的标配。前后端通过RESTful API交互职责清晰便于独立开发和部署。掌握这一点你的项目结构就超越了大部分“缝合怪”式的毕设。1.3 学习路径清晰可逐步深入本项目设计为“脚手架”模式。我会先带你搭建最基础的用户登录和商品管理模块确保你能跑通整个流程。在此基础上你可以像搭积木一样自行扩展会员管理、促销活动、供应商管理等更多功能。这种模式能让你建立信心并拥有持续改进的空间。2. 环境准备磨刀不误砍柴工在开始编码前请确保你的开发环境已就绪。以下是我推荐的版本尽量保持一致以避免不必要的兼容性问题。2.1 后端开发环境JDK: 1.8 或 11 (推荐11长期支持版本)IDE: IntelliJ IDEA (社区版或旗舰版均可本文演示基于IDEA)项目管理与构建工具: Apache Maven 3.6数据库: MySQL 5.7 或 8.0 (推荐8.0)2.2 前端开发环境Node.js: 14.x 或 16.x LTS 版本包管理工具: npm (随Node.js安装) 或 yarn (可选)IDE: Visual Studio Code (轻量高效) 或 WebStorm2.3 环境检查与配置打开终端或命令提示符逐一执行以下命令进行验证# 检查Java版本 java -version # 检查Maven版本 mvn -v # 检查Node.js和npm版本 node -v npm -v # 登录MySQL检查版本 mysql -u root -p SELECT VERSION();如果任何一项检查失败请先安装或配置对应的环境变量。3. 后端工程搭建用SpringBoot快速启动我们将使用Spring Initializr来生成项目骨架这是最规范、最省事的方式。3.1 使用IDEA创建SpringBoot项目打开IDEA选择File - New - Project。左侧选择Spring Initializr选择合适的JDK版本。填写项目信息Group:com.xianxiang(可自定义一般为公司域名倒写)Artifact:supermarket-systemType: MavenJava Version: 8 或 11Packaging: Jar在Dependencies中添加我们初期需要的依赖Spring Web(构建Web应用)MyBatis Framework(数据库ORM)MySQL Driver(数据库连接)Lombok(简化Java Bean代码强烈推荐)点击FinishIDEA会自动下载依赖并创建项目。3.2 项目结构与关键配置创建完成后你的项目结构应类似于supermarket-system ├── src/main/java │ └── com.xianxiang.supermarketsystem │ └── SupermarketSystemApplication.java (启动类) ├── src/main/resources │ ├── application.properties (或 application.yml) │ └── static/ templates/ (暂时用不到前后端分离) └── pom.xml (Maven依赖管理文件)接下来配置数据库连接。修改src/main/resources/application.yml(如果不存在创建它如果存在application.properties可以删除或重命名YAML格式更清晰)# application.yml server: port: 8080 # 后端服务端口 spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/supermarket_db?useUnicodetruecharacterEncodingutf-8serverTimezoneAsia/Shanghai username: root # 你的MySQL用户名 password: yourpassword # 你的MySQL密码 # 配置JPA/Hibernate特性用于自动创建表非必须但方便 jpa: hibernate: ddl-auto: update # 启动时更新表结构生产环境请改为validate或none show-sql: true # 控制台打印SQL便于调试 # MyBatis 配置 mybatis: mapper-locations: classpath:mapper/*.xml # XML映射文件位置 type-aliases-package: com.xianxiang.supermarketsystem.entity # 实体类包名 configuration: map-underscore-to-camel-case: true # 自动将下划线字段映射为驼峰属性注意请先在MySQL中创建数据库supermarket_db。CREATE DATABASE IF NOT EXISTS supermarket_db CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;4. 核心模块开发从数据库到API我们将采用经典的Controller - Service - Mapper - Entity分层架构。首先从最简单的“用户”模块开始。4.1 实体层 (Entity) 与 Lombok创建用户实体类src/main/java/com/xianxiang/supermarketsystem/entity/User.java。package com.xianxiang.supermarketsystem.entity; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; import java.time.LocalDateTime; Data // Lombok注解自动生成getter, setter, toString等方法 TableName(sys_user) // MyBatis-Plus注解指定表名 public class User { TableId(type IdType.AUTO) // 主键自增 private Long id; private String username; // 用户名 private String password; // 密码存储加密后的 private String nickname; // 昵称 private String email; private String phone; private String avatar; // 头像地址 private Integer status; // 状态 0:禁用 1:正常 private Integer isAdmin; // 是否是管理员 0:否 1:是 private LocalDateTime createTime; private LocalDateTime updateTime; }这里我们引入了MyBatis-Plus它是一个强大的MyBatis增强工具。需要在pom.xml中添加依赖dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-boot-starter/artifactId version3.5.3.1/version !-- 请使用最新稳定版 -- /dependency4.2 数据访问层 (Mapper)创建src/main/java/com/xianxiang/supermarketsystem/mapper/UserMapper.java。package com.xianxiang.supermarketsystem.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.xianxiang.supermarketsystem.entity.User; import org.apache.ibatis.annotations.Mapper; Mapper // 标识为MyBatis的Mapper接口 public interface UserMapper extends BaseMapperUser { // 继承BaseMapper后基本的CRUD方法已自动拥有无需编写XML或实现类 // 例如selectById, insert, updateById, deleteById, selectList等 }4.3 业务逻辑层 (Service)创建接口UserService.java和其实现类UserServiceImpl.java。// UserService.java package com.xianxiang.supermarketsystem.service; import com.baomidou.mybatisplus.extension.service.IService; import com.xianxiang.supermarketsystem.entity.User; public interface UserService extends IServiceUser { // 可以在此定义复杂的业务方法不局限于BaseMapper提供的CRUD User login(String username, String password); } // UserServiceImpl.java package com.xianxiang.supermarketsystem.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.xianxiang.supermarketsystem.entity.User; import com.xianxiang.supermarketsystem.mapper.UserMapper; import com.xianxiang.supermarketsystem.service.UserService; import org.springframework.stereotype.Service; import org.springframework.util.DigestUtils; Service public class UserServiceImpl extends ServiceImplUserMapper, User implements UserService { Override public User login(String username, String password) { // 1. 根据用户名查询用户 LambdaQueryWrapperUser queryWrapper new LambdaQueryWrapper(); queryWrapper.eq(User::getUsername, username); User user this.getOne(queryWrapper); // 2. 判断用户是否存在 if (user null) { throw new RuntimeException(用户名或密码错误); } // 3. 判断密码是否匹配 (这里使用MD5简单加密生产环境应用更安全的如BCrypt) String encryptedPassword DigestUtils.md5DigestAsHex(password.getBytes()); if (!user.getPassword().equals(encryptedPassword)) { throw new RuntimeException(用户名或密码错误); } // 4. 判断用户状态 if (user.getStatus() 0) { throw new RuntimeException(账号已被禁用); } // 5. 登录成功返回用户信息注意应去除密码等敏感信息 user.setPassword(null); return user; } }4.4 控制层 (Controller) 与 RESTful API创建src/main/java/com/xianxiang/supermarketsystem/controller/UserController.java。package com.xianxiang.supermarketsystem.controller; import com.xianxiang.supermarketsystem.common.Result; import com.xianxiang.supermarketsystem.entity.User; import com.xianxiang.supermarketsystem.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; RestController RequestMapping(/api/user) public class UserController { Autowired private UserService userService; PostMapping(/login) public Result login(RequestBody User user) { // 使用RequestBody接收JSON格式参数 try { User loggedInUser userService.login(user.getUsername(), user.getPassword()); return Result.success(登录成功, loggedInUser); } catch (RuntimeException e) { return Result.error(e.getMessage()); } } GetMapping(/{id}) public Result getUserById(PathVariable Long id) { User user userService.getById(id); if (user ! null) { user.setPassword(null); // 返回前脱敏 return Result.success(user); } return Result.error(用户不存在); } // 后续可以添加注册、修改信息、分页查询等接口 }这里用到了一个统一的返回结果封装类Result这是一个非常实用的技巧。// src/main/java/com/xianxiang/supermarketsystem/common/Result.java package com.xianxiang.supermarketsystem.common; import lombok.Data; Data public class ResultT { private Integer code; // 状态码如200成功500失败 private String msg; // 提示信息 private T data; // 返回的数据 public static T ResultT success(T data) { ResultT result new Result(); result.setCode(200); result.setMsg(操作成功); result.setData(data); return result; } public static T ResultT success(String msg, T data) { ResultT result new Result(); result.setCode(200); result.setMsg(msg); result.setData(data); return result; } public static T ResultT error(String msg) { ResultT result new Result(); result.setCode(500); result.setMsg(msg); return result; } }5. 前端工程搭建与登录页面实现后端API准备好了现在来构建前端。我们使用Vue CLI快速搭建项目。5.1 创建Vue项目打开终端进入你的工作目录执行# 使用npm安装Vue CLI如果已安装请跳过 npm install -g vue/cli # 创建项目 vue create supermarket-frontend # 进入项目创建流程这里选择手动配置 # 请确保勾选Babel, Router, Vuex, CSS Pre-processors (如Sass/SCSS), Linter/Formatter可暂时不选 # Vue版本选择 2.x 或 3.x本文以Vue 2为例更稳定且生态成熟 cd supermarket-frontend5.2 安装必要依赖除了创建时选择的我们还需要安装UI库和HTTP请求库。npm install element-ui axios --save # Element UI 是一套基于Vue的桌面端组件库非常适合后台管理系统 # Axios 是一个基于Promise的HTTP库用于发送请求5.3 配置Element UI和Axios在src/main.js中引入并配置import Vue from vue import App from ./App.vue import router from ./router import store from ./store import ElementUI from element-ui import element-ui/lib/theme-chalk/index.css import axios from axios Vue.config.productionTip false Vue.use(ElementUI) // 将axios挂载到Vue原型上方便在组件中使用 this.$axios Vue.prototype.$axios axios // 配置axios的基准URL指向后端服务 axios.defaults.baseURL http://localhost:8080 new Vue({ router, store, render: h h(App) }).$mount(#app)5.4 实现登录页面创建src/views/Login.vuetemplate div classlogin-container el-form refloginForm :modelform :rulesrules classlogin-form label-width80px h2 classtitle鲜享超市管理系统/h2 el-form-item label用户名 propusername el-input v-modelform.username placeholder请输入用户名/el-input /el-form-item el-form-item label密码 proppassword el-input v-modelform.password typepassword placeholder请输入密码 keyup.enter.nativehandleLogin/el-input /el-form-item el-form-item el-button typeprimary clickhandleLogin :loadingloading stylewidth:100%;登录/el-button /el-form-item /el-form /div /template script export default { name: Login, data() { return { form: { username: admin, password: 123456 }, rules: { username: [{ required: true, message: 请输入用户名, trigger: blur }], password: [{ required: true, message: 请输入密码, trigger: blur }] }, loading: false } }, methods: { handleLogin() { this.$refs.loginForm.validate(valid { if (valid) { this.loading true // 调用后端登录接口 this.$axios.post(/api/user/login, this.form) .then(response { if (response.data.code 200) { this.$message.success(response.data.msg) // 1. 将用户信息存储到Vuex或本地存储 localStorage.setItem(user, JSON.stringify(response.data.data)) // 2. 跳转到主页 this.$router.push(/) } else { this.$message.error(response.data.msg) } }) .catch(error { this.$message.error(登录失败 (error.response?.data?.msg || error.message)) }) .finally(() { this.loading false }) } else { return false } }) } } } /script style scoped .login-container { height: 100vh; display: flex; justify-content: center; align-items: center; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); } .login-form { width: 400px; padding: 40px; background: #fff; border-radius: 10px; box-shadow: 0 15px 35px rgba(50, 50, 93, 0.1), 0 5px 15px rgba(0, 0, 0, 0.07); } .title { text-align: center; margin-bottom: 30px; color: #333; } /style5.5 配置路由修改src/router/index.js将登录页设置为默认路由。import Vue from vue import VueRouter from vue-router import Login from ../views/Login.vue Vue.use(VueRouter) const routes [ { path: /login, name: Login, component: Login }, { path: /, redirect: /login // 默认重定向到登录页 } // ... 后续可以在这里添加主页、商品管理等路由 ] const router new VueRouter({ mode: history, base: process.env.BASE_URL, routes }) export default router6. 前后端联调与运行验证这是最关键的一步确保前后端能正常通信。6.1 启动后端服务在IDEA中找到SupermarketSystemApplication.java右键点击Run。看到控制台输出类似Tomcat started on port(s): 8080的信息说明后端启动成功。6.2 启动前端服务在supermarket-frontend目录下运行npm run serve服务启动后通常会显示App running at: - Local: http://localhost:8081。6.3 解决跨域问题 (CORS)此时前端运行在http://localhost:8081后端在http://localhost:8080端口不同浏览器会因同源策略阻止请求。我们需要在后端配置CORS。 在SpringBoot后端创建一个配置类// src/main/java/com/xianxiang/supermarketsystem/config/CorsConfig.java package com.xianxiang.supermarketsystem.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import org.springframework.web.filter.CorsFilter; Configuration public class CorsConfig { Bean public CorsFilter corsFilter() { CorsConfiguration config new CorsConfiguration(); // 允许所有域名进行跨域调用生产环境应指定具体域名 config.addAllowedOriginPattern(*); // 允许跨越发送cookie config.setAllowCredentials(true); // 放行全部原始头信息 config.addAllowedHeader(*); // 允许所有请求方法跨域调用 config.addAllowedMethod(*); UrlBasedCorsConfigurationSource source new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration(/**, config); return new CorsFilter(source); } }6.4 初始化数据库与测试登录重启后端服务使CORS配置生效。由于我们在application.yml中配置了ddl-auto: updateSpring Boot会自动根据User实体创建sys_user表。我们需要手动插入一个测试用户。可以使用数据库工具或编写一个简单的初始化SQL脚本。-- 在MySQL的supermarket_db数据库中执行 INSERT INTO sys_user (username, password, nickname, status, is_admin) VALUES (admin, MD5(123456), 系统管理员, 1, 1);打开浏览器访问http://localhost:8081(或前端服务提示的地址)应该会自动跳转到登录页。输入用户名admin密码123456点击登录。如果配置正确你会看到“登录成功”的提示并跳转虽然主页还没做。至此你已经成功打通了前后端最核心的链路这是一个从零到一的巨大飞跃。7. 核心功能扩展商品管理模块实战登录跑通后我们快速搭建第二个核心模块——商品管理来巩固开发流程。7.1 后端商品实体、Mapper、Service、Controller实体类Product.java:package com.xianxiang.supermarketsystem.entity; import com.baomidou.mybatisplus.annotation.*; import lombok.Data; import java.math.BigDecimal; import java.time.LocalDateTime; Data TableName(product) public class Product { TableId(type IdType.AUTO) private Long id; private String productCode; // 商品编码 private String productName; // 商品名称 private Long categoryId; // 分类ID private BigDecimal price; // 单价 private Integer stock; // 库存 private String unit; // 单位如件、千克 private String imageUrl; // 商品图片 private String description; // 描述 private Integer status; // 状态 1:上架 0:下架 TableField(fill FieldFill.INSERT) private LocalDateTime createTime; TableField(fill FieldFill.INSERT_UPDATE) private LocalDateTime updateTime; }Mapper接口ProductMapper.java:package com.xianxiang.supermarketsystem.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.xianxiang.supermarketsystem.entity.Product; import org.apache.ibatis.annotations.Mapper; Mapper public interface ProductMapper extends BaseMapperProduct { }Service层ProductService和ProductServiceImpl(结构同User略)。ControllerProductController.java:package com.xianxiang.supermarketsystem.controller; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.xianxiang.supermarketsystem.common.Result; import com.xianxiang.supermarketsystem.entity.Product; import com.xianxiang.supermarketsystem.service.ProductService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.*; RestController RequestMapping(/api/product) public class ProductController { Autowired private ProductService productService; // 新增或修改 PostMapping public Result save(RequestBody Product product) { // 简单校验 if (StringUtils.isEmpty(product.getProductName())) { return Result.error(商品名称不能为空); } productService.saveOrUpdate(product); return Result.success(操作成功); } // 分页查询带条件 GetMapping(/page) public Result findPage(RequestParam(defaultValue 1) Integer pageNum, RequestParam(defaultValue 10) Integer pageSize, RequestParam(defaultValue ) String productName) { IPageProduct page new Page(pageNum, pageSize); LambdaQueryWrapperProduct queryWrapper new LambdaQueryWrapper(); if (!StringUtils.isEmpty(productName)) { queryWrapper.like(Product::getProductName, productName); } // 按创建时间倒序 queryWrapper.orderByDesc(Product::getCreateTime); IPageProduct productPage productService.page(page, queryWrapper); return Result.success(productPage); } // 删除 DeleteMapping(/{id}) public Result delete(PathVariable Long id) { productService.removeById(id); return Result.success(删除成功); } }7.2 前端商品列表与表单页面在src/views/下创建Product.vue实现一个包含查询、表格、新增、编辑、删除功能的页面。由于代码较长这里给出核心思路和关键代码片段在router/index.js中配置路由。在Product.vue中使用el-table展示商品列表。使用el-pagination实现分页。使用el-dialog弹出新增/编辑表单。使用this.$axios调用后端的/api/product/page、/api/product(POST/PUT)、/api/product/{id}(DELETE) 接口。在created()或mounted()生命周期钩子中调用获取第一页数据的方法。这是一个典型的前后端分离CRUD操作掌握了这个模式其他如分类管理、订单管理等模块都可以如法炮制。8. 常见问题与排查思路 (QA)在开发过程中你几乎一定会遇到下面这些问题。提前了解能节省大量排查时间。问题现象可能原因排查方式解决方案后端启动失败端口被占用8080端口已被其他程序如旧SpringBoot应用、Tomcat占用查看IDEA控制台错误日志或使用netstat -ano | findstr :8080(Win) 或lsof -i:8080(Mac/Linux) 命令1. 在application.yml中修改server.port。 2. 终止占用端口的进程。前端npm run serve失败Node.js版本不兼容、依赖未安装、网络问题查看命令行报错信息通常是红色错误日志1. 确认Node.js版本符合要求。 2. 删除node_modules和package-lock.json重新npm install。 3. 检查网络或配置npm镜像源。前端访问后端API报404后端API路径错误、后端服务未启动、CORS未配置1. 检查浏览器开发者工具Network标签看请求URL是否正确。 2. 确认后端控制台无报错且已启动。 3. 查看请求的Response Headers是否有Access-Control-Allow-Origin。1. 核对axios.defaults.baseURL和后端RequestMapping路径。 2. 确保后端CORS配置正确且已生效。登录成功但无法跳转/无反应前端路由配置错误、Vuex或本地存储未正确保存状态、主页组件未开发1. 查看浏览器控制台有无JS错误。 2. 检查localStorage是否保存了用户信息。 3. 检查登录成功后this.$router.push的路径是否存在。1. 正确配置路由。 2. 开发一个简单的主页组件并配置路由。 3. 使用Vuex进行全局状态管理是更佳实践。数据库连接失败MySQL服务未启动、数据库名/用户名/密码错误、时区配置问题查看后端启动日志通常会有明确的连接失败信息。1. 启动MySQL服务。 2. 核对application.yml中的数据库配置。 3. 在数据库URL中添加serverTimezoneAsia/Shanghai。MyBatis-Plus 插入/更新失败实体类字段与数据库表列名不匹配、主键策略错误查看MyBatis-Plus打印的SQL日志对比生成的SQL与你的预期。1. 使用TableField注解指定映射关系。 2. 确认TableId的主键策略如AUTO与数据库自增设置一致。9. 项目完善与最佳实践建议完成基础模块后你可以从以下方向深化项目这会让你的毕设脱颖而出。9.1 引入权限控制后端使用Spring Security或Shiro JWT (JSON Web Token)。用户登录后后端生成一个Token返回给前端前端后续请求在Header中携带此Token后端进行校验和权限解析。前端根据用户角色从Token解析或接口获取动态生成路由菜单使用Vue Router的导航守卫和动态路由。9.2 文件上传功能商品图片需要上传。可以使用SpringBoot的MultipartFile接收文件并存储到服务器本地或云存储如OSS、COS将文件访问URL保存到数据库。9.3 数据导出使用Apache POI或EasyExcel库实现将商品列表、销售报表等数据导出为Excel文件。9.4 前端工程化优化API统一管理将所有的this.$axios调用抽离到单独的src/api/目录下的JS文件中。环境变量使用.env.development和.env.production区分开发和生产环境的API地址。组件封装将常用的表格、表单、弹窗等封装成可复用的组件。9.5 部署与打包后端使用mvn clean package打包成Jar文件通过java -jar your-app.jar运行。考虑使用Docker容器化部署。前端使用npm run build生成静态文件在dist目录将其放到Nginx或SpringBoot的static目录下进行部署。9.6 文档与注释良好的文档是优秀毕设的一部分。在项目根目录创建README.md写明项目介绍、技术栈、部署步骤。在关键代码处添加清晰的注释。走到这里你已经从一个“无从下手”的状态变成了一个拥有完整全栈项目开发脉络的准开发者。这个“鲜享超市管理系统”项目骨架已经具备了用户认证、商品管理等核心功能并且采用了前后端分离、分层架构等现代开发模式。你可以在此基础上继续添加库存管理、订单流程、数据统计图表等模块最终形成一个丰满的毕业设计。最重要的是通过这个从零搭建的过程你收获的不仅仅是一份可以运行的代码而是一套解决同类问题的可复用方法论。下次再遇到新的业务需求你就能清晰地知道实体如何设计、接口如何划分、前后端如何协作、问题如何排查。这才是本篇文章希望带给你的超越项目本身的核心价值。建议你将此项目作为基础不断迭代和扩展它完全有潜力成为你简历上的一个亮眼作品。