三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

SpringBoot+Vue3前后端分离项目实战:从零搭建美食网站

SpringBoot+Vue3前后端分离项目实战:从零搭建美食网站

1. 这个项目到底能帮你解决什么问题?

如果你正在找一份能跑起来、代码结构清晰、前后端分离的 SpringBoot + Vue3 项目,用来学习、做毕业设计或者丰富简历,那这个“美食网站”项目就是一个非常典型的起点。它不是什么高深莫测的架构,核心就是围绕“增删改查”这个基础但至关重要的能力,把前后端分离的开发流程走一遍。

很多人学框架时,看官方文档和零散教程,知识点是割裂的。这个项目的价值在于,它把这些知识点串成了一个可运行、可观察的系统。你拿到源码后,两小时内能搭建起来,看到页面,操作数据,感受从浏览器点击到数据库更新再回到页面的完整链路。这对于理解“前后端分离”到底是怎么工作的,比看十篇概念文章都管用。

项目本身是“美食网站”,但它的骨架——用户管理、菜品信息管理、分类管理、订单管理——换套皮肤和业务逻辑,就能变成博客、商城、OA系统。所以,别只盯着“美食”,要关注它如何组织代码、如何定义接口、前端如何调用、后端如何处理数据、权限怎么控制。这些才是你简历上和面试中能讲出来的“实战经验”。

2. 动手之前,先理清环境和思路

在下载代码和打开 IDE 之前,先花五分钟确认你的“作战地图”。盲目开跑,大概率会卡在环境配置上。

2.1 你需要准备什么?

硬件要求不高,但软件版本是关键。版本不匹配是新手踩坑的重灾区。

后端 (SpringBoot) 环境:

  • JDK:版本 8 或 11。推荐 JDK 11,兼容性和社区支持都更好。用java -version命令确认。
  • 构建工具:Maven 3.6+ 或 Gradle。项目大概率是 Maven,确保mvn -v能运行,并且配置了国内镜像源(如阿里云镜像)以加速依赖下载。
  • IDE:IntelliJ IDEA (社区版或旗舰版) 或 Eclipse (需安装 Spring Tools)。IDEA 对 SpringBoot 支持更友好。
  • 数据库:MySQL 5.7 或 8.0。确保已安装并启动服务,记住 root 密码(或你有权限的账号密码)。
  • 其他:可能需要 Redis(用于缓存或会话管理),根据项目pom.xmlapplication.yml判断。

前端 (Vue3) 环境:

  • Node.js:版本 16.x 或 18.x。不要用太老或太新的版本。用node -vnpm -v确认。
  • 包管理器:npm 或 yarn。通常 npm 随 Node.js 安装。
  • IDE:Visual Studio Code 是主流选择,轻量且插件丰富。

核心思路:前后端分离项目,后端提供 API 接口,前端通过 HTTP 请求调用。所以你的搭建顺序应该是:配数据库 -> 启动后端 -> 启动前端。后端启动成功,接口能访问,前端才能正常工作。

2.2 源码结构预览

拿到源码压缩包后,先解压,看目录结构。一个典型的结构可能如下:

food-project/ ├── backend/ # SpringBoot 后端项目 │ ├── src/ │ ├── pom.xml # Maven 依赖管理 │ └── application.yml # 核心配置文件,数据库连接在这里改! ├── frontend/ # Vue3 前端项目 │ ├── src/ │ ├── package.json # 前端依赖管理 │ └── vue.config.js # 前端配置文件,如代理设置 └── sql/ # 数据库初始化脚本 └── food_db.sql

关键文件解读:

  1. backend/application.yml:这是后端的“大脑”。你需要修改spring.datasource下的urlusernamepassword,让它指向你的本地 MySQL。
  2. sql/food_db.sql:在启动后端前,先在 MySQL 中执行这个 SQL 文件,创建数据库和表结构,并插入初始数据(如管理员账号)。
  3. frontend/package.json:查看scripts部分,通常npm run servenpm run dev用于启动开发服务器。
  4. frontend/vue.config.js:如果前端需要调用后端接口,这里可能会配置devServer.proxy来解决开发时的跨域问题。

3. 从零到一:让项目在你的机器上跑起来

现在,我们按照标准流程,一步步启动项目。我建议你严格按这个顺序操作,并观察每个步骤的日志输出。

3.1 第一步:初始化数据库

这是最基础,也最容易出错的一步。

  1. 打开你的 MySQL 客户端(命令行、Navicat、Workbench 等)。
  2. 创建一个新的数据库,名字根据application.yml里的配置来,比如food_db
    CREATE DATABASE IF NOT EXISTS `food_db` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  3. 使用这个数据库:USE food_db;
  4. 执行sql/food_db.sql文件中的所有 SQL 语句。这会创建表并插入初始数据。
  5. 执行完后,查看一下是否有userdish(菜品)、category(分类)等表生成,并确认user表里有一条初始的管理员账号记录(用于登录)。

注意:如果执行 SQL 报错,常见原因是 SQL 语法与你的 MySQL 版本不兼容(如反引号、关键字),或者字符集设置问题。可以尝试用文本编辑器打开 SQL 文件,检查并简单修改。

3.2 第二步:配置并启动 SpringBoot 后端

后端是服务的核心,先确保它能独立运行。

  1. 用 IDEA 打开backend文件夹。IDEA 会自动识别为 Maven 项目并开始下载依赖(观察右下角进度条)。
  2. 打开src/main/resources/application.yml
  3. 找到数据库配置部分,修改成你的本地信息:
    spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/food_db?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai username: root # 你的数据库用户名 password: your_password # 你的数据库密码
  4. 检查其他配置,如server.port(后端服务端口,默认可能是 8080),redis配置(如果用到)。
  5. 找到主启动类(通常叫FoodApplicationApplication,带有@SpringBootApplication注解)。
  6. 右键点击这个类,选择Run ‘FoodApplication‘
  7. 观察控制台日志:这是最重要的环节。成功的日志会显示:
    • Tomcat started on port(s): 8080
    • Started FoodApplication in X.XXX seconds
    • 没有持续的、导致进程停止的 ERROR 日志。
  8. 验证:打开浏览器,访问http://localhost:8080(或你配置的端口)。如果看到 Whitelabel Error Page 或简单的 JSON 错误,这是正常的,说明后端服务已经启动,只是没有定义根路径的接口。更专业的验证是访问其内置的接口文档(如果集成了 Swagger),比如http://localhost:8080/swagger-ui.htmlhttp://localhost:8080/doc.html

常见启动失败原因:

  • 数据库连接失败:检查application.yml配置、MySQL 服务是否启动、用户名密码是否正确、数据库名是否存在。
  • 端口被占用:修改server.port为其他端口,如 8081。
  • 依赖下载失败:检查 Maven 镜像源,或尝试在 IDEA 中右键pom.xml->Maven->Reload project
  • JDK 版本不匹配:在 IDEA 的Project Structure中确认项目使用的 JDK 版本。

3.3 第三步:配置并启动 Vue3 前端

后端 API 服务就绪后,前端才能正常获取数据。

  1. 用 VS Code 打开frontend文件夹。
  2. 打开终端(Terminal),确保路径在前端项目根目录下。
  3. 安装依赖:npm installcnpm install(如果你用了淘宝镜像)。这个过程会下载node_modules,耐心等待。
  4. 检查vue.config.js文件。关键看devServer.proxy配置,它定义了前端开发服务器将 API 请求代理到哪个后端地址。通常配置如下:
    module.exports = { devServer: { port: 80, // 前端开发服务器端口,如 80 proxy: { '/api': { // 以 /api 开头的请求会被代理 target: 'http://localhost:8080', // 你的后端地址 changeOrigin: true, pathRewrite: { '^/api': '' // 重写路径,去掉 /api 前缀(根据后端接口实际情况调整) } } } } }
    这意味着,前端代码里请求/api/user/login,实际上会被转发到http://localhost:8080/user/login
  5. 启动前端开发服务器:npm run servenpm run dev
  6. 终端会输出访问地址,通常是http://localhost:80http://localhost:8081。用浏览器打开这个地址。
  7. 如果页面成功加载,出现登录页或主页,恭喜你,项目基本跑通了。

前端启动常见问题:

  • npm install报错:网络问题或 Node.js 版本问题。尝试使用npm cache clean --force后重试,或切换 npm 源 (npm config set registry https://registry.npmmirror.com)。
  • 页面能打开但接口报 404:检查vue.config.js中的proxy配置,确保target指向正确的、正在运行的后端地址和端口。可以在浏览器开发者工具的Network面板查看请求详情。
  • 页面空白或控制台有 JS 错误:可能是依赖版本冲突。尝试删除node_modulespackage-lock.json,重新npm install

4. 深入核心:理解并操作“增删改查”

项目跑起来只是第一步,理解其代码实现才能转化为你的能力。我们以最经典的“菜品管理”模块为例,拆解前后端如何协作完成 CRUD。

4.1 后端 API 层剖析

在后端项目中,找到菜品相关的 Controller、Service、Mapper 和实体类。

  1. 实体类 (Entity/Domain):Dish.java。它定义了菜品的属性(id, name, price, categoryId, status 等),并与数据库表字段映射(通常使用 JPA 注解或 MyBatis 的映射)。
  2. 数据访问层 (Mapper/Repository):DishMapper.java。这里定义了数据库操作方法。如果使用 MyBatis,你会看到@Mapper注解和对应的 XML 文件(在resources/mapper下),里面是具体的 SQL 语句。如果使用 JPA 或 MyBatis-Plus,方法定义会更简洁。
  3. 业务逻辑层 (Service):DishService.javaDishServiceImpl.java。这里包含业务规则,比如新增菜品前检查名称是否重复,删除菜品前检查是否被订单关联。Service 调用 Mapper 来操作数据。
  4. 控制层 (Controller):DishController.java。这是对外的 HTTP 接口。你会看到类似下面的代码:
    @RestController @RequestMapping("/dish") public class DishController { @Autowired private DishService dishService; @GetMapping("/list") public Result list(DishQuery query) { // 查询列表,可能带分页和条件 PageInfo<DishVO> pageInfo = dishService.list(query); return Result.success(pageInfo); } @PostMapping public Result add(@RequestBody Dish dish) { // 新增 dishService.save(dish); return Result.success(); } @PutMapping public Result update(@RequestBody Dish dish) { // 更新 dishService.updateById(dish); return Result.success(); } @DeleteMapping("/{id}") public Result delete(@PathVariable Long id) { // 删除 dishService.removeById(id); return Result.success(); } }
    • @GetMapping@PostMapping@PutMapping@DeleteMapping对应 HTTP 方法的 GET, POST, PUT, DELETE。
    • @RequestBody表示接收 JSON 格式的请求体。
    • @PathVariable表示从 URL 路径中获取参数。
    • 返回的Result对象是一个包装类,通常包含codemsgdata字段,用于统一接口响应格式。

4.2 前端请求层与页面交互

在前端项目中,找到菜品管理的页面组件(如src/views/dish/index.vue)和对应的 API 请求文件(如src/api/dish.js)。

  1. API 请求封装:dish.js中,你会看到使用axios封装的函数。
    import request from '@/utils/request' // 通常是一个配置了拦截器的 axios 实例 export function getDishList(params) { return request({ url: '/dish/list', method: 'get', params // GET 请求参数 }) } export function addDish(data) { return request({ url: '/dish', method: 'post', data // POST 请求体 }) }
  2. 页面组件调用:在 Vue 组件中,引入这些 API 函数,并在生命周期钩子(如onMounted)或事件处理函数中调用。
    <script setup> import { ref, onMounted } from 'vue' import { getDishList, deleteDish } from '@/api/dish' const tableData = ref([]) // 加载列表 const loadData = async () => { const res = await getDishList({ page: 1, size: 10 }) tableData.value = res.data.list } // 删除操作 const handleDelete = async (id) => { // 先弹窗确认 await deleteDish(id) // 删除成功后,重新加载列表或提示 loadData() } onMounted(() => { loadData() }) </script>
  3. 页面渲染与事件绑定:模板部分会使用tableData渲染表格,并将删除按钮的点击事件绑定到handleDelete方法。

前后端数据流闭环:用户点击前端删除按钮 -> 前端调用deleteDish(id)-> 发送DELETE /dish/{id}请求到后端(通过代理)-> 后端DishController.delete()接收请求 -> 调用DishService.removeById(id)-> 调用DishMapper.deleteById(id)执行 SQL -> 数据库记录被删除 -> 后端返回成功结果 -> 前端接收到成功响应,刷新列表或给出提示。

走通这个闭环,你就真正理解了前后端分离开发的基本模式。

5. 从“能跑”到“能用”:项目改造与深度探索

把默认项目跑起来只是完成了 30%。剩下的 70% 在于你如何基于它进行探索和改造,让它变成你自己的经验。

5.1 如何进行二次开发?

  1. 修改现有功能:

    • 增加字段:Dish实体类中加一个description(描述)字段。然后需要:
      • 修改数据库表结构(执行 ALTER TABLE 语句)。
      • 修改后端:实体类、Mapper(或 XML)、Service、Controller、DTO/VO。
      • 修改前端:表单模型、表格列、API 请求和接收的数据结构。
    • 改变业务逻辑:比如删除菜品时,如果该菜品已有销量,则不允许删除,改为下架。这需要修改DishService.delete方法,加入业务判断。
  2. 增加新模块:

    • 模仿现有“菜品管理”模块的代码结构,创建一个“评论管理”模块。
    • 步骤:设计数据库表 -> 创建实体类 -> 创建 Mapper -> 创建 Service -> 创建 Controller -> 定义前端 API -> 创建前端页面组件 -> 配置路由。
    • 这个过程能强制你理解整个项目的架构和文件组织方式。
  3. 集成第三方功能:

    • 文件上传:学习如何在 SpringBoot 中处理MultipartFile,并集成 OSS(对象存储)如阿里云 OSS 或 MinIO。
    • 权限控制:项目可能使用了简单的拦截器或基础的权限注解。你可以尝试集成更完整的权限框架,如 Spring Security + JWT,理解认证和授权的流程。
    • 接口文档:如果项目没有 Swagger,可以自己集成knife4j,为 API 生成漂亮的文档。

5.2 项目亮点提炼与面试准备

当你对这个项目足够熟悉后,需要提炼出能写在简历上和面试中讲出来的点:

  • 技术栈:SpringBoot 2.x, Vue 3 + Composition API, Element Plus, Axios, MyBatis/MyBatis-Plus, MySQL。
  • 核心实现:
    • 实现了前后端完全分离,通过 RESTful API 进行数据交互。
    • 前端使用 Vue Router 管理路由,Pinia/Vuex 进行状态管理(如果用了)。
    • 后端采用 MVC 分层架构,全局统一异常处理和响应封装。
    • 使用 MyBatis 动态 SQL 构建灵活的条件查询。
    • 实现了基于 Token 或 Session 的用户认证与权限拦截。
  • 遇到的问题与解决:
    • 跨域问题:通过配置后端@CrossOrigin注解或前端vue.config.jsproxy解决。
    • 前后端数据格式对接:明确了日期时间等字段使用字符串传输(如yyyy-MM-dd HH:mm:ss)还是时间戳。
    • 分页查询性能:在数据量大时,深入理解了数据库分页(LIMIT)的优化,以及 MyBatis-Plus 分页插件的使用。
    • 重复提交问题:在前端按钮添加 loading 状态,或后端接口做幂等性处理。

6. 避坑指南与进阶思考

最后,分享几个我多次搭建此类项目后总结的经验,能帮你节省大量排查时间。

  1. 环境问题永远是第一嫌疑犯:项目跑不起来,90% 的问题出在环境。JDK版本、MySQL版本、Node版本、Maven镜像、npm 源。严格按照项目推荐的版本号来,能避免绝大多数玄学问题。
  2. 先单点测试,再整体联调:不要一上来就前后端一起跑。先用 Postman 或浏览器直接调用后端接口(如GET http://localhost:8080/dish/list),确保后端 API 本身是通的、返回数据格式是正确的。然后再去调试前端。
  3. 善用开发者工具:前端调试,浏览器 F12 的Network面板是你的眼睛。看请求是否发出、URL 是否正确、请求参数和响应数据是什么。Console面板看 JS 错误。
  4. 关注日志:后端控制台日志、前端终端日志、MySQL 的 general log(如果需要)。错误信息通常就藏在里面。
  5. 理解“约定大于配置”:SpringBoot 和 Vue CLI 帮你省了很多配置,但你也需要知道它们的默认约定是什么。比如 SpringBoot 默认从application.yml读取配置,Vue 的@别名指向src目录。
  6. 关于“若依”(RuoYi)等框架:搜索热词里出现了“若依框架前后端分离”。若依是一个功能非常丰富的开源权限管理系统。你现在搭建的这个“美食网站”可以看作是一个简化版、教学版的若依核心部分。如果你把这个项目吃透了,再去学习若依,会更容易理解其复杂的模块设计和权限模型。反之,如果直接上手若依,可能会被其庞大的代码量吓到。

这个“美食网站”项目,本质上是一个“教学模具”。它的价值不在于功能多强大,而在于结构清晰、技术栈主流、流程完整。把它当作你进入 SpringBoot + Vue3 全栈开发世界的第一块跳板,亲手敲一遍,改一改,踩几个坑再爬出来,你的收获会比单纯下载十套源码大得多。

← 返回列表