尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

SpringBoot+Vue前后端分离个人博客实战:从环境搭建到Nginx部署

SpringBoot+Vue前后端分离个人博客实战:从环境搭建到Nginx部署 最近在整理之前写的个人博客项目把整个前后端分离的开发过程重新过了一遍发现不少当时踩过的坑现在看特别有代表性。这里就把整个 SpringBoot Vue 的个人博客系统实战过程完整梳理出来从技术选型、环境搭建、核心模块实现到部署上线把我自己的实操经验和踩坑教训都揉进去希望对正准备做前后端分离项目的朋友有帮助。这个项目适合三类人一是刚学完 SpringBoot 和 Vue 基础、想找个完整项目练手的小伙伴二是需要做毕业设计或简历项目的在校学生三是想了解前后端分离架构真实开发流程的初级开发。整个项目麻雀虽小五脏俱全涉及用户认证、文章管理、评论系统、文件上传等常见业务场景能帮你把零散的知识点串成一条完整的开发链路。1. 项目整体设计与技术选型1.1 为什么选择前后端分离架构前后端分离这个词喊了好多年但真正自己动手做一遍才会理解它的价值。传统开发方式里后端用 Thymeleaf 这类模板引擎直接渲染 HTML前端页面和后端 Java 代码耦合在一起改个页面样式都要重启整个应用。而前后端分离后后端只负责提供 JSON 接口前端用 Vue 独立开发和构建两者通过 HTTP 协议通信。我做这个个人博客系统时最直观的感受就是开发效率的提升。后端把接口写好用 Postman 一测没问题就可以把接口文档丢给前端或者自己切到前端项目继续写页面两边并行开发互不干扰。后续想给博客加个移动端适配只要复用同一套后端 API重新写个前端页面就行不用动后端一行代码。1.2 个人博客系统的功能模块拆解个人博客看着简单但真要做得完整涉及的功能点其实不少。我当时梳理下来核心模块有这些用户模块注册、登录、JWT 令牌签发与校验、用户信息管理文章模块文章的增删改查、Markdown 内容解析、标签和分类管理评论模块对文章的评论、评论列表展示、管理员删除文件模块图片上传、头像上传涉及本地存储路径处理和静态资源映射统计模块文章阅读量、分类归档统计我之所以选个人博客作为实战项目就是因为它足够复杂——能覆盖前后端交互的绝大多数场景但又不至于像电商系统那样庞大到一个人难以驾驭。尤其认证授权这块前后端分离场景下的 Token 处理是面试高频考点也是实际工作中天天要用的东西做一遍印象非常深。1.3 技术栈选型的对比与权衡技术选了 SpringBoot 2.7.14 Vue 2 MyBatis-Plus MySQL 8.0 这套组合。有朋友会问现在 Vue 3 都出来这么久了为什么不直接上 Vue 3原因在于生态兼容性。我常用的很多组件库虽然已经支持 Vue 3但后端管理类模板、第三方插件不少还是 Vue 2 的生态更成熟网上能找到的现成例子也更多。再加上当时我手头的服务器配置一般Vue 2 构建出来的包体积更小所以选择了稳妥路线。SpringBoot 版本我特意选 2.7.14 而不是最新的 3.x这里有个很重要的原因3.x 把 javax 包迁移到了 jakarta很多第三方依赖还没来得及适配网上搜到的教程大部分还是基于 2.x 写的。对新手来说跟着教程走能少踩一半的坑。这个选择在后面集成各种组件时证明非常明智后面我会专门讲版本引发的那些坑。Vue 2 全家桶我用了 Vue Router 3 Vuex 3 Axios配合 Element UI 组件库。Element UI 对后端管理页面来说简直是生产力工具表格、表单、弹窗这些高频组件开箱即用让我能集中精力写业务逻辑而不是反复造轮子。2. 开发环境准备与项目初始化2.1 后端环境搭建与 SpringBoot 版本避坑后端的开发环境要装 JDK、Maven、IDEA 和 MySQL。JDK 版本这里要特别提醒SpringBoot 2.7.x 用 JDK 8 或 JDK 11 都行但如果你电脑上装的是 JDK 17会遇到一些意想不到的问题比如 Lombok 版本不兼容导致编译报错。我当时用的是 JDK 8配合 Maven 3.6.3这个组合非常稳定。第一次用 IDEA 创建 SpringBoot 项目时很多人会在 Spring Initializr 这一步卡住。如果你的网络访问 start.spring.io 比较慢可以换成阿里云的镜像地址https://start.aliyun.com创建速度和依赖下载体验都会好很多。创建完成后检查一下 pom.xml确认 spring-boot-starter-parent 的版本号是你预期的版本别一不留神给你搞了个最新的 3.x。依赖方面一个个人博客系统需要引入这些核心依赖dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency !-- MyBatis-Plus 的 Spring Boot Starter -- dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-boot-starter/artifactId version3.5.3.1/version /dependency !-- MySQL 驱动 -- dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId version8.0.33/version /dependency !-- JWT 工具库 -- dependency groupIdio.jsonwebtoken/groupId artifactIdjjwt/artifactId version0.9.1/version /dependency !-- Lombok省略 getter/setter -- dependency groupIdorg.projectlombok/groupId artifactIdlombok/artifactId optionaltrue/optional /dependency2.2 前端环境配置与 Vue 项目创建前端需要安装 Node.js 和 npmNode 版本建议 LTS 版本我当时用的是 16.x。安装完 Node 后npm 的默认源在国内下载依赖很慢建议换成淘宝镜像npm config set registry https://registry.npmmirror.comVue 项目的创建有两种方式一个是 Vue CLI 的交互式命令另一个是直接手动搭 webpack。新手建议用 Vue CLI少折腾构建配置npm install -g vue/cli vue create blog-frontend创建过程中会问你选什么预设我建议选 Manually select features然后勾选 Babel、Router、Vuex、CSS Pre-processors。这几个是博客项目必需的。等依赖安装完进入项目目录跑一下npm run serve浏览器打开 localhost:8080 看到 Vue 的欢迎页面就说明环境通了。注意Vue CLI 5 创建的项目默认 webpack 版本是 5如果你在后续开发中遇到某些 loader 版本兼容问题优先检查 package.json 里的依赖版本是不是被 npm 自动升级了。这种问题排查起来很费时间锁定版本是一个好习惯。2.3 后端项目结构与数据库表设计在写代码之前先把项目的包结构理清楚。我习惯用这种分层结构清晰且符合主流规范com.example.blog ├── controller // 接收请求参数校验 ├── service // 业务逻辑层接口实现 ├── mapper // MyBatis-Plus 的数据访问层 ├── entity // 数据库表对应的实体类 ├── dto // 数据传输对象接收前端参数 ├── vo // 视图对象返回给前端的数据 ├── config // 配置类跨域、拦截器、静态资源 ├── utils // 工具类JWT、MD5、统一返回结果 ├── handler // 全局异常处理 └── BlogApplication.java数据库表的设计我放了五张表用户表 t_user、文章表 t_article、评论表 t_comment、分类表 t_category、标签表 t_tag另外加了一张文章标签关联表 t_article_tag。这里分享一个经验博客类的文章表一定要单独存一个 content_md 字段存 Markdown 原文再存一个 content_html 字段存渲染后的 HTML。虽然有点冗余但这样前端展示时直接渲染 HTML 就行不需要每次请求都做实时转换性能更好而且编辑文章时又能直接拿 Markdown 原文去回显。3. 后端核心模块的实现细节3.1 数据库连接与 MyBatis-Plus 配置数据库连接配置写在 application.yml 里。这里重点提一下时区问题如果 URL 里不加上serverTimezoneAsia/Shanghai数据库连接会报时区错误。密码也别用明文可以通过环境变量注入但在本地开发阶段为了方便我直接写在了配置文件里等部署上线再改成变量引用。spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/blog?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai username: root password: 你的密码 mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl global-config: db-config: logic-delete-field: deleted logic-delete-value: 1 logic-not-delete-value: 0MyBatis-Plus 的配置里有几个点值得解释。log-impl配成 StdOutImpl 后控制台会打印 SQL 语句开发调试时特别有用你能清楚地看到 MyBatis-Plus 帮你生成的 SQL 到底是什么样。logic-delete-field配置了逻辑删除字段这样删除文章时实际上执行的是 UPDATE 而不是 DELETE数据不会真正消失对博客这类内容型系统来说是个安全网误删了还能恢复。3.2 统一返回结果与全局异常处理的设计前后端分离的项目接口返回的数据格式一定要统一。我的做法是定义一个 Result 类所有接口都返回这个结构Data public class ResultT { private Integer code; // 状态码200成功400参数错误401未登录500服务器异常 private String message; // 提示信息 private T data; // 业务数据 public static T ResultT success(T data) { ResultT result new Result(); result.setCode(200); result.setMessage(操作成功); result.setData(data); return result; } public static T ResultT error(Integer code, String message) { ResultT result new Result(); result.setCode(code); result.setMessage(message); return result; } }配合全局异常处理器把业务异常、参数校验异常、系统异常分别处理保证任何情况下前端拿到的都是结构统一的 JSON而不是一堆乱七八糟的异常堆栈。统一返回格式这件事看似简单但对前后端协作来说很重要。前端 Axios 拦截器只需要对这个结构做一次统一判断就能处理所有的请求响应不用每个接口单独写错误处理逻辑。3.3 JWT 鉴权前后端分离的 Token 完整链路前后端分离项目里最核心的认证方案就是 JWT。原理就是用户登录成功后后端签发一个包含用户信息的加密 Token 返回给前端前端把 Token 存在 localStorage 里每次请求都在 HTTP 头里带上这个 Token后端通过拦截器校验 Token 的合法性从而识别用户身份。JWT 工具类我用了 jjwt 库核心就两个方法生成 Token 和解析 Token。生成 Token 时一定要设置过期时间我当时设的是 7 天对个人博客够用了。另外要把用户的 id 和用户名放进 Token 的 claims 里这样后续处理请求时直接从 Token 里就能拿到当前用户信息不用每次都查数据库public String generateToken(Long userId, String username) { MapString, Object claims new HashMap(); claims.put(userId, userId); claims.put(username, username); return Jwts.builder() .setClaims(claims) .setSubject(username) .setIssuedAt(new Date()) .setExpiration(new Date(System.currentTimeMillis() 7 * 24 * 60 * 60 * 1000L)) .signWith(SignatureAlgorithm.HS256, SECRET_KEY) .compact(); }拦截器的逻辑我之前说过在 preHandle 方法里从请求头的 Authorization 字段取出 Token调用 API key 解析成功就把 userId 放到 request 的 attribute 里放行失败就返回 401。但要注意拦截器只拦需要登录的接口像文章列表、博客首页这些公开数据接口要放行。前端这边Axios 请求拦截器里统一加上 Tokenconfig.headers[Authorization] Bearer localStorage.getItem(token)。响应拦截器里判断返回的 code如果是 401 就跳转登录页。这就是前端请求带 Token、响应踢回登录的完整闭环也是搜索热词里vue前后端分离请求token处理这个问题的标准答案。3.4 文章模块与 Markdown 内容处理文章的增删改查是博客系统的核心。我用了 MyBatis-Plus 的 IService 和 BaseMapperCRUD 的胶水代码基本不需要自己写直接继承接口就有常用的方法。文章列表接口要考虑分页和条件查询。分页用 MyBatis-Plus 的分页插件配置一个 PaginationInnerInterceptor 就行然后调用 Page 对象作为查询参数。条件查询支持按分类 ID、标签 ID、关键词匹配标题这三个维度组合过滤用 LambdaQueryWrapper 动态拼接条件逻辑很清晰LambdaQueryWrapperArticle wrapper new LambdaQueryWrapper(); if (StringUtils.hasText(keyword)) { wrapper.like(Article::getTitle, keyword); } if (categoryId ! null) { wrapper.eq(Article::getCategoryId, categoryId); } wrapper.orderByDesc(Article::getCreateTime);文章发布时涉及 Markdown 转 HTML 的问题。我选了 commonmark-java 这个库它比老牌的 Markdown 渲染器更轻量、更新更积极。处理流程是前端把 Markdown 原文提交到后端 → 后端用 commonmark 转成 HTML → 存进 content_html 字段。同时为了安全转换后的 HTML 需要做一次 XSS 过滤用 jsoup 的 clean 方法把 script 标签等危险内容过滤掉这个细节建议一定要加上。图片上传则是把 multipart 文件保存到服务器的指定目录然后返回一个访问 URL。这里有个后端配置容易漏要自定义静态资源映射把/upload/**这个路径映射到本地磁盘的上传目录否则浏览器访问不到你上传的图片。4. 前端页面开发与接口联调4.1 Vue Router 路由设计与页面守卫前端路由的规划其实就是整个博客的页面结构。我设计了这样几个页面/首页文章列表流分页加载/article/:id文章详情页路由参数就是文章的 ID/category/:id分类下的文章列表/tag/:id标签下的文章列表/login和/register登录注册页/admin后台管理页包含文章编辑、评论管理等子页面Vue Router 按需加载很重要每个路由组件用() import(/views/xxx.vue)这种写法动态导入这样首屏只加载首页的代码访问到管理页时才加载对应代码块能显著减少首屏白屏时间。路由守卫是前端鉴权的关键环节。在 beforeEach 钩子里做登录判断如果访问的是后台管理页检查 localStorage 里有没有 token没有就跳转到登录页。这里要注意token 存在这个操作本身就有 XSS 风险但个人项目为了简单可以接受。生产环境更安全的做法是存 HttpOnly Cookie但前后端分离场景又得处理 CSRF 问题属于另一套权衡了。4.2 Axios 封装与 Token 拦截的完整实现前面后端部分讲了 JWT 鉴权的原理前端这里把拦截器的完整代码分享出来。这一步做得好不好直接决定你调试接口时爽不爽import axios from axios import { Message } from element-ui import router from /router const service axios.create({ baseURL: /api, timeout: 10000 }) // 请求拦截器自动携带 token service.interceptors.request.use(config { const token localStorage.getItem(token) if (token) { config.headers[Authorization] Bearer token } return config }, error Promise.reject(error)) // 响应拦截器统一处理结果和错误 service.interceptors.response.use(response { const res response.data if (res.code ! 200) { if (res.code 401) { localStorage.removeItem(token) router.push(/login) } Message.error(res.message || 请求失败) return Promise.reject(new Error(res.message)) } return res }, error { Message.error(error.message || 网络异常) return Promise.reject(error) }) export default servicebaseURL配成/api是因为我在 Vue 的 devServer 里配置了代理把开发环境的请求转发到后端的 8080 端口这样开发阶段就没有跨域问题。代理配置在 vue.config.js 里上面搜索结果里提到的跨域问题基本都靠这一招解决devServer: { proxy: { /api: { target: http://localhost:8080, changeOrigin: true, pathRewrite: { ^/api: } } } }4.3 文章列表与详情页的渲染细节文章列表页的渲染逻辑比较常规用 Element UI 的卡片组件展示文章标题、摘要、分类和发布时间滚动到底部或点击按钮触发加载更多。这里一个细节是日期的格式化后端返回的时间戳如果直接显示会很难看我封装了一个日期过滤器把时间统一格式化成YYYY-MM-DD HH:mm。文章详情页最核心的是 Markdown 渲染。后端已经返回了 content_html前端直接用一个 v-html 指令渲染就行。但原生 HTML 的样式会比较朴素我引入了一个 GitHub 风格的 Markdown 样式包github-markdown-css加上markdown-body这个类后渲染效果立刻专业起来。代码高亮我用了 highlight.js在 mounted 里扫描页面中的 pre 标签并绑定高亮这个体验对技术博客来说非常重要。评论区我用的是组件嵌套的方式每个评论组件自身维护回复列表点回复时弹出输入框提交后刷新评论列表。这个交互在 Vue 里实现起来比 jQuery 时代清爽得多本质就是组件内部的数据状态管理。4.4 管理后台与富文本编辑后台管理页面我做了一个简易的布局左侧导航栏右侧内容区。文章列表用 Element UI 的 el-table 展示顶部放新建文章按钮和搜索框。新建和编辑文章共用一个表单组件通过路由参数区分是编辑还是新增。富文本编辑这块我试过几款编辑器最终选用了 mavon-editor它本身就是基于 Vue 2 的 Markdown 编辑器支持实时预览、图片上传和我后端 Markdown 渲染的方案完全匹配。图片上传走了一个通用的上传接口编辑器把图片传到服务器返回的 URL 自动插入到 Markdown 里。提示mavon-editor 在 npm 安装时如果版本不对可能会报依赖冲突。我用的是 2.11.1 版本和 Vue 2.6 完美兼容。升级到 2.11.2 之后反而出现过样式丢失的问题排查了很久才发现是版本导致的所以建议锁定一个你验证过的版本。5. 实战中常见问题与排查实录5.1 SpringBoot 版本过高的那些坑做这个项目的过程中我对版本太高这个问题真的深有体会。最早我图省事在 IDEA 里直接选了默认的最新版 SpringBoot当时是 3.1.x结果一连串问题接踵而至。先是在导入依赖时发现 mysql-connector-java 这个坐标在 3.x 里被改了得换成com.mysql:mysql-connector-j。然后是 javax.servlet 相关的包全部找不到了因为 SpringBoot 3 基于 Jakarta EE 9包名从 javax 变成了 jakarta导致我用的很多第三方库编译直接报错。最后连 jjwt 0.9.1 这个老牌 JWT 库都存在兼容性问题。最后我果断回退到 2.7.14所有问题迎刃而解。这个经历给我的教训是如果你想跑通一个完整项目优先选择生态成熟、教程丰富的版本。新版本特性确实好但不是实战练手时的好选择。看 SpringBoot 版本可以直接在 pom.xml 里改 parent 的版本号改完记得刷新 Maven 让依赖重新下载。5.2 前后端联调时的跨域与代理问题联调阶段最常遇到的就是跨域。一开始后端我配置了CrossOrigin注解前端直接请求后端地址也能通。但这种方式有两个问题一是每个 Controller 上都要加注解麻烦二是生产环境部署时前端静态文件和后端接口不在一个域下跨域配置容易出问题。后来我改成统一方案开发环境用 Vue 的 devServer 代理生产环境用 Nginx 反向代理。这样前后端代码里都不需要处理跨域浏览器看到的请求都是同源的。这个方案少量代码就能解决跨域而且部署后也省心。后端那边只需要把自定义的跨域配置类删掉或者注释掉避免和代理策略冲突。5.3 Vue 打包后的布局异常问题搜索热词里有个vue 打包后 布局异常这个问题我打包上线时确实遇到了。开发环境一切正常npm run build之后部署到 Nginx发现所有的图片不显示路由跳转到二级页面就 404。问题根源是打包后的静态资源路径用的是绝对路径/js/xxx.js而我把前端文件部署在了服务器的子目录下。解决办法是在vue.config.js里设置publicPath: ./让资源加载使用相对路径。路由 404 的问题则是 Nginx 配置里没有做 history 模式的回退加上下面这段配置就好了location / { try_files $uri $uri/ /index.html; }这个坑几乎是每个用 Vue 做前后端分离项目的人都会遇到的一遍踩过去之后就明白了构建路径和服务器部署路径的关系。5.4 文件上传路径与静态资源映射丢失上传图片后访问返回的 URL 出现 404也是高频问题。这个大概率是后端没有把上传目录映射成静态资源。在 SpringBoot 里加一个 WebMvcConfigurer 配置类就能解决Configuration public class WebConfig implements WebMvcConfigurer { Override public void addResourceHandlers(ResourceHandlerRegistry registry) { String uploadPath System.getProperty(user.dir) /upload/; registry.addResourceHandler(/upload/**) .addResourceLocations(file: uploadPath); } }注意 file 协议后面的路径一定要以/结尾否则还是映射不上。我在这个细节上卡了将近一个小时最后才注意到路径末尾的问题。还有一个相关的坑是 Nginx 部署时前端页面通过/upload/xxx.jpg访问图片但 Nginx 根本没把/upload路径转发给后端又在 Nginx 里配了一条 location 规则才解决。做前后端分离项目这种前端访问路径 → Nginx → 后端静态资源映射的链条你迟早会碰到提前了解能省不少事。5.5 视频播放等扩展场景的处理有朋友问过我用这个博客系统播放在线视频怎么处理这里顺带提一下。想在 Vue 页面播放 m3u8 格式的流媒体视频一般用 hls.js 这个库。m3u8 是 HLS 协议的视频索引文件浏览器原生不支持直接播放需要借助 MSE 技术把视频流喂给 video 元素。实际集成步骤如下先npm install hls.js然后在视频组件里实例化 Hls 对象把视频源绑定到 video 元素的 src 上。如果视频文件有跨域限制还需要在后端配置 CORS 允许对应的来源。这块内容作为博客系统的扩展功能是可以的但个人博客使用场景有限我很早就没有加进核心功能里只做了技术验证。5.6 常见问题速查表问题现象排查方向解决方案SpringBoot 启动失败检查 JDK 版本与 SpringBoot 版本兼容性2.7.x 用 JDK 8/113.x 用 JDK 17接口返回 401Token 过期或请求头没有带 Token检查前端拦截器重新登录接口跨域报错开发环境代理配置是否正确用 devServer.proxy 或后端 CORS数据库乱码连接 URL 字符集与库表字符集不一致统一 utf8mb4URL 加 characterEncodingutf8打包后资源 404publicPath 路径配置错误设置 publicPath: ./路由刷新 404Nginx 未做 history 回退配置 try_files图片上传后访问不到静态资源映射缺失WebMvcConfigurer 添加映射npm 安装依赖报错版本冲突或网络问题锁定版本使用 npmmirror 镜像6. 项目部署与进阶扩展建议6.1 前后端构建与 Nginx 部署全流程项目做完之后部署上线又是一轮新的考验。我的部署方案是前端构建成静态文件后交给 Nginx 托管后端打成 jar 包用 systemd 守护进程运行。前端的构建命令很简单npm run build产物在 dist 目录里。把这个目录里的文件上传到服务器的/var/www/blog下然后 Nginx 配置里指定 root 指向这个目录。后端的 jar 包通过 Maven 打包生成我把mvn clean package之后的 jar 文件放到/opt/blog目录用 systemd 创建一个服务文件来管理它的启停和自启动。后端接口的路径设计要注意一个细节。我在后端 Controller 里给所有接口都加了/api前缀这样 Nginx 配置里一条location /api规则就能把接口请求转发到 127.0.0.1:8080代码清晰反向代理配置也简单。你可能会问为什么当初不在 Vue 的 devServer 代理里就把/api去掉因为保持前后端路径一致对部署最省心。6.2 项目的进阶扩展方向个人博客系统跑通之后往哪里扩展其实是很多朋友关心的问题。我自己梳理了几个方向就是基于前后端分离的个人博客系统这个核心骨架生长出去的接入第三方登录GitHub 登录省去注册流程提高评论参与率集成 Elasticsearch给文章搜索做全文索引替代 MySQL 的 like 模糊查询搜索性能提升明显对接 Redis 缓存热点文章的阅读量和详情数据放到缓存里降低数据库压力在线办公集成如果你想把博客扩展成一个小型内容管理平台可以研究 SpringBoot 集成 OnlyOffice 实现在线文档预览编辑这个功能在企业内部知识库场景下特别实用消息推送接一个 ActiveMQ 或 RabbitMQ实现文章发布后异步通知订阅用户体验感直接上一个档次如果你只是想快速搭一套带权限管理的系统也可以参考若依这类成熟的前后端分离脚手架。若依框架把用户、角色、菜单权限这些通用功能都封装好了代码结构清晰非常适合作为学习对象。不过我自己的建议是实战项目一定要自己从零写一遍核心链路参考别人的代码和直接抄别人的代码收获差距是很大的。6.3 写代码之外的一些心得最后分享一点这个项目之外的想法。很多人做前后端分离项目容易陷入一个误区只关注技术框架的使用却忽略了业务流程和工程化思维。比如登录功能看起来就是调一个接口拿个 Token但真正做完整了会发现里面还涉及密码加密存储、Token 过期续期、刷新令牌、权限控制粒度等一系列细节问题。再一个体会是项目的调试能力比写代码能力更值钱。这个博客系统开发过程中一半以上的时间花在排查问题上——版本冲突、跨域配置、路径映射、构建异常每一个问题排查清楚后对整体架构的理解就加深一层。所以遇到报错不要慌从日志的第一行往外读从配置的错误项往前推总能找到根因。个人博客这个项目我一直觉得是练手的最佳选择因为它有足够真实的业务场景又不会有复杂的并发和分布式问题分散你的注意力。把整个流程完整走下来你不仅能熟练掌握 SpringBoot 和 Vue 前后端分离开发模式更关键的是建立起一套从设计到开发再到部署的完整的项目思维这种能力是只看教程看不出来的。
返回列表