Spring Boot + Vue3 博客管理系统实战:从零搭建前后端分离项目

Spring Boot + Vue3 博客管理系统实战:从零搭建前后端分离项目
1. 这个项目到底能帮你解决什么问题如果你正在找一个能串联起 Spring Boot 和 Vue3 核心技能、并且能直接写到简历里的实战项目这个博客管理项目就是一个非常典型的选择。它不是一个简单的“增删改查”Demo而是覆盖了前后端分离开发中那些真正会遇到的问题权限管理、文章发布、分类标签、文件上传、以及前后端数据如何安全高效地交互。很多教程只讲单个技术点但实际工作中你面对的是一个完整的系统。这个项目最核心的价值就是提供一个从零到一的完整开发视角。你会看到如何用 Spring Boot 搭建 RESTful API 后端如何用 Vue3 的 Composition API 和 Pinia 来管理前端状态以及两者如何通过 Axios 和 JWT 协同工作。学完之后你不仅能掌握技术栈更能理解一个真实项目的开发流程和模块划分这对于应对面试和实际工作至关重要。2. 动手之前先理清技术栈和工具链在开始敲代码之前明确你需要准备的环境和工具这能避免很多“为什么我的跑不起来”的问题。这个项目主要涉及后端和前端两套技术栈。2.1 后端技术栈与环境准备后端基于 Spring Boot这是 Java 领域最主流的快速开发框架。你需要确保本地环境已经就绪。核心依赖Spring Boot 2.7.x / 3.x: 项目基石提供自动配置、内嵌服务器等。Spring Security JWT: 负责用户认证登录和授权权限控制。这是项目的安全核心。MyBatis-Plus: 对 MyBatis 的增强简化了数据库操作你会大量用到它的通用 Mapper 和条件构造器。MySQL: 关系型数据库用于存储用户、文章、分类等数据。Redis (可选但推荐): 用于缓存热点数据如网站配置、热门文章列表或存储登录令牌的黑名单提升性能。Maven: 项目构建和依赖管理工具。开发环境JDK: 建议使用 JDK 8、11 或 17根据 Spring Boot 版本选择2.7.x 兼容 JDK 83.x 需要 JDK 17。在终端输入java -version确认。IDE: IntelliJ IDEA社区版或旗舰版是首选它对 Spring Boot 的支持最好。也可以用 Eclipse 或 VS Code需安装 Java 插件。数据库工具: 安装 MySQL并准备一个图形化管理工具如 Navicat、DBeaver 或 IDEA 自带的数据库工具。API 测试工具: Postman 或 Apifox用于测试后端接口是否正常工作。第一步不是写代码而是建库建表。我一般会先根据项目预期的功能用户、文章、分类、标签、评论等在 MySQL 中创建一个数据库例如blog_db然后运行项目提供的 SQL 脚本来初始化表结构。如果没有脚本就需要根据实体类Entity来设计表这一步能帮你提前理解数据模型。2.2 前端技术栈与环境准备前端使用 Vue3 的 Composition API 写法这是目前的主流和未来趋势。核心依赖Vue 3: 前端核心框架。Vite: 新一代前端构建工具启动和热更新速度远超传统的 Webpack。Vue Router 4: 管理前端路由页面跳转。Pinia: Vue 官方推荐的状态管理库替代了 Vuex更简洁。Element Plus 或 Ant Design Vue: UI 组件库能极大提升开发效率。本项目通常会选用其中一个。Axios: 用于发送 HTTP 请求到后端 API。Node.js npm/pnpm/yarn: 运行环境和包管理器。开发环境Node.js: 建议安装 LTS长期支持版本如 18.x 或 20.x。安装后在终端输入node -v和npm -v检查版本。IDE: Visual Studio Code 是前端开发的首选安装 Vue 官方扩展Volar和必要的插件如 Auto Close Tag, Path Intellisense。包管理器: npm 是默认的但 pnpm 或 yarn 在速度和磁盘空间上更有优势可以按喜好选择。注意在开始前先用npm create vuelatest或pnpm create vue命令通过官方脚手架快速创建一个干净的 Vue3 项目模板。这能确保你的基础环境是正确可用的。3. 从零开始后端 Spring Boot 核心模块搭建后端是整个系统的发动机。不要一上来就想把所有功能写完应该按模块逐个击破。我建议的顺序是项目初始化 - 数据库连接与实体 - 通用返回结果封装 - 用户认证授权 - 业务模块文章、分类等。3.1 项目初始化与基础配置使用 Spring Initializr在 IDEA 里直接选择或访问 start.spring.io创建项目。关键依赖选择Spring Web,Spring Security,MyBatis Framework,MySQL Driver,Lombok简化实体类代码。创建完成后首先配置application.yml或application.properties文件server: port: 8080 # 后端服务端口 spring: datasource: url: jdbc:mysql://localhost:3306/blog_db?useUnicodetruecharacterEncodingutf-8serverTimezoneAsia/Shanghai username: root password: your_password driver-class-name: com.mysql.cj.jdbc.Driver # Redis配置如果使用 redis: host: localhost port: 6379 database: 0 # 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: 0这里最容易出错的是数据库连接 URL 的时区设置和驱动类名如果用的是 MySQL 8.0一定要加上serverTimezone和cj驱动。3.2 用户认证与授权Spring Security JWT这是后端最复杂也最重要的部分。目标是用户登录成功后后端生成一个 JWT Token 返回给前端前端后续请求在 Header 中携带此 Token后端进行校验。引入 JWT 依赖在pom.xml中添加jjwt相关依赖。创建 JWT 工具类包含生成 Token、解析 Token、校验 Token 是否过期等方法。配置 Spring Security创建一个配置类继承WebSecurityConfigurerAdapterSpring Boot 2.x或使用新式配置Spring Boot 3.x。核心是放行登录接口、注册接口、静态资源等。配置密码加密器使用BCryptPasswordEncoder。自定义UserDetailsService来从数据库加载用户信息。添加一个JwtAuthenticationFilter在用户名密码验证前先尝试从请求头中解析 JWT如果有效则直接设置用户认证信息。配置异常处理返回统一的 JSON 格式而不是跳转到登录页。实测踩坑点Spring Security 的过滤器链顺序很重要。你的 JWT 过滤器必须放在UsernamePasswordAuthenticationFilter之前。另外处理成功后一定要调用SecurityContextHolder.getContext().setAuthentication(...)将认证信息放入上下文否则后续的PreAuthorize等注解会失效。3.3 业务模块开发以文章模块为例采用经典的三层架构Controller - Service - Mapper。实体类 (Entity)使用DataLombok创建Article类定义 id、标题、内容、摘要、分类ID、标签、状态、创建时间等字段。使用TableName指定表名。Mapper 接口继承 MyBatis-Plus 的BaseMapperArticle你就自动拥有了单表通用的 CRUD 方法。复杂查询可以自定义 XML 文件或使用Select注解。Service 层创建接口IArticleService和实现类ArticleServiceImpl。实现类继承ServiceImplArticleMapper, Article并实现你的接口。在这里写业务逻辑比如发布文章前校验分类是否存在查询文章列表时关联查询分类名称等。Controller 层使用RestController和RequestMapping(“/articles”)。方法上使用GetMapping、PostMapping等注解。关键点在创建、修改、删除等方法上使用PreAuthorize(“hasAuthority(‘admin’)”)或PreAuthorize(“isAuthenticated()”)进行权限控制。使用Validated注解配合校验注解如NotBlank对传入参数进行校验。统一返回格式例如一个包含 code、data、msg 的Result对象。关于分页查询MyBatis-Plus 的分页插件需要配置。在配置类中注册一个PaginationInterceptor2.x或MybatisPlusInterceptor3.x然后在 Controller 中接收Page对象Service 中调用page(page, queryWrapper)方法即可。4. 前端 Vue3 项目与后台管理界面实现前端项目我们使用 Vite 创建这样启动速度更快。重点在于理解 Composition API、Pinia 状态管理以及如何与后端 API 对接。4.1 项目初始化与基础架构运行npm create vuelatest按提示选择需要的特性Router, Pinia, ESLint。创建完成后安装 UI 库和 Axioscd blog-admin-frontend npm install npm install element-plus axios # 或者使用 pnpm # pnpm add element-plus axios接下来进行基础配置引入 Element Plus在main.js或main.ts中全局引入或者按需引入以减小打包体积。配置 Axios 实例在src/utils/request.js中创建一个 Axios 实例设置基础 URLbaseURL: ‘http://localhost:8080’、请求超时时间并添加请求拦截器和响应拦截器。请求拦截器从本地存储localStorage中读取 JWT Token并添加到每个请求的 Header 中Authorization: Bearer ${token}。响应拦截器统一处理错误例如当后端返回 401 状态码时提示“登录已过期”并跳转到登录页。配置路由守卫在src/router/index.js中利用router.beforeEach实现全局前置守卫。检查目标路由是否需要认证可通过meta字段标记如果需要但用户未登录则重定向到登录页。4.2 状态管理使用 Pinia 管理用户信息为什么用 Pinia因为像登录状态、用户信息用户名、头像、权限列表这些数据在多个组件如导航栏、个人中心都需要访问放在 Pinia 里比用 Props 层层传递或事件总线要清晰得多。运行npm install pinia如果创建时未选。在src/stores目录下创建user.jsimport { defineStore } from pinia import { ref } from vue import { login, getInfo, logout } from /api/user // 假设这是你的API文件 export const useUserStore defineStore(user, () { const token ref(localStorage.getItem(token) || ) const userInfo ref({}) const setToken (newToken) { token.value newToken localStorage.setItem(token, newToken) } const clearToken () { token.value localStorage.removeItem(token) } const loginAction async (loginForm) { const res await login(loginForm) setToken(res.data.token) // 登录成功后可以立即获取用户信息 await getUserInfo() } const getUserInfo async () { const res await getInfo() userInfo.value res.data } const logoutAction () { // 调用后端退出接口如果需要使token失效 logout() clearToken() userInfo.value {} router.push(/login) } return { token, userInfo, loginAction, getUserInfo, logoutAction } })在登录组件中调用userStore.loginAction(form)即可。其他组件通过const userStore useUserStore()来获取和响应式更新用户状态。4.3 典型页面开发文章列表与编辑我们以文章管理页面为例串联起组件、API调用和状态管理。文章列表页 (ArticleList.vue)模板使用 Element Plus 的el-table展示数据el-pagination做分页el-button提供新增、编辑、删除操作。脚本使用ref定义响应式数据tableData列表数据、total总条数、queryParams查询参数。使用onMounted钩子在页面加载时调用fetchData方法。fetchData方法调用封装好的 Axios 实例例如getArticleList(queryParams)获取数据并赋值给tableData和total。将删除、查询等方法也定义在这里。样式使用style scoped编写组件局部样式。文章编辑/新增页 (ArticleEdit.vue)这是一个表单页包含标题输入框、分类选择器、标签输入、富文本编辑器需要集成如wangeditor/editor或tinymce等。关键点如果是编辑在onMounted中根据路由参数route.params.id调用接口获取文章详情并回填表单。富文本编辑器集成后需要处理内容通常是 HTML 字符串的上传和回显。提交表单时调用创建或更新接口。成功后给出提示并返回列表页。关于文件上传通常使用 Element Plus 的el-upload组件。需要配置action为后端上传接口地址设置请求头携带 Token并处理上传成功/失败的回调将服务器返回的文件路径保存到表单数据中。5. 前后端联调与部署上线的关键细节代码写完了本地也能跑不代表项目就完成了。联调和部署才是检验项目是否健壮的最后关卡。5.1 联调常见问题与排查跨域问题 (CORS)前端运行在localhost:5173后端在localhost:8080浏览器会因同源策略阻止请求。解决方案在后端配置 CORS。Spring Boot 中可以在配置类添加CrossOrigin注解不推荐用于生产或使用WebMvcConfigurer进行全局配置明确允许前端的源、方法和请求头。401 Unauthorized这是联调中最常见的问题。检查 Token前端是否成功获取并存储了 Token每次请求的 Header 中Authorization字段格式是否正确Bearer token检查 Token 有效期JWT Token 可能已过期。后端拦截器是否正确处理了过期情况并返回了明确的错误信息检查接口权限这个接口是否需要特定角色如ROLE_ADMIN当前登录用户的权限是否包含它404 Not Found检查前后端请求路径是否完全一致包括大小写。检查后端 Controller 的RequestMapping路径。500 Internal Server Error查看后端控制台日志这是最直接的错误信息源。可能是空指针、数据库查询错误、参数绑定失败等。我的联调习惯一定会打开浏览器的开发者工具F12看Network标签页。这里能看到每一个请求的 URL、方法、状态码、请求头和响应体。响应体里的后端错误信息是排查的关键。同时后端也要开启 SQL 日志确认执行的语句是否符合预期。5.2 项目打包与简易部署后端打包使用 Maven 执行mvn clean package跳过测试可以加-DskipTests。在target目录下会生成一个*.jar文件。在服务器上或本地测试只需要安装好 Java 运行环境JRE然后通过java -jar your-project.jar即可启动。可以通过--server.port9090指定端口。前端打包执行npm run build。Vite 会在dist目录下生成静态文件HTML, JS, CSS。这些静态文件需要被一个 Web 服务器托管。最简单的方式是使用 Nginx。使用 Nginx 部署前后端分离项目将前端dist目录下的所有文件上传到服务器某个目录例如/usr/share/nginx/html/blog。配置 Nginx核心思想是将前端页面服务起来并将所有/api/开头的请求代理到后端 Java 服务。server { listen 80; server_name your-domain.com; # 你的域名或IP # 前端静态资源 location / { root /usr/share/nginx/html/blog; 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; } }重启 Nginxsudo systemctl restart nginx。这样用户访问你的服务器 IP 或域名看到的是前端页面。前端页面中的 Axios 请求发往/api/xxx会被 Nginx 转发到后端的localhost:8080/xxx完美解决跨域和部署问题。6. 从“跑通”到“写好”项目亮点与优化方向一个能跑的项目和一个能拿得出手的项目区别在于细节和深度。完成基础功能后可以从以下几个方向优化你的项目这会让你的简历和面试回答更有分量。接口文档与规范化使用Swagger/OpenAPI通过springdoc-openapi依赖自动生成 API 文档。访问/swagger-ui.html就能看到所有接口的说明、参数和测试界面这是非常专业的体现。全局异常处理在 Spring Boot 中使用ControllerAdvice和ExceptionHandler创建一个全局异常处理器。统一处理业务异常、参数校验异常、权限异常等并返回结构化的错误信息而不是一堆堆栈跟踪。数据校验进阶除了在 Controller 参数上用Validated可以在 Service 层甚至领域模型内部进行更复杂的业务规则校验。使用自定义注解和校验器。缓存策略在查询频繁、变化不频繁的数据上使用 Redis 缓存如网站配置、热门文章列表。使用 Spring Cache 注解如Cacheable可以优雅地集成。日志记录使用 SLF4J Logback 记录详细的运行日志特别是关键业务操作如发布文章、删除评论和异常信息。配置日志按天滚动和分级存储便于线上排查问题。安全性加固SQL 注入MyBatis-Plus 的条件构造器默认使用预编译语句基本能防止。但要避免在 XML 中手动拼接 SQL。XSS 攻击对富文本内容在前端编辑器和后端存储时都要做适当的过滤或转义。CSRF 攻击如果使用类似 Cookie Session 的传统模式需要关注但 JWT 无状态 API 模式本身对此有一定免疫不过仍需注意 Token 的存储安全不要放在 localStorage可放在内存或 HttpOnly Cookie 中讨论利弊。前端性能与体验路由懒加载在 Vue Router 配置中使用() import(‘…’)语法实现组件懒加载减少首屏加载体积。API 请求防抖/节流在搜索框等场景应用。错误边界使用 Vue 3 的onErrorCaptured钩子捕获组件内错误提供友好的错误提示。这个博客管理项目就像一座桥把 Spring Boot 和 Vue3 的理论知识连接到了实际应用的岸边。我建议你在跟着敲完一遍后不要就此停止。尝试自己添加一个新功能比如“文章浏览量统计”、“文章点赞/收藏”或者把 UI 换成另一个组件库。在这个过程中你一定会遇到新的问题而解决这些问题的过程才是你真正提升工程能力的时候。记住看懂和做出来是两回事做出来和做好、做稳定又是不同的层次。