1. 这个项目到底能帮你解决什么问题?
如果你正在找一门能串联起 Java 后端和 Vue 前端的实战课,或者正为课程设计、毕业设计发愁,那么这个基于 Spring Boot 3 和 Vue 3 的超市管理系统,就是一个非常典型的“练手+交差”型项目。它最核心的价值,不是技术有多新潮,而是能让你在一个完整的、有业务逻辑的项目里,把学过的零散知识点串起来,最终得到一个能跑起来、有界面、有数据库交互的“作品”。
很多初学者学完 Spring Boot 和 Vue 的语法,一上手做项目就懵了:接口怎么设计?前端怎么调接口?权限怎么控制?数据怎么展示?这个超市管理系统,本质上就是提供了一个解决这些问题的标准答案和实现模板。它覆盖了用户登录、商品管理、库存管理、订单处理、收银结算等超市核心业务,你跟着做一遍,就能搞清楚一个典型的管理系统从数据库设计到前端展示的全链路流程。对于课程设计或毕业设计,它结构清晰、功能明确,老师一看就知道你做了什么,而且技术栈(Spring Boot 3 + Vue 3)也是当前企业里比较主流的组合,写在简历上或答辩时都很有说服力。
所以,别把它想得太复杂。它的目标就是让你“做得出来”,而不是追求极致的性能或架构。下面,我会按照从环境准备到功能实现的顺序,带你拆解这个项目,重点讲清楚每一步为什么要这么做,以及那些容易卡住你的“坑点”在哪里。
2. 动手前,先理清技术栈和本地环境
在开始敲代码之前,先把“战场”打扫干净。一个清晰的环境是项目能顺利跑起来的前提,很多“莫名其妙”的报错都源于环境问题。
2.1 核心技术栈与版本选择
这个项目主要涉及后端、前端和数据库三块。
后端 (Backend):
- 框架: Spring Boot 3.x。这是必须的,Spring Boot 2.x 和 3.x 在一些配置和依赖上有差异,直接用3能避免很多兼容性问题。
- 语言: Java 17 或更高版本。Spring Boot 3 最低要求 Java 17,建议直接安装 JDK 17 或 21。
- 构建工具: Maven 或 Gradle。教程通常用 Maven,如果你不熟悉,跟着用 Maven 就行。
- 数据库操作: MyBatis-Plus。这是一个国产的 MyBatis 增强工具,能极大简化单表 CRUD(增删改查)的代码量,对于管理系统这类表单操作多的场景非常友好。
- 数据库: MySQL 8.0。版本尽量用 8.0+,避免低版本(如5.7)的某些语法或驱动兼容问题。
- 其他常用依赖: Spring Security(权限控制)、JWT(令牌认证)、Lombok(简化实体类代码)、Hutool(工具集)等。这些不一定全部用到,但都是管理系统的常见选型。
前端 (Frontend):
- 框架: Vue 3.x。使用 Composition API 写法,这是 Vue 3 的主流写法,和 Vue 2 的 Options API 区别较大,需要适应。
- 构建工具: Vite。这比传统的 Vue CLI 更快、更轻量,是现在 Vue 项目的标配。
- UI 组件库: Element Plus。这是基于 Vue 3 的 Element UI 版本,组件丰富,文档齐全,能快速搭建出美观的管理后台界面。
- 状态管理: Pinia。这是 Vue 3 官方推荐的状态管理库,比 Vuex 更简洁。
- 路由: Vue Router 4.x。
- HTTP 客户端: Axios。用于调用后端接口。
- 开发工具: 建议使用 Visual Studio Code,并安装 Volar(Vue 3 官方推荐扩展)、ESLint、Prettier 等插件。
数据库 (Database):
- 本地安装 MySQL 8.0,并创建一个名为
supermarket的数据库(名字可以自定,记得在配置文件中修改)。 - 准备好数据库管理工具,如 Navicat、DBeaver 或 MySQL Workbench。
- 本地安装 MySQL 8.0,并创建一个名为
版本一致性的重要性:我建议你严格按照教程或项目初始代码中pom.xml和package.json里指定的版本号来安装依赖。自己随意升级版本,是项目启动失败最常见的原因之一。
2.2 本地环境检查清单
在拉取代码之前,先按这个清单过一遍:
- Java: 打开终端(CMD 或 PowerShell),输入
java -version,确认版本为 17+。 - Maven: 输入
mvn -v,确认已安装且版本不太旧。 - Node.js: 输入
node -v和npm -v,建议安装 Node.js 18+ 或 20+ LTS 版本。这是运行 Vue 和 npm 命令的基础。 - MySQL: 确保 MySQL 服务已启动,并能用 root 用户或其他有权限的用户登录。
- IDE/编辑器:
- 后端:IntelliJ IDEA(社区版即可)或 Eclipse。IDEA 对 Spring Boot 支持更好。
- 前端:Visual Studio Code。
- Git(可选但推荐):用于克隆项目代码。输入
git --version检查。
如果其中任何一项检查失败,先去官网下载安装。环境配置是第一步,也是最容易劝退的一步,耐心配好,后面会顺利很多。
3. 项目初始化与后端搭建(Spring Boot 3)
拿到项目代码(可能是 GitHub/Gitee 的仓库链接或压缩包)后,不要急着同时启动前后端。我建议的顺序是:先让后端跑起来,能连上数据库并返回简单的接口数据。
3.1 创建项目与导入
如果你是从头创建,可以用 Spring Initializr(start.spring.io)生成项目骨架。但作为课程设计,更常见的是直接使用现成的项目模板。这时,用 IDEA 直接打开项目根目录(包含pom.xml的文件夹)即可。
导入后第一件事:等待 Maven 下载依赖。IDEA 右下角会有进度条。网络不好可能导致依赖下载失败,如果一直卡住,可以检查 Maven 配置的镜像源是否为国内镜像(如阿里云镜像)。
3.2 核心配置文件详解
配置文件是后端项目的“开关总闸”,90%的启动错误都跟它有关。重点关注src/main/resources/application.yml(或application.properties)。
# 应用配置 server: port: 8080 # 后端服务启动端口 # 数据源配置 (重中之重!) spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver # MySQL 8 的驱动类 url: jdbc:mysql://localhost:3306/supermarket?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai username: root # 你的数据库用户名 password: your_password # 你的数据库密码 # 文件上传配置(如果涉及商品图片上传) servlet: multipart: max-file-size: 10MB max-request-size: 100MB # MyBatis-Plus 配置 mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 控制台打印SQL,调试用,生产环境去掉 global-config: db-config: id-type: auto # 主键策略,如数据库自增 logic-delete-field: deleted # 逻辑删除字段名(如果用了逻辑删除) logic-delete-value: 1 # 逻辑已删除值 logic-not-delete-value: 0 # 逻辑未删除值 # JWT 配置(如果用了JWT做认证) jwt: secret: your_jwt_secret_key_here # 密钥,务必修改成复杂字符串 expire: 604800 # 过期时间,单位秒,例如7天你必须修改的地方:
spring.datasource.url中的localhost:3306:确保是你的 MySQL 地址和端口。spring.datasource.username和password:改成你本地 MySQL 的登录凭据。jwt.secret:如果项目用了 JWT,这个密钥必须改,不要用默认值。
3.3 数据库与实体类映射
管理系统离不开数据库表。通常项目会提供 SQL 脚本来创建表。找到doc/或sql/目录下的.sql文件,在你的 MySQL 工具中执行它,创建所有表。
然后看代码中的实体类(Entity),例如User.java、Product.java。它们使用了 MyBatis-Plus 的注解(如@TableName,@TableId)来和数据库表字段映射。这是 ORM(对象关系映射)的核心。
import com.baomidou.mybatisplus.annotation.*; import lombok.Data; @Data // Lombok注解,自动生成getter, setter等方法 @TableName("sys_user") // 对应数据库表名 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; @TableField(fill = FieldFill.INSERT) // 插入时自动填充 private Date createTime; @TableField(fill = FieldFill.INSERT_UPDATE) // 插入和更新时自动填充 private Date updateTime; }理解这个映射关系:后端操作的是User这个 Java 对象,但 MyBatis-Plus 会帮你自动转换成对sys_user表的 SQL 操作。这避免了手写大量重复的 SQL。
3.4 编写第一个接口并测试
实体类有了,接下来是数据访问层(Mapper)、业务层(Service)和控制层(Controller)。这是经典的 MVC 三层架构。
- Mapper 接口:继承 MyBatis-Plus 的
BaseMapper,基本的 CRUD 方法就有了。import com.baomidou.mybatisplus.core.mapper.BaseMapper; @Mapper // 告诉Spring这是一个Mapper public interface UserMapper extends BaseMapper<User> { // 可以在这里定义自定义的复杂SQL方法 } - Service 接口和实现:封装业务逻辑。
public interface UserService extends IService<User> { // 定义业务方法,如登录、注册 User login(String username, String password); } @Service // Spring Service组件 public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService { @Override public User login(String username, String password) { // 1. 根据用户名查询用户 // 2. 比对密码(密码通常是加密存储的) // 3. 返回用户信息或抛出异常 } } - Controller:接收 HTTP 请求,调用 Service,返回 JSON 数据。
@RestController // 表明这是一个RESTful控制器,返回JSON @RequestMapping("/api/user") // 请求路径前缀 public class UserController { @Autowired private UserService userService; @PostMapping("/login") public Result login(@RequestBody LoginForm form) { // 调用userService.login // 成功则生成Token返回,失败返回错误信息 return Result.success("登录成功", token); } }
如何测试:启动 Spring Boot 应用(运行xxxApplication类的 main 方法),然后在浏览器或使用 API 测试工具(如Postman或Apifox)访问http://localhost:8080/api/user/login,传入 JSON 格式的用户名密码,看是否能收到预期的响应。
注意:第一次启动如果报“找不到主类”或“端口被占用”,检查你的启动类位置和
application.yml中的端口。如果报数据库连接错误,99%是配置文件里的数据库连接信息错了。
4. 前端项目搭建与页面开发(Vue 3 + Element Plus)
后端接口能通之后,再搞前端。前后端分离的项目,前端本质上就是一个独立的、能发起网络请求的网页应用。
4.1 创建 Vue 3 项目并安装核心依赖
如果你拿到的是完整项目,直接用 VSCode 打开前端目录(通常叫frontend或vue-project)。如果是自己创建,可以用 Vite:
npm create vue@latest # 按照提示选择项目名,并勾选需要的功能(Router, Pinia, ESLint等) cd your-project-name npm install然后,安装项目必需的 UI 库和工具库:
npm install element-plus axios pinia # 安装图标库(如果Element Plus图标不够用) npm install @element-plus/icons-vue # 安装Sass(如果需要) npm install sass -D关键配置:在main.js或main.ts中全局引入 Element Plus 和样式。
import { createApp } from 'vue' import App from './App.vue' import router from './router' import { createPinia } from 'pinia' // 引入Element Plus import ElementPlus from 'element-plus' import 'element-plus/dist/index.css' const app = createApp(App) app.use(createPinia()) app.use(router) app.use(ElementPlus) // 使用Element Plus app.mount('#app')4.2 理解前端项目结构
一个典型的管理系统前端目录结构如下,了解每个文件夹的作用能帮你快速定位代码:
src/ ├── api/ # 存放所有调用后端接口的函数(使用axios封装) ├── assets/ # 静态资源,如图片、字体 ├── components/ # 可复用的Vue组件,如搜索框、分页组件 ├── layout/ # 布局组件,如包含侧边栏和顶栏的主布局 ├── router/ # 路由配置,定义页面路径和组件的映射关系 ├── stores/ # Pinia状态管理,存储全局状态如用户信息 ├── utils/ # 工具函数,如时间格式化、请求封装 ├── views/ # 页面级组件,一个.vue文件对应一个页面 ├── App.vue # 根组件 └── main.js # 入口文件核心工作流:用户在views/Login.vue页面点击登录 -> 调用api/user.js中的login函数 -> 该函数使用axios发送请求到后端http://localhost:8080/api/user/login-> 收到响应后,将用户 Token 存入stores/user.js(Pinia) 和本地存储(localStorage) -> 通过router跳转到主页views/Home.vue。
4.3 开发一个典型页面:商品管理
我们以商品管理列表页为例,拆解前端如何与后端配合。
- 定义 API 接口(
src/api/product.js):import request from '@/utils/request' // 这是一个封装了axios的实例,通常加了基础URL和拦截器 export function getProductList(params) { // params 可能包含 pageNum, pageSize, productName 等查询条件 return request({ url: '/api/product/list', method: 'get', params }) } export function addProduct(data) { return request({ url: '/api/product', method: 'post', data // data是商品对象,如 {name: '可乐', price: 3.0, stock: 100} }) } - 编写页面组件(
src/views/product/ProductList.vue):<template> <div class="product-container"> <!-- 搜索和操作区域 --> <el-form :inline="true" :model="queryParams"> <el-form-item label="商品名称"> <el-input v-model="queryParams.productName" placeholder="请输入" /> </el-form-item> <el-form-item> <el-button type="primary" @click="handleQuery">搜索</el-button> <el-button @click="resetQuery">重置</el-button> <el-button type="success" @click="handleAdd">新增</el-button> </el-form-item> </el-form> <!-- 表格区域 --> <el-table :data="productList" style="width: 100%"> <el-table-column prop="id" label="ID" width="80" /> <el-table-column prop="name" label="商品名称" /> <el-table-column prop="categoryName" label="分类" /> <el-table-column prop="price" label="单价" /> <el-table-column prop="stock" label="库存" /> <el-table-column label="操作" width="200"> <template #default="scope"> <el-button size="small" @click="handleEdit(scope.row)">编辑</el-button> <el-button size="small" type="danger" @click="handleDelete(scope.row)">删除</el-button> </template> </el-table-column> </el-table> <!-- 分页组件 --> <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="queryParams.pageNum" :page-sizes="[10, 20, 50]" :page-size="queryParams.pageSize" layout="total, sizes, prev, pager, next, jumper" :total="total"> </el-pagination> <!-- 新增/编辑商品的对话框 --> <ProductDialog v-model="dialogVisible" :form-data="dialogForm" @success="handleDialogSuccess" /> </div> </template> <script setup> import { ref, reactive, onMounted } from 'vue' import { getProductList } from '@/api/product' import ProductDialog from './components/ProductDialog.vue' // 响应式数据 const productList = ref([]) const total = ref(0) const queryParams = reactive({ pageNum: 1, pageSize: 10, productName: '' }) const dialogVisible = ref(false) const dialogForm = ref({}) // 方法 const loadData = async () => { const res = await getProductList(queryParams) if (res.code === 200) { // 假设后端统一返回 {code: 200, data: {}, msg: 'success'} productList.value = res.data.list total.value = res.data.total } } const handleQuery = () => { queryParams.pageNum = 1 // 搜索时回到第一页 loadData() } const handleAdd = () => { dialogForm.value = {} // 清空表单 dialogVisible.value = true } const handleEdit = (row) => { dialogForm.value = { ...row } // 浅拷贝当前行数据 dialogVisible.value = true } const handleDialogSuccess = () => { dialogVisible.value = false loadData() // 操作成功后刷新列表 } // 生命周期钩子 onMounted(() => { loadData() }) </script> - 处理跨域问题:前端运行在
localhost:5173(Vite默认端口),后端在localhost:8080,浏览器会因同源策略阻止请求。解决方法是在vite.config.js中配置代理:
配置后,前端请求import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' export default defineConfig({ plugins: [vue()], server: { proxy: { '/api': { target: 'http://localhost:8080', // 后端地址 changeOrigin: true, // rewrite: (path) => path.replace(/^\/api/, '') // 如果后端接口本身没有/api前缀,可能需要重写 } } } })/api/product/list会被代理到http://localhost:8080/api/product/list。
页面开发要点:先画静态布局(用 Element Plus 组件),再绑定数据(ref,reactive),然后写方法调用接口,最后处理交互反馈(加载中、成功提示、错误提示)。一个功能一个功能地实现,不要想着一口吃成胖子。
5. 前后端联调与核心业务模块实现
前后端都跑起来后,真正的挑战在于“联调”——让它们像齿轮一样咬合起来。超市管理系统有几个核心模块,每个模块的联调重点不同。
5.1 用户认证与权限管理
这是系统的门户,也是最容易出错的地方。
登录流程:
- 前端:用户输入账号密码 -> 点击登录 -> 调用
/api/user/loginPOST 接口,发送{username: ‘admin‘, password: ‘123456’}。 - 后端:Controller 接收参数 -> Service 验证用户并生成 JWT Token -> 将 Token 返回给前端。
- 前端:收到 Token 后,存入 Pinia Store和
localStorage(或sessionStorage)。存两份的原因:Pinia 状态在页面刷新后会丢失,而localStorage是持久的,可以用来初始化 Pinia。 - 前端:在
axios的请求拦截器中,自动为后续每一个请求的 Header 加上Authorization: Bearer ${token}。 - 后端:在需要权限的接口上,通过拦截器或过滤器(如 Spring Security 的
JwtAuthenticationFilter)校验 Token 的有效性。
- 前端:用户输入账号密码 -> 点击登录 -> 调用
常见坑点:
- 密码传输:前端应对密码进行 MD5/SHA 或 RSA 加密后再传输,后端存储的也是加密后的密文。绝对不要明文传输和存储。
- Token 过期:前端需要在响应拦截器中判断,如果后端返回
401(未授权)或403(禁止访问),则跳转回登录页。 - 路由守卫:使用 Vue Router 的
beforeEach钩子,检查用户是否已登录(检查 Pinia 或 localStorage),未登录则跳转到登录页,防止直接输入 URL 进入内部页面。
5.2 商品与库存管理
这是业务核心,涉及大量的表单和表格操作。
商品增删改查(CRUD):这是最基础的操作。前端用 Element Plus 的
el-dialog和el-form做弹窗表单,用el-table展示列表。后端对应 Controller 提供POST /api/product(新增)、PUT /api/product/{id}(更新)、DELETE /api/product/{id}(删除)、GET /api/product/list(查询)等接口。库存管理:
- 入库:创建一个“采购入库”或“库存调整”功能。前端表单包含商品选择、数量、操作类型(入库/出库)、备注。后端接口需要事务操作:1. 在
inventory_log(库存流水表)插入一条记录;2. 更新product表的stock字段。这两步必须在同一个事务里,保证数据一致性。 - 库存预警:在商品列表或单独页面,用不同颜色(如红色)标记库存低于安全库存的商品。这通常是在查询商品列表时,SQL 中加上
where stock < safe_stock条件,或者前端拿到数据后过滤显示。
- 入库:创建一个“采购入库”或“库存调整”功能。前端表单包含商品选择、数量、操作类型(入库/出库)、备注。后端接口需要事务操作:1. 在
联调技巧:
- 先用 Postman 单独测试每一个后端接口,确保其逻辑和返回数据正确。
- 前端调用时,在浏览器开发者工具的Network面板中,仔细查看请求的Payload(发送的数据)和响应的Preview/Response。很多问题都是数据格式不对(比如日期格式、数字和字符串混淆)。
- 对于文件上传(商品图片),前端使用
<el-upload>组件,后端使用MultipartFile接收,并处理好文件存储路径(存到服务器本地或云存储),将访问 URL 存回数据库。
5.3 订单与收银模块
这是最体现业务流程复杂性的地方。
- 购物车/订单生成:
- 前端维护一个本地购物车(可以用 Pinia Store)。
- 点击结算时,将购物车商品列表、总价、收货信息(如果是线上)提交到后端
/api/order/create。 - 后端 Service 需要处理更复杂的事务:
- 检查库存是否充足(遍历商品列表,查询当前库存)。
- 扣减库存(同样需要事务,避免超卖)。
- 生成订单主表(
order)记录和订单明细表(order_item)记录。 - 可能还需要调用支付接口(如果是课程设计,可以模拟支付成功)。
- 收银台界面:对于线下超市系统,收银界面需要更实时和快捷。可以考虑:
- 使用 WebSocket 实现前后端实时通信,同步价格变动或促销信息。
- 前端界面设计要简洁,支持扫码枪输入商品编码,快速累加。
- 重点优化“挂单”、“取单”、“会员折扣”、“多种支付方式(现金、扫码)”等功能的交互逻辑。
数据一致性是生命线:凡是涉及“查询再更新”的操作,比如下单扣库存,在高并发下会出问题。课程设计虽然不要求应对高并发,但你要知道这个原理,并在代码中体现“事务”和“乐观锁”(例如使用数据库的version字段或update ... where stock > 0)的思想。
6. 项目部署、答辩准备与避坑指南
把项目在本地跑通只是第一步,要让老师或答辩评委看到成果,还需要完成“最后一公里”。
6.1 基础部署:让项目能在服务器上跑起来
课程设计通常不要求复杂的 Docker 容器化部署,但至少要做到能打包,并在一个干净的环境里启动。
后端打包:
- 在项目根目录执行
mvn clean package(Maven)或./gradlew bootJar(Gradle)。 - 在
target/目录下会生成一个xxx-0.0.1-SNAPSHOT.jar文件。 - 将这个 jar 包上传到服务器(或你演示用的另一台电脑)。
- 确保目标机器安装了相同版本的 Java。
- 在 jar 包所在目录,执行
java -jar xxx-0.0.1-SNAPSHOT.jar。可以通过--server.port=9090参数修改端口。 - 关键点:生产环境的数据库配置(
application-prod.yml)要和本地开发环境(application-dev.yml)分开。打包时通过-Dspring.profiles.active=prod指定使用生产配置。
- 在项目根目录执行
前端打包与部署:
- 在前端目录执行
npm run build。这会在dist目录生成静态文件(HTML, JS, CSS)。 - 部署有两种常见方式:
- 方式一:单独部署。将
dist文件夹里的所有文件,放到 Nginx 或 Apache 等 Web 服务器的目录下。同时,在 Nginx 配置中,将/api路径的请求代理到后端服务地址(解决跨域和请求转发)。 - 方式二:合并部署。将
dist文件夹里的所有文件,复制到 Spring Boot 项目的src/main/resources/static目录下,然后重新打包后端。这样访问后端端口,就能直接看到前端页面。这种方式更简单,适合演示。
- 方式一:单独部署。将
- 在前端目录执行
6.2 课程设计/毕业设计文档与答辩要点
代码跑通只占一半分数,清晰的文档和讲解同样重要。
必备文档:
- 需求分析说明书:简要说明超市管理系统要解决哪些问题(进货、销售、库存、人员管理)。
- 系统设计说明书:包括架构图(前后端分离)、功能模块图、数据库 E-R 图、核心表结构设计。
- 部署说明文档:写清楚运行本项目所需的环境(JDK, Node, MySQL 版本)、如何导入数据库、如何修改配置、如何启动前后端。这份文档要详细到让一个完全没接触过这项目的人也能按步骤跑起来。
- 用户使用手册:用截图配文字,说明每个功能怎么用。
- 源代码:整理干净的工程文件夹。
答辩演示准备:
- 准备一个稳定的演示环境:最好在答辩用的电脑上提前部署好,避免现场配置网络、数据库导致失败。也可以录屏作为备用。
- 设计演示脚本:不要漫无目的地点击。按一个完整的业务流程走,例如:“管理员登录 -> 新增一个商品 -> 进行采购入库增加库存 -> 模拟顾客在前台选购商品生成订单 -> 进行收银结算 -> 查看订单和库存变化”。这个过程能串联起大部分核心功能。
- 准备技术问答:
- 为什么用 Spring Boot 和 Vue 3?答:Spring Boot 简化了传统 Spring 的配置,能快速构建后端服务;Vue 3 是当前主流的前端框架,响应式系统更高效,生态丰富。
- 前后端怎么交互的?答:通过 RESTful API,前端用 Axios 发起 HTTP 请求,后端返回 JSON 数据。
- 用户密码怎么存的?答:前端加密后传输,后端使用 BCrypt 等不可逆算法加密后存入数据库,从不存储明文。
- 如何处理多人同时操作一个商品库存?答:在扣减库存的 SQL 语句中使用条件判断(如
update product set stock = stock - 1 where id = ? and stock > 0),并结合数据库事务,防止超卖。
6.3 开发与部署中的常见“坑”及排查思路
后端启动报错:
Failed to configure a DataSource- 原因:Spring Boot 找不到数据库配置,或配置错误。
- 排查:检查
application.yml中spring.datasource下的url,username,password。确认数据库服务是否启动,数据库名是否存在,用户是否有权限。
前端运行报错:
Cannot find module ‘xxx‘或Uncaught TypeError: xxx is not a function- 原因:依赖未安装或版本冲突。
- 排查:删除
node_modules文件夹和package-lock.json文件,重新执行npm install。检查package.json中依赖的版本号。
接口调用报 404 (Not Found)
- 原因:前端请求的 URL 不对,或后端没有对应的
@RequestMapping。 - 排查:
- 看浏览器 Network 面板,请求的完整 URL 是什么。
- 核对后端 Controller 类上的
@RequestMapping(“/api/user”)和方法上的@PostMapping(“/login”),拼起来是否是/api/user/login。 - 检查后端应用是否成功启动(看控制台日志)。
- 原因:前端请求的 URL 不对,或后端没有对应的
接口调用报 500 (Internal Server Error)
- 原因:后端代码运行时出错(空指针、数据库异常等)。
- 排查:这是最需要关注的错误。第一时间看后端控制台日志,错误堆栈信息会明确指出哪一行代码出了问题。常见原因:SQL 语法错误、传入参数为 null、字段类型不匹配。
前端页面空白或样式错乱
- 原因:JS 报错导致渲染中断,或 CSS/组件库未正确引入。
- 排查:打开浏览器开发者工具的Console面板,看是否有红色错误信息。打开Elements面板,看组件是否正常渲染。检查
main.js中是否正确引入了 Element Plus 的 CSS 文件。
打包后运行,前端访问不到后端接口
- 原因:开发时配置的代理(vite.config.js)在打包后失效。生产环境前端和后端是独立的服务,存在跨域。
- 解决:生产环境不能用开发服务器的代理。有两种方案:1) 将前端和后端部署在同一个域名下(如用 Nginx 反向代理,将
/指向前端,将/api/指向后端)。2) 后端配置允许跨域(CORS),在前端代码中,将请求的 BaseURL 直接改为后端生产环境的绝对地址。
这个项目麻雀虽小,五脏俱全。把它完整做下来,你不仅能得到一个可以展示的作品,更能把 Spring Boot 和 Vue 3 的开发流程、前后端协作模式、常见问题排查方法实实在在地走一遍。这比单纯看教程要深刻得多。遇到报错别慌,按照“看日志、查配置、搜错误信息”的顺序,大部分问题都能解决。