SpringBoot3+Vue3全栈博客项目实战:从零到部署的企业级开发指南
这次我们来看一个基于 SpringBoot3 和 Vue3 的个人博客管理项目。这是一个企业级实战项目从环境搭建、功能开发到部署上线手把手带你敲出完整代码。对于想学习全栈开发、构建个人作品集甚至为面试大厂做准备的朋友来说这是一个非常扎实的练手项目。项目提供了完整的源码和配套笔记技术栈选用了当前企业开发中最主流的 SpringBoot3 和 Vue3 组合。这意味着你学到的不仅是功能实现更是符合现代开发规范的最佳实践。本文将带你从零开始完成项目的本地环境搭建、核心功能开发、前后端联调并最终部署运行。无论你是刚学完基础想找项目练手还是希望深入理解前后端分离架构这篇文章都能提供清晰的路径。1. 核心能力速览在深入代码之前我们先快速了解这个项目的核心特性和它能为你带来的价值。能力项说明项目类型个人博客内容管理系统 (CMS)技术栈后端SpringBoot3 MyBatis-Plus MySQL前端Vue3 TypeScript Element Plus Vite核心功能用户认证、文章管理增删改查、分类标签、评论互动、文件上传、数据统计开发模式前后端分离基于 RESTful API 进行数据交互部署方式支持本地开发运行也可打包为 JAR 和静态资源进行部署学习目标掌握企业级项目结构、前后端协作流程、常见业务功能实现、项目部署资源包含完整可运行源码、数据库脚本、详细开发笔记2. 适用场景与使用边界这个项目适合哪些人又能解决什么问题适合人群Java 后端学习者希望将 SpringBoot 理论知识应用于实战理解控制器、服务层、数据访问层的设计与协作。Vue 前端开发者想学习如何使用 Vue3 的 Composition API、Pinia 状态管理、以及如何与后端 API 对接。全栈开发入门者渴望体验从数据库设计、接口开发到前端页面渲染的完整流程构建自己的第一个全栈项目。求职面试准备者需要一个结构清晰、技术栈主流、功能完整的项目作为个人作品丰富简历。能解决的核心问题知识串联将分散的 SpringBoot、Vue、MySQL 知识点串联成一个可运行的系统。工程化实践学习如何组织项目结构、管理依赖、编写可维护的代码。业务逻辑实现通过实现博客的核心业务如文章发布、评论理解典型业务场景下的开发思路。部署上线了解如何将开发完成的项目打包并部署到服务器完成从开发到上线的闭环。使用边界与注意学习目的本项目主要面向学习和实践源码和笔记可用于个人学习、毕业设计参考。版权与商用请注意直接用于商业用途可能涉及版权问题。建议在理解其设计思想后根据自身业务需求进行重构和创新。生产环境作为学习项目其在安全性、性能优化、高可用等方面可能未达到生产级要求。若用于生产需进行全面的安全审计、压力测试和代码优化。3. 环境准备与前置条件开始编码前请确保你的开发环境已就绪。以下是必需的软件和工具清单Java 开发环境JDK 17 或更高版本SpringBoot3 需要 JDK 17。推荐使用 OpenJDK 或 Oracle JDK。验证命令打开终端输入java -version和javac -version确认版本号。Node.js 与 npmNode.js 18用于运行 Vue3 项目和包管理。验证命令在终端输入node -v和npm -v。开发工具后端 IDEIntelliJ IDEA (推荐) 或 Eclipse。前端 IDEVisual Studio Code (推荐) 或 WebStorm。数据库工具Navicat、DBeaver 或 MySQL Workbench。数据库MySQL 8.0确保已安装并启动 MySQL 服务。创建数据库需要提前创建一个空的数据库例如my_blog。版本控制Git用于克隆项目源码和管理代码版本。构建工具Maven 3.6用于管理 Java 项目依赖和构建。IDEA 通常内置。浏览器Chrome 或 Edge用于前端调试和访问。环境检查清单[ ] JDK 17 已安装并配置环境变量。[ ] Node.js 18 和 npm 已安装。[ ] MySQL 8.0 服务正在运行并拥有 root 或具有足够权限的用户。[ ] 开发工具IDEA, VSCode已准备就绪。[ ] Git 已安装。4. 项目初始化与数据库搭建拿到源码后第一步是将其导入开发环境并初始化数据库。4.1 获取项目源码假设你已经通过提供的链接下载或克隆了项目源码。项目结构通常如下blog-backend/ # SpringBoot 后端项目 ├── src/ ├── pom.xml └── application.yml blog-frontend/ # Vue3 前端项目 ├── src/ ├── package.json └── vite.config.ts docs/ # 项目笔记或文档 sql/ # 数据库初始化脚本 README.md # 项目说明使用 IDEA 打开blog-backend文件夹使用 VSCode 打开blog-frontend文件夹。4.2 导入后端项目并配置依赖在 IDEA 中打开后端项目后Maven 会自动下载依赖pom.xml中定义。请确保网络通畅。主要依赖包括spring-boot-starter-web: Web 开发spring-boot-starter-data-jdbc: 数据访问mybatis-plus-boot-starter: MyBatis 增强工具mysql-connector-j: MySQL 驱动spring-boot-starter-security或jjwt: 安全与认证如果项目包含lombok: 简化实体类编写4.3 配置数据库连接找到后端项目的配置文件通常是src/main/resources/application.yml或application.properties。根据你的 MySQL 设置进行修改spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/my_blog?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai username: root password: your_password # 替换为你的数据库密码 # MyBatis-Plus 配置 mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 控制台输出SQL开发时开启 global-config: db-config: logic-delete-field: deleted # 全局逻辑删除字段名如果使用 logic-delete-value: 1 logic-not-delete-value: 04.4 执行数据库脚本在sql/目录下找到数据库初始化脚本如init.sql。使用你的数据库工具连接到my_blog数据库并执行该脚本。脚本通常会创建以下核心表user: 用户表article: 文章表category: 分类表tag: 标签表comment: 评论表article_tag: 文章-标签关联表执行成功后刷新数据库应能看到创建的表结构。5. 后端启动与核心功能剖析配置完成后我们来启动后端服务并理解其核心模块。5.1 启动 SpringBoot 应用在 IDEA 中找到主启动类通常命名为BlogApplication或Application其路径类似com.yourname.blog.BlogApplication。右键点击该类选择Run ‘BlogApplication‘。观察控制台日志如果没有报错并看到类似以下的输出说明启动成功Tomcat started on port(s): 8080 (http) Started BlogApplication in 5.123 seconds (process running for 5.456)此时SpringBoot 内嵌的 Tomcat 服务器已在http://localhost:8080上运行。5.2 项目结构解析一个典型的企业级 SpringBoot 项目会采用分层架构src/main/java/com/yourname/blog/ ├── config/ # 配置类如Web配置、安全配置、MyBatisPlus配置 ├── controller/ # 控制器层接收请求返回响应 ├── service/ # 业务逻辑层 │ └── impl/ # 业务逻辑实现类 ├── mapper/ # 数据访问层MyBatis Mapper接口 ├── entity/ # 实体类与数据库表对应 ├── dto/ # 数据传输对象用于前后端交互 ├── vo/ # 视图对象用于封装返回给前端的数据 └── utils/ # 工具类如JWT工具、加密工具5.3 核心 API 接口测试后端启动后我们可以使用 Postman 或浏览器直接测试一些基础的 RESTful API以验证服务是否正常。健康检查接口访问GET http://localhost:8080/actuator/health(如果引入了 actuator 依赖)应返回{status:UP}。用户相关接口根据项目设计可能包括POST /api/auth/login用户登录。POST /api/auth/register用户注册。GET /api/user/info获取当前用户信息需要认证。文章相关接口GET /api/articles分页获取文章列表。GET /api/articles/{id}根据ID获取文章详情。POST /api/articles创建新文章需要认证。PUT /api/articles/{id}更新文章需要认证。DELETE /api/articles/{id}删除文章需要认证。使用 Postman 测试登录接口示例方法POSTURLhttp://localhost:8080/api/auth/loginBody (raw JSON):{ username: admin, password: 123456 }预期响应返回包含token和用户信息的 JSON 对象。{ code: 200, message: 登录成功, data: { token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..., userInfo: {...} } }拿到token后在后续需要认证的接口请求头中加上Authorization: Bearer 你的token。6. 前端项目启动与配置后端 API 就绪后我们启动前端项目来构建用户界面。6.1 安装前端依赖在 VSCode 中打开终端Terminal定位到blog-frontend目录执行npm install # 或使用 yarn yarn install此命令会根据package.json文件安装所有依赖包包括 Vue3、Vite、Element Plus、Axios、Pinia 等。6.2 配置 API 代理为了在开发时解决跨域问题需要配置 Vite 的代理。修改vite.config.ts文件import { defineConfig } from vite import vue from vitejs/plugin-vue export default defineConfig({ plugins: [vue()], server: { port: 3000, // 前端开发服务器端口 proxy: { /api: { target: http://localhost:8080, // 后端API地址 changeOrigin: true, rewrite: (path) path.replace(/^\/api/, ) // 可选重写路径 } } } })这样前端在开发环境下访问/api/articles时请求会被代理到http://localhost:8080/api/articles。6.3 启动前端开发服务器在终端中运行npm run dev # 或 yarn dev控制台会输出类似信息VITE v4.x.x ready in 123 ms ➜ Local: http://localhost:3000/ ➜ Network: use --host to expose现在打开浏览器访问http://localhost:3000应该能看到博客的前端界面。6.4 前端项目结构解析src/ ├── api/ # 封装所有后端API请求使用axios ├── assets/ # 静态资源图片、样式 ├── components/ # 可复用Vue组件 ├── router/ # Vue Router路由配置 ├── stores/ # Pinia状态管理 ├── views/ # 页面级组件如HomeView, LoginView ├── utils/ # 前端工具函数 ├── App.vue # 根组件 └── main.ts # 应用入口文件7. 核心功能开发与联调实战现在前后端都已运行我们以“文章管理”为例深入一个核心功能的开发与联调流程。7.1 后端文章列表接口实现实体类 (Entity)Article.java定义了文章的数据结构使用 Lombok 简化代码。Mapper 接口ArticleMapper.java继承 MyBatis-Plus 的BaseMapper无需编写基础 SQL。Service 层ArticleService.java定义业务接口ArticleServiceImpl.java实现分页查询、条件查询等逻辑。Controller 层ArticleController.java暴露 REST API。关键代码示例分页查询文章列表ArticleController.java:RestController RequestMapping(/api/articles) public class ArticleController { Autowired private ArticleService articleService; GetMapping public Result listArticles( RequestParam(defaultValue 1) Integer pageNum, RequestParam(defaultValue 10) Integer pageSize, RequestParam(required false) String categoryId, RequestParam(required false) String tagId) { PageArticleVO page articleService.listArticles(pageNum, pageSize, categoryId, tagId); return Result.success(page); } }ArticleServiceImpl.java(核心查询逻辑):Override public PageArticleVO listArticles(Integer pageNum, Integer pageSize, String categoryId, String tagId) { PageArticle page new Page(pageNum, pageSize); LambdaQueryWrapperArticle queryWrapper new LambdaQueryWrapper(); queryWrapper.eq(Article::getStatus, 1); // 只查询已发布的文章 queryWrapper.orderByDesc(Article::getCreateTime); // 条件查询分类 if (StringUtils.hasText(categoryId)) { queryWrapper.eq(Article::getCategoryId, categoryId); } // 条件查询标签通过关联表查询 if (StringUtils.hasText(tagId)) { queryWrapper.inSql(Article::getId, SELECT article_id FROM article_tag WHERE tag_id tagId); } PageArticle articlePage articleMapper.selectPage(page, queryWrapper); // 将 Article 转换为 ArticleVO并填充分类名、标签列表等额外信息 return convertToArticleVOPage(articlePage); }7.2 前端调用文章列表 API 并渲染API 封装在src/api/下创建article.js。import request from /utils/request // 基于axios封装的请求工具 export function getArticleList(params) { return request({ url: /api/articles, method: get, params }) }页面组件在src/views/ArticleListView.vue中调用 API。template div classarticle-list el-card v-forarticle in articleList :keyarticle.id classarticle-card h3 clickgoDetail(article.id){{ article.title }}/h3 p{{ article.summary }}/p div classmeta span分类{{ article.categoryName }}/span span标签{{ article.tagNames.join(, ) }}/span span发布时间{{ formatTime(article.createTime) }}/span /div /el-card el-pagination current-changehandlePageChange :current-pagepagination.pageNum :page-sizepagination.pageSize :totalpagination.total layoutprev, pager, next /el-pagination /div /template script setup langts import { ref, onMounted } from vue import { getArticleList } from /api/article import { useRouter } from vue-router const router useRouter() const articleList ref([]) const pagination ref({ pageNum: 1, pageSize: 10, total: 0 }) const fetchArticles async () { const params { pageNum: pagination.value.pageNum, pageSize: pagination.value.pageSize } const res await getArticleList(params) if (res.code 200) { articleList.value res.data.records pagination.value.total res.data.total } } const handlePageChange (newPage) { pagination.value.pageNum newPage fetchArticles() } const goDetail (id) { router.push(/article/${id}) } onMounted(() { fetchArticles() }) /script状态管理 (可选)对于全局状态如用户登录信息可以使用 Pinia 管理。7.3 前后端联调关键点接口协议统一确保前后端对 API 的路径、方法GET/POST、请求参数、响应格式如统一的Result包装类定义一致。跨域问题开发环境下通过 Vite 代理解决。生产环境下需要在后端通过CrossOrigin注解或全局配置解决或通过 Nginx 反向代理。数据格式前后端时间格式如LocalDateTime序列化、枚举值等需要约定一致。错误处理前端需要处理后端返回的非 200 状态码并给用户友好提示。联调工具善用浏览器开发者工具的Network面板查看请求和响应详情是定位问题的利器。8. 项目打包与部署本地开发调试完成后下一步是将项目部署到服务器或云环境。8.1 后端打包 (SpringBoot)SpringBoot 项目打包非常简便。在项目根目录包含pom.xml的目录下执行 Maven 命令mvn clean package -DskipTests命令执行成功后在target/目录下会生成一个可执行的 JAR 文件例如blog-backend-0.0.1-SNAPSHOT.jar。这个 JAR 包包含了所有依赖和嵌入式 Tomcat可以直接运行java -jar blog-backend-0.0.1-SNAPSHOT.jar可以通过--server.port8081参数指定运行端口。8.2 前端打包 (Vue3)在前端项目根目录下执行npm run build # 或 yarn build此命令会在项目根目录下生成一个dist文件夹里面是优化和压缩后的静态资源HTML, JS, CSS。8.3 生产环境部署方案方案一前后端分离部署推荐后端将 JAR 包上传至服务器使用java -jar启动或使用systemd、supervisor等工具托管进程实现开机自启和进程守护。前端将dist目录下的所有文件上传至 Nginx 或 Apache 的静态资源目录。Nginx 配置配置 Nginx 作为反向代理和静态资源服务器。server { listen 80; server_name yourdomain.com; # 你的域名 # 前端静态资源 location / { root /path/to/your/dist; index index.html; try_files $uri $uri/ /index.html; # 支持Vue Router的history模式 } # 后端API代理 location /api/ { proxy_pass http://localhost:8080/; # 代理到后端服务 proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } }方案二前后端整合部署将前端打包后的dist目录内容复制到 SpringBoot 项目的src/main/resources/static/目录下然后重新打包后端。这样访问 SpringBoot 服务的根路径就能直接访问前端页面。这种方式更简单但不利于前后端独立升级和维护。9. 常见问题与排查方法在开发和部署过程中你可能会遇到以下问题问题现象可能原因排查方式解决方案后端启动失败端口冲突8080 端口被其他程序占用控制台查看错误日志或使用netstat -ano | findstr :8080(Win) 或lsof -i :8080(Mac/Linux) 查看1. 终止占用端口的进程。2. 修改application.yml中的server.port为其他端口。前端npm install失败网络问题或 node 版本不兼容查看错误信息通常是网络超时或包版本冲突1. 切换 npm 源npm config set registry https://registry.npmmirror.com。2. 删除node_modules和package-lock.json重试。3. 检查 Node.js 版本是否符合要求。前端访问后端 API 404代理配置错误或后端服务未启动1. 检查浏览器 Network 面板请求是否发送到正确地址。2. 检查后端服务是否在运行。1. 确认vite.config.ts中的target地址和端口正确。2. 重启后端服务。数据库连接失败数据库配置错误、服务未启动、或驱动版本不匹配查看后端启动日志中的数据库连接错误信息1. 检查application.yml中的数据库 URL、用户名、密码。2. 确认 MySQL 服务已启动。3. 确认 MySQL 版本与驱动版本兼容。页面刷新后 404 (Vue Router History 模式)生产环境未配置 Nginxtry_files直接访问非根路径的路由时Nginx 找不到对应文件在 Nginx 配置中为前端 location 块添加try_files $uri $uri/ /index.html;。登录成功但后续请求 401Token 未正确传递或已过期检查请求头中Authorization字段是否正确携带Bearer token1. 前端检查 token 存储和请求拦截器逻辑。2. 后端检查 JWT 校验逻辑和过期时间。打包后前端资源路径错误公共路径 (publicPath) 配置错误打开浏览器控制台查看加载失败的资源路径在vite.config.ts中配置base: ./(相对路径) 或base: /your-sub-path/(子路径部署)。10. 项目扩展与深入学习建议完成基础功能后你可以尝试以下方向进行扩展和深化让这个项目更具竞争力引入 Redis 缓存将热点数据如文章列表、网站配置缓存到 Redis大幅提升访问速度。学习 Spring Cache 与 Redis 的集成。增加全文搜索使用 Elasticsearch 实现文章内容的全文检索功能提升用户体验。实现文件云存储将用户上传的图片、文件存储到 OSS如阿里云 OSS、七牛云减轻服务器压力。完善权限系统基于 Spring Security 实现更细粒度的角色权限控制RBAC例如管理员、编辑、普通用户的不同权限。接入第三方登录实现微信、GitHub、Gitee 等第三方账号登录。优化前端体验实现文章目录导航、暗黑模式切换。使用Markdown-it或Vditor优化文章编辑和渲染体验。增加 PWA 支持实现离线访问。容器化部署编写Dockerfile和docker-compose.yml将前后端和数据库容器化实现一键部署。编写单元测试为后端 Service 层和 Controller 层编写 JUnit 单元测试保证代码质量。性能监控与日志集成 Spring Boot Actuator、Prometheus 和 Grafana 进行应用监控使用 ELK 栈管理日志。这个 SpringBoot3 Vue3 的博客项目不仅是一个功能实现更是一个现代 Web 应用开发的样板间。通过亲手敲完每一行代码理解每一个配置项解决每一个报错你对前后端分离开发、RESTful API 设计、项目部署运维的认知会变得非常具体。把它吃透无论是应对面试中的项目拷问还是作为你下一个更复杂项目的基石都大有裨益。建议你在理解本项目的基础上尝试至少一个上述的扩展功能这会让你的学习效果和作品价值成倍提升。