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):组件化开发,响应式数据绑定。相比于传统的JSP,Vue能让前端界面更优雅、交互更流畅,是当前前端开发的绝对主流。
  • 前后端分离:这是现代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 (轻量高效) 或 WebStorm

2.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项目

  1. 打开IDEA,选择File -> New -> Project
  2. 左侧选择Spring Initializr,选择合适的JDK版本。
  3. 填写项目信息:
    • Group:com.xianxiang(可自定义,一般为公司域名倒写)
    • Artifact:supermarket-system
    • Type: Maven
    • Java Version: 8 或 11
    • Packaging: Jar
  4. Dependencies中,添加我们初期需要的依赖:
    • Spring Web(构建Web应用)
    • MyBatis Framework(数据库ORM)
    • MySQL Driver(数据库连接)
    • Lombok(简化Java Bean代码,强烈推荐)

点击Finish,IDEA会自动下载依赖并创建项目。

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?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/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> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.5.3.1</version> <!-- 请使用最新稳定版 --> </dependency>

4.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 BaseMapper<User> { // 继承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 IService<User> { // 可以在此定义复杂的业务方法,不局限于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 ServiceImpl<UserMapper, User> implements UserService { @Override public User login(String username, String password) { // 1. 根据用户名查询用户 LambdaQueryWrapper<User> 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 Result<T> { private Integer code; // 状态码,如200成功,500失败 private String msg; // 提示信息 private T data; // 返回的数据 public static <T> Result<T> success(T data) { Result<T> result = new Result<>(); result.setCode(200); result.setMsg("操作成功"); result.setData(data); return result; } public static <T> Result<T> success(String msg, T data) { Result<T> result = new Result<>(); result.setCode(200); result.setMsg(msg); result.setData(data); return result; } public static <T> Result<T> error(String msg) { Result<T> 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-frontend

5.2 安装必要依赖除了创建时选择的,我们还需要安装UI库和HTTP请求库。

npm install element-ui axios --save # Element UI 是一套基于Vue的桌面端组件库,非常适合后台管理系统 # Axios 是一个基于Promise的HTTP库,用于发送请求

5.3 配置Element UI和Axiossrc/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.vue

<template> <div class="login-container"> <el-form ref="loginForm" :model="form" :rules="rules" class="login-form" label-width="80px"> <h2 class="title">鲜享超市管理系统</h2> <el-form-item label="用户名" prop="username"> <el-input v-model="form.username" placeholder="请输入用户名"></el-input> </el-form-item> <el-form-item label="密码" prop="password"> <el-input v-model="form.password" type="password" placeholder="请输入密码" @keyup.enter.native="handleLogin"></el-input> </el-form-item> <el-form-item> <el-button type="primary" @click="handleLogin" :loading="loading" style="width: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; } </style>

5.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 router

6. 前后端联调与运行验证

这是最关键的一步,确保前后端能正常通信。

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 初始化数据库与测试登录

  1. 重启后端服务,使CORS配置生效。
  2. 由于我们在application.yml中配置了ddl-auto: update,Spring Boot会自动根据User实体创建sys_user表。
  3. 我们需要手动插入一个测试用户。可以使用数据库工具,或编写一个简单的初始化SQL脚本。
-- 在MySQL的supermarket_db数据库中执行 INSERT INTO `sys_user` (`username`, `password`, `nickname`, `status`, `is_admin`) VALUES ('admin', MD5('123456'), '系统管理员', 1, 1);
  1. 打开浏览器,访问http://localhost:8081(或前端服务提示的地址),应该会自动跳转到登录页。
  2. 输入用户名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 BaseMapper<Product> { }
  • Service层ProductServiceProductServiceImpl(结构同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) { IPage<Product> page = new Page<>(pageNum, pageSize); LambdaQueryWrapper<Product> queryWrapper = new LambdaQueryWrapper<>(); if (!StringUtils.isEmpty(productName)) { queryWrapper.like(Product::getProductName, productName); } // 按创建时间倒序 queryWrapper.orderByDesc(Product::getCreateTime); IPage<Product> 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,实现一个包含查询、表格、新增、编辑、删除功能的页面。由于代码较长,这里给出核心思路和关键代码片段:

  1. router/index.js中配置路由
  2. 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. 常见问题与排查思路 (Q&A)

在开发过程中,你几乎一定会遇到下面这些问题。提前了解,能节省大量排查时间。

问题现象可能原因排查方式解决方案
后端启动失败,端口被占用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_modulespackage-lock.json,重新npm install。 3. 检查网络或配置npm镜像源。
前端访问后端API报404后端API路径错误、后端服务未启动、CORS未配置1. 检查浏览器开发者工具Network标签,看请求URL是否正确。 2. 确认后端控制台无报错且已启动。 3. 查看请求的Response Headers是否有Access-Control-Allow-Origin1. 核对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中添加&serverTimezone=Asia/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,写明项目介绍、技术栈、部署步骤。在关键代码处添加清晰的注释。

走到这里,你已经从一个“无从下手”的状态,变成了一个拥有完整全栈项目开发脉络的准开发者。这个“鲜享超市管理系统”项目骨架,已经具备了用户认证、商品管理等核心功能,并且采用了前后端分离、分层架构等现代开发模式。你可以在此基础上,继续添加库存管理、订单流程、数据统计图表等模块,最终形成一个丰满的毕业设计。

最重要的是,通过这个从零搭建的过程,你收获的不仅仅是一份可以运行的代码,而是一套解决同类问题的可复用方法论。下次再遇到新的业务需求,你就能清晰地知道:实体如何设计、接口如何划分、前后端如何协作、问题如何排查。这才是本篇文章希望带给你的,超越项目本身的核心价值。建议你将此项目作为基础,不断迭代和扩展,它完全有潜力成为你简历上的一个亮眼作品。