简介:这是一套基于 Vue 与 SpringBoot 开发的个人博客项目源码,面向具备 Java 与前端基础、希望完整实践前后端分离架构的开发者,可用于课程设计、毕业设计或二次开发学习。项目后台管理页面采用 Vue 编写,其余页面使用 Thymeleaf 模板,后端整合 Shiro+Jwt 鉴权、MyBatisPlus、MySQL 与 Redis,前端涉及 ElementUI、axios、vue-router、Vuex、WebSocket 及 vue-cli4,并支持管理员在线分配角色权限与用户端目录缓存。压缩包共 530 个文件,以 js、html、java、css 为主,另含 png、jpg 等图片资源及 sql 建库脚本、yml 配置与字体文件,整体约 4.27MB,目录结构清晰,便于按前后端模块检索。目前已有 1344 人学习下载,适合借此理解博客系统的权限设计、缓存策略与前后端联调流程。
1. 前后端分离博客从零跑通:这套 Vue+SpringBoot 源码能省你多少事
手里有一套能直接跑起来的前后端分离博客源码,和从零搭一套,中间差的不只是几天时间。最近把一套基于 Vue + SpringBoot2 的个人博客项目完整拆了一遍,从数据库建表到前端打包部署,走通了整条链路。它解决的核心问题很具体:让你跳过脚手架选型、接口联调、权限框架拼装这些重复劳动,直接进入「改业务、换皮肤、加功能」的阶段。适合两类人——想快速拥有一个能写文章、能管理的个人站点,又不想被现成 SaaS 平台绑死的开发者;以及想拿一个结构完整、技术栈主流的项目练手 Java 后端与 Vue 前端联调的学生或转行者。技术栈是 MySQL + SpringBoot2 + Vue,前后端分离,接口走 REST,鉴权用 Token,属于当前招聘市场上出现频率最高的一类组合。
这套东西不是玩具 Demo。它把博客该有的东西都摆齐了:文章发布与分类标签、评论、后台管理、登录鉴权、分页查询。你拿到手之后真正要做的判断是:它的分层结构合不合理、接口设计能不能扩展、数据库字段够不够用。下面按「先看清结构、再动手跑通、然后踩坑排错、最后做二次开发」的顺序拆,每一步都落到能复制的命令和能改的参数上。
2. 拆开源码看骨架:分层结构、依赖与数据库设计
拿到一个陌生项目,我一般不看 README,先看目录树和 pom。目录结构决定了这个项目的作者有没有分层意识,pom 决定了它依赖了哪些轮子、版本有没有埋雷。这套项目的后端是标准的 Controller-Service-Mapper 三层,前端是 Vue 单页应用加路由,前后端通过/api前缀的接口通信。
2.1 后端目录与 Maven 依赖清单
后端根目录下是典型的 SpringBoot 结构,src/main/java里按controller、service、mapper、entity、config、utils分包。这种分法不新鲜,但对博客这种业务量不大的系统足够用,好处是新人接手时找代码路径清晰。真正要看的是pom.xml里的依赖版本,它直接决定你本地能不能一次编译通过。
<!-- pom.xml 关键依赖,版本以实际文件为准 --> <dependencies> <!-- Web 层,提供 REST 接口能力 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- MyBatis 持久层,配合 XML 写 SQL --> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.x</version> </dependency> <!-- MySQL 驱动,注意 8.x 与 5.x 的驱动类名不同 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <!-- Lombok,实体类靠它省 getter/setter --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> </dependencies>这段依赖里有两个地方最容易翻车。一是 MyBatis starter 的版本,2.x 系列对应 SpringBoot2,如果你本地 JDK 是 17 而项目是按 JDK8 写的,编译期可能报模块访问异常,稳妥做法是把 JDK 切到 8 或 11 再跑。二是 MySQL 驱动,8.x 的驱动类是com.mysql.cj.jdbc.Driver,5.x 是com.mysql.jdbc.Driver,连接串里还要带时区和 SSL 参数,否则启动时数据源初始化直接失败。Lombok 则要求 IDE 装插件并开启注解处理,不然实体类全是红色报错,很多人第一次跑不起来就卡在这。
2.2 数据库表结构与字段含义
博客系统的表不多,但字段设计能看出作者有没有想过扩展。核心表大致是用户表、文章表、分类表、标签表、文章标签关联表、评论表。下面这张表是我从建表脚本里整理出来的关键字段,实际字段名以源码 SQL 文件为准。
| 表名 | 关键字段 | 作用与注意点 |
|---|---|---|
| 用户表 | id、username、password、avatar | 密码字段看是否做了加密存储,明文就是安全隐患 |
| 文章表 | id、title、content、category_id、status、create_time | status 区分草稿与已发布,前端列表要按它过滤 |
| 分类表 | id、name、sort | sort 控制前台展示顺序,别忽略 |
| 标签表 | id、name | 与文章是多对多,靠关联表维系 |
| 评论表 | id、article_id、content、parent_id | parent_id 支持楼中楼,为空表示一级评论 |
建表脚本一般在src/main/resources下的.sql文件里,导入时注意字符集统一用utf8mb4,否则文章里带表情符号会存成问号。文章正文如果字段类型是TEXT,长文可能不够用,改成LONGTEXT更稳。这些细节不改也能跑,但上线写几篇长文之后就会回来找原因,属于典型的后悔药场景。
2.3 前端工程结构与接口约定
前端是 Vue CLI 生成的标准结构,src下有views、components、router、api、store几个目录。api目录里按模块拆了请求文件,统一用 axios 实例,拦截器里挂 Token。这里要重点看vue.config.js里的代理配置,它决定了开发阶段前端请求怎么打到后端。
// vue.config.js 开发代理配置 module.exports = { devServer: { port: 8080, proxy: { '/api': { target: 'http://localhost:9090', // 后端实际端口,按 application.yml 改 changeOrigin: true, pathRewrite: { '^/api': '' } // 后端接口没带 /api 前缀时去掉 } } } }target必须和后端application.yml里的server.port一致,这是联调失败最高频的原因。pathRewrite要不要写,取决于后端 Controller 上的@RequestMapping有没有/api前缀,两边对不上就是一片 404。我一般先把后端跑起来,用浏览器直接访问一个接口确认返回正常,再回来配代理,这样能把问题范围缩小到前端一侧。
3. 本地跑通全链路:环境、配置与启动顺序
结构看清之后就是动手。这套项目的启动顺序有讲究:先数据库、再后端、最后前端。顺序反了会出现前端页面白屏、接口全红的情况,排查起来反而更费时间。下面按我实际操作的顺序写,每一步都给命令和要改的配置项。
3.1 环境准备与数据库导入
先确认本机三样东西的版本:JDK、Maven、Node。JDK 建议 8 或 11,Maven 3.6 以上,Node 建议 14 或 16,Node 版本过高时老版本 Vue CLI 的依赖可能装不上。MySQL 用 5.7 或 8.0 都行,但驱动和连接串要对应。
# 1. 建库并导入建表脚本 mysql -u root -p -e "CREATE DATABASE blog_db DEFAULT CHARACTER SET utf8mb4;" mysql -u root -p blog_db < src/main/resources/blog.sql # 2. 确认表已建好 mysql -u root -p -e "USE blog_db; SHOW TABLES;"导入之后别急着启动,先看一眼建表脚本里有没有初始管理员账号的 INSERT 语句。有的话记下用户名密码,没有的话你得自己往用户表插一条,密码字段如果是加密的,还得用项目里的加密工具生成密文再插,直接写明文登录会失败。这一步是很多新手卡住的地方,现象是登录接口一直返回认证失败,其实数据库里压根没有可用账号。
3.2 后端配置修改与启动
后端要改的配置集中在application.yml,主要是数据源、端口、文件上传路径三项。
server: port: 9090 # 与前端代理 target 保持一致 spring: datasource: url: jdbc:mysql://localhost:3306/blog_db?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false username: root password: 你的密码 driver-class-name: com.mysql.cj.jdbc.Driver # MySQL 8.x 用这个类名 mybatis: mapper-locations: classpath:mapper/*.xml # XML 映射文件位置,写错就报找不到语句连接串里的serverTimezone不写,MySQL 8 会报时区错误;useSSL=false在本地开发时省掉证书告警。mapper-locations如果和实际目录对不上,启动不报错,但一调接口就抛Invalid bound statement,这个报错看着吓人,本质就是 XML 没被扫描到。配置改完执行启动:
# 在项目根目录,跳过测试加快启动 mvn spring-boot:run -DskipTests # 或者先打包再运行 mvn clean package -DskipTests java -jar target/blog-0.0.1-SNAPSHOT.jar看到控制台打印 Tomcat 启动端口和耗时,说明后端起来了。此时用浏览器或 curl 访问一个不需要鉴权的接口,比如文章列表,确认返回 JSON 正常,再往下走。
3.3 前端依赖安装与联调
前端进入目录后先装依赖,再起开发服务。国内网络环境下 npm 装包慢是常态,配个镜像源能省不少时间。
# 安装依赖,建议锁定版本避免依赖漂移 npm install # 启动开发服务器 npm run serve启动成功后控制台会给一个本地地址,通常是 8080。打开页面,如果文章列表能出来,说明代理和接口都通了;如果页面能开但数据为空,先看浏览器 Network 面板里请求的 URL 和状态码,404 查代理前缀,401 查 Token 是否带上,500 就回后端看日志。这个三段式排查法比盲目改代码有效得多。前后端都跑通之后,建议立刻做一次完整操作:登录后台、发一篇文章、前台看到它、再删掉。走完这一圈,你才算真正验证了这套源码的可用性。
4. 避坑与排查:五个让项目跑不起来的真实原因
同一套源码,有人半小时跑通,有人折腾两天,差别基本都在这几个点上。下面五条是我在拆这类项目时反复遇到的,按「现象 → 原因 → 解决」写,照着对号入座就行。
4.1 启动报数据源初始化失败
现象是应用启动阶段直接退出,日志里出现Failed to configure a DataSource或连接被拒绝。原因通常是application.yml里的库名、账号密码和本地 MySQL 不一致,或者 MySQL 服务根本没启动。解决方式是先用命令行mysql -u root -p手动连一次,确认账号能进、库存在,再回头核对 yml 里的四项配置。还有一种隐蔽情况:密码里带特殊字符,在 yml 里没加引号被解析错,给密码加上单引号即可。
4.2 接口报 Invalid bound statement
现象是后端能启动,但一调某个接口就抛org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)。原因是 MyBatis 没找到对应的 XML 映射文件,可能是mapper-locations路径写错,也可能是 XML 里的namespace和 Mapper 接口全限定名对不上。解决时先确认target/classes/mapper下有没有编译后的 XML,没有就是资源没被打包,需要在 pom 的resources里把**/*.xml包含进去;有的话就逐字核对 namespace 和方法 id。
4.3 前端请求全部 404
现象是页面能打开,但所有数据接口都返回 404。原因多半是vue.config.js的代理target端口和后端实际端口不一致,或者pathRewrite把不该去的前缀去掉了。解决方式是打开浏览器开发者工具,看请求实际发到了哪个地址,再对照后端 Controller 的完整路径。我一般会临时把pathRewrite注释掉试一次,能通就说明是前缀问题,不能通就查端口。
4.4 登录成功但刷新后掉登录态
现象是登录后能进后台,一刷新页面就退回登录页。原因是 Token 只存在了内存或 Vuex 里,没持久化到 localStorage,刷新即丢失。解决方式是在登录成功后把 Token 写入 localStorage,axios 请求拦截器里从 localStorage 读取并塞进请求头,路由守卫里也改成读 localStorage 判断。改的时候注意退出登录要同步清除,否则会出现「退了还能进」的怪现象。
4.5 文章图片上传后访问 404
现象是后台上传图片成功,但前台展示时图片地址打不开。原因是上传目录是服务器本地路径,而返回给前端的 URL 没有对应的静态资源映射。解决方式是在后端配置类里加一个WebMvcConfigurer,把上传目录映射成可访问的 URL 前缀,同时确认上传路径在配置文件里是绝对路径而非相对路径。这个坑在本地开发时容易被忽略,一部署到服务器就暴露。
5. 二次开发与验证:把通用博客改成你自己的
跑通只是起点,这套源码真正的价值在于它的结构够你往上加东西。二次开发我建议从三个方向入手,每个方向都能验证你对这套代码的理解程度。第一个方向是换皮,改前端主题色和布局,验证的是你对组件结构和样式作用域的把控;第二个方向是加功能,比如给文章加阅读量统计,需要动数据库字段、Mapper、Service、Controller 和前端展示,一条链路走完,前后端联调就彻底熟了;第三个方向是改鉴权,把简单的 Token 校验换成带角色区分的权限控制,验证的是你对拦截器和注解的理解。
加阅读量这个功能最能说明问题,因为它跨了所有层。数据库给文章表加一个views字段,Mapper 里加一条自增更新语句,Service 在查询详情时调用它,Controller 不用改,前端详情页展示即可。这里有个细节要注意:自增更新要放在查询之前还是之后,放错顺序会导致本次访问不计入。我一般放在查询之后异步执行,避免影响详情接口的响应时间。
-- 文章表增加阅读量字段 ALTER TABLE article ADD COLUMN views INT DEFAULT 0 COMMENT '阅读量';<!-- ArticleMapper.xml 中新增自增语句 --> <update id="increaseViews" parameterType="int"> UPDATE article SET views = views + 1 WHERE id = #{id} </update>改完之后怎么验证没改坏?我的习惯是每次动完一个功能,把「登录 → 发文 → 列表 → 详情 → 评论 → 删除」这条主链路手动走一遍,再顺手看一眼后端日志有没有异常堆栈。这套流程看着笨,但能挡住绝大多数低级错误。从那以后我每次拿到这类前后端分离的源码,都强制先跑通主链路再动一行代码,因为基线不清的情况下改出来的问题,你根本分不清是新引入的还是原本就有。希望帮到你。
本文还有配套的精品资源,点击获取