做 Java 这些年,带过新人,也帮人改过不少课程设计和毕业设计,我发现一个很普遍的现象:很多人能照着教程写几个 CRUD 接口,但一让他独立搭一个完整项目就卡壳——表怎么设计、目录怎么分、配置怎么写、部署到服务器上要注意什么,全是坑。个人博客系统恰恰是解决这个问题的绝佳载体。今天要聊的这套基于 Java + Spring Boot 的个人博客系统,把源码、配套文档、运行视频、讲解视频四样东西都配齐了,目的很直接:让一个刚学完 Java 基础和 Spring Boot 的人,能照着这套东西把一个完整项目跑起来、吃透它的设计思路,最后改成自己的作品。
这套系统不复杂,但“麻雀虽小五脏俱全”。文章发布、分类归档、标签聚合、评论互动、后台管理,一个典型博客该有的模块全都有。如果你正在纠结毕业设计选题,或者想找个能完整落地、又不至于劝退的 Spring Boot 练手项目,这篇内容基本能当操作手册用。我会从技术选型、功能模块、运行部署、常见坑点、二开建议这几个维度展开,把我实际搞这套项目时的思路和经验都写出来。
1. 项目定位与整体设计思路
1.1 这套博客系统包了哪些东西
先理清楚项目交付物是什么。除了源码本身,这套项目的价值在于配套资料齐全:一份文档负责讲明白数据库初始化和配置项修改,一个运行视频演示从导入 IDEA 到启动成功的全过程,还有一个讲解视频专门拆代码结构和核心逻辑。对于刚开始接触完整项目的人来说,这种“文档 + 视频 + 源码”三合一的组合,能有效避免“代码拿到了但不知道怎么跑”的尴尬。
功能层面,前台是访客视角的博客展示:首页文章列表、文章详情、分类页面、标签页面、关于我、时间归档;后台是管理员的创作管理:登录认证、文章新增与编辑、分类和标签维护、评论管理。这样的功能划分和大多数个人博客系统保持了一致,既不会因为模块太少而失去练习价值,也不会因为过度设计而让新手看不懂。
1.2 技术栈选型:为什么以 Spring Boot 为核心
个人博客这种项目,技术选型的第一原则是“够用且能学到东西”。传统 SSM(Spring + Spring MVC + MyBatis)当然也能做,但 XML 配置能写到你怀疑人生。Spring Boot 最大的贡献是自动化配置和起步依赖(Starter),把过去一大堆繁琐的配置收敛到几个注解和一份简洁的application.yml里,内置的 Tomcat 又让你不用单独部署 War 包,一个java -jar就能跑起来。
本项目采用 Spring Boot 2.7.x 系列作为基础版本,搭配 MyBatis-Plus 操作数据库,前端使用 Thymeleaf 模板引擎 + Bootstrap 搭建页面,数据库选用 MySQL。这套组合是当前国内 Java 学习圈最常见的技术路线,网上资料多、遇到问题容易搜到答案,对新手极其友好。Spring Boot 的核心优势在于“约定优于配置”,它已经帮你把 MVC、Jackson、日志、连接池这些基础组件都配置好了,你只需要关注自己的业务代码。
1.3 分层结构与工程目录设计
拿到源码后第一件事,先看包结构。这套项目遵循标准的 Controller → Service → Mapper 三层架构,外加 entity(实体类)、config(配置类)、common(通用返回与工具类)。目录划分大概是这样的:
com.example.blog ├── controller // 控制层,接收请求、返回视图或数据 ├── service // 业务层,处理核心逻辑 ├── mapper // 数据访问层,MyBatis-Plus 的 Mapper 接口 ├── entity // 数据库实体类 ├── config // 配置类,如拦截器、WebMvc 配置 └── common // 统一返回结果、异常处理、分页封装这样的分层看似朴素,但逻辑边界非常清晰:Controller 不写业务,Service 不碰 SQL,Mapper 只做数据读写。新人最容易犯的毛病就是在一个方法里把请求解析、业务处理、数据库操作全堆在一起,当时觉得很爽,后期改一个需求能把自己绕晕。分层的目的不是代码量变多,而是让每一层都能独立测试、独立替换,这也是以后进公司写真实项目时的基本素养。
2. 核心功能模块拆解与实现要点
2.1 文章管理模块:Markdown 编写与展示链路
文章是博客的核心资产,这个模块的设计直接决定用户体验和后台操作的顺畅度。文章表的字段设计要兼顾展示和检索,常见的字段包括:主键 id、标题 title、摘要 summary、正文内容 content、封面图 cover、分类 id、创建时间、更新时间、浏览量、是否置顶、是否发布。
正文存储格式这里要说明白:项目中建议正文以 Markdown 原文存库,页面展示时再做渲染。为什么要这么做?因为 Markdown 是纯文本,方便编辑、方便迁移,也方便做全文检索;而如果直接存渲染后的 HTML,后续想换主题或改样式就非常被动。
实现上,前端编辑器可以使用 Editor.md(国内很流行的开源 Markdown 编辑器),它自带预览功能;后端渲染可以用 commonmark-java 库。核心链路是:管理员在后台用 Editor.md 编写并预览 → 表单提交 Markdown 源码到后端 → 存入数据库 → 访客访问文章详情页时,后端将 Markdown 渲染成 HTML 再交给 Thymeleaf 模板展示。注意渲染一定要做在服务端,不要把 Markdown 原文直接通过 Thymeleaf 的th:utext输出,那样会有 XSS 风险——如果用户可以在内容里插入恶意 script,危害很大。使用专门的安全渲染库虽然不能说 100% 免疫所有攻击,但至少能过滤掉最常见的那批危险标签。
2.2 分类与标签:两种维度管理文章的差别
分类和标签本质上都是给文章分组的,但设计上有讲究。分类一般是单层、一对多的关系,一篇文章属于一个分类,一个分类下有多篇文章,用category_id字段挂在文章表上即可;标签则是多对多关系,一篇文章可以打多个标签,一个标签可以对应多篇文章,必须用中间表article_tag来维护关联。
表结构设计如下:
category表:id,name,descriptiontag表:id,namearticle_tag中间表:article_id,tag_id
不要嫌中间表麻烦。如果图省事把标签存成一个以逗号分隔的字符串字段,刚开始确实方便,但等你要做“点击标签查看所有相关文章”的时候,就得用模糊匹配去捞数据,这种 SQL 在数据量上来之后效率非常差,而且完全没法做关联统计。中间表虽然多一张表,但查询逻辑一目了然,后期加功能也容易,这个设计债不能欠。
查询标签相关的文章时,可以用 MyBatis-Plus 的 QueryWrapper 先查到文章 id 列表,再回表查文章详情;数据量大一点也可以写自定义 SQL 用 JOIN 一次查出。建议后者,因为少一次回环,SQL 执行计划也更可控,这也是看讲解视频时要重点理解的地方。
2.3 评论模块:从表设计到防刷的简单处理
评论是博客互动的重要组成部分,设计时要把“游客可评论”和“管理员可删评”这两个需求考虑进去。评论表核心字段有:id,article_id,nickname,email,content,parent_id,created_at。这里parent_id是为了支持楼中楼回复,顶级评论该字段为 0,回复某条评论时记录它的 id,前端展示时按层次渲染。
评论提交做两道防线就够了。第一道是后端校验:内容不能为空、长度限制在合理范围(比如 200 字以内)、昵称不能带 HTML 标签。第二道是时间校验:用 Session 记录用户上次评论时间,两次评论间隔小于 30 秒就直接拒绝,这能挡住大批脚本刷评论的请求。
这里有个容易忽略的点:评论内容在展示到页面上之前一定要做 HTML 转义,把<、>转成实体字符,否则别人在评论区写一段<script>,你整个站就沦陷了。Thymeleaf 默认的th:text本身就带转义,但如果你手痒用了th:utext,就等于亲手把后门打开了。这种低级错误在真实项目中出过太多事故了,务必重视。
2.4 后台认证与拦截器实现
博客后台不能裸奔,必须做登录认证。这套项目的处理方式不复杂——登录成功后把管理员信息放进 Session,同时定义一个拦截器,对/admin/**路径下的请求做拦截,未登录一律重定向到登录页。拦截器里实现HandlerInterceptor接口,在preHandle里检查 Session 是否存在管理员标识。
实际写拦截器时有两个容易踩的坑。第一个是拦截范围别把静态资源也拦了,CSS、JS、图片这些资源路径要记得在配置里排除,否则页面加载时样式全丢,给人感觉项目坏了。第二个是登录请求本身不能被拦,/admin/login这个路径必须放行,否则永远进不了登录页,死循环。
如果想让项目更有练习价值,可以把逻辑再升级一层:登录成功后生成一个 Token,用 Redis 存储并设置过期时间,前端每次请求把 Token 放在 Header 里,拦截器里核对 Token。这种方案代表了无状态登录的基本思路,今后接触 Spring Security 或 JWT 时会更容易理解。不过对于当前这套个人博客系统,Session 方案已经足够,加了 Redis 反而让项目复杂度上升,除非你想把它作为二次开发的一个练手方向。
3. 环境准备与项目运行实操
3.1 本地开发环境的版本匹配建议
很多人在“跑不起来”这一步就放弃了,原因多半是环境版本不匹配。这里先给出一套经过验证的本地环境组合:
| 组件 | 推荐版本 | 说明 |
|---|---|---|
| JDK | JDK 8 或 11 | 对应 Spring Boot 2.7.x,兼容性最好 |
| Maven | 3.6.3 及以上 | 版本别太老,依赖下载会出问题 |
| MySQL | 5.7 或 8.0 | 5.7 更稳定,8.0 需要调整时区配置 |
| IDEA | 2022 及以上 | 对 Spring Boot 和 Maven 支持更友好 |
| Navicat / DataGrip | 任意版本 | 用于可视化导入 SQL |
特别强调 JDK 和 Spring Boot 的对应关系。Spring Boot 2.7.x 用 JDK 8 编译运行是最稳的;如果你把项目升级到 Spring Boot 3.x,那 JDK 最低也要 17,而且包名从javax换成了jakarta,很多 import 语句要跟着改。这个问题在热词里有“springboot版本太高”这一条,真实情况也是这样——不少人在 IDEA 里用 Spring Initializr 生成项目,默认拉到了 3.x 版本,结果 JDK 还是 8,编译直接报错。所以拿到这套源码后,先确认你本机的 JDK 版本再决定要不要动 Spring Boot 版本。
MySQL 8.0 的时区问题也提一下,连接 URL 里必须带serverTimezone=Asia/Shanghai,否则驱动会报时区异常。很多新手在这一步栽跟头,其实不是代码问题,就是配置缺了参数。
3.2 数据库初始化与配置文件修改
源码里通常会附带一个blog.sql脚本,里面建好了所有表,还预置了管理员的账号密码(一般是默认的 admin / admin123,首次登录后记得改)。用 Navicat 或命令行执行source blog.sql就能完成初始化。
关键配置集中在src/main/resources/application.yml里,需要改的地方就三处:
server: port: 8080 spring: datasource: url: jdbc:mysql://localhost:3306/blog?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai username: root password: root driver-class-name: com.mysql.cj.jdbc.Driver换成本机的数据库账号密码就完事了。有一点注意:MySQL 5.7 的驱动类可以写com.mysql.jdbc.Driver,但 MySQL 8.0 建议用com.mysql.cj.jdbc.Driver,两者兼容性有细微差别,统一用新版驱动类最省心。
3.3 从源码到跑起来的完整步骤
整个启动流程我建议按这个顺序操作,可以少走很多弯路:
用 IDEA 的
Open功能选择源码目录,选择 Maven 项目导入,等待依赖下载完成。如果 IDEA 提示 Maven 未配置,先在File → Settings → Build Tools → Maven里配置好本地仓库路径。打开
blog.sql,在本地 MySQL 中执行,建库建表。修改
application.yml中的数据库账号密码,确认端口没有被占用。找到启动类
BlogApplication.java,右键运行。控制台出现
Started BlogApplication in x.x seconds字样后,浏览器访问http://localhost:8080。访问
http://localhost:8080/admin进入后台登录页,用默认账号登录,创建第一篇文章。
整个过程如果顺利,五六分钟就能跑起来。但这些步骤里随便哪一步不对,报错信息都能让新手懵半天——这正是运行视频存在的意义,它会把每一步的鼠标操作和界面反馈都录进去,卡住了对着视频逐帧比对就行。
3.4 运行视频里不会讲的几个启动细节
有些细节运行视频往往一带而过,但实际影响很大。第一,IDEA 首次导入 Maven 项目时,右下角会提示是否自动导入,一定要选开启,不然后面改pom.xml里的依赖不会自动更新。第二,如果依赖下载慢,在 Maven 的settings.xml里配置阿里云镜像,这能省一大半时间。第三,启动失败时别只看红色的异常堆栈,先看最下面一行Caused by:的内容,那才是真正的根因。
还有一个非常容易忽略的点:确认本机 8080 端口没被其他程序占用。Windows 下用netstat -ano | findstr 8080查一下,如果被占用,直接把application.yml里的端口改成 8081 或其他可用端口就行,不需要和别人抢。
4. 常见问题排查与避坑指南
4.1 Spring Boot 版本太高引发的兼容性问题
前面提过的“springboot版本太高”是绝对的高频坑,这里展开说。如果你在 IDEA 新建项目时直接选了 Spring Boot 3.x,或者把原有项目升级了,会碰到三类典型报错:
javax.servlet找不到:Spring Boot 3.x 把 JavaEE 标准换成了 Jakarta EE,所有javax.*包名要改成jakarta.*。涉及面很广,包括HttpServletRequest、ServletContext等,手动改起来很麻烦。- JDK 版本不兼容:Spring Boot 3.x 要求 JDK 17 以上,如果你本机只有 JDK 8,编译阶段直接失败。
- 部分第三方组件不支持:比如比较老的 MyBatis-Plus 版本在 Spring Boot 3.x 下会启动失败,需要换成对应适配版本。
所以我的建议很简单:这套个人博客系统用 Spring Boot 2.7.x + JDK 8 是最稳的组合,别追求版本新。新版本带来的特性在这个项目里基本用不上,反而徒增兼容性风险。真正理解 Spring Boot 的核心思想之后再玩 3.x,心态和排查能力都完全不一样了。
4.2 数据库连接报错排查实录
数据库相关的报错占了新手问题的一半以上。最经典的几种情况:
Access denied for user 'root'@'localhost':账号密码错了,或者 root 只允许 localhost 连接。检查application.yml里的 username 和 password。Unknown database 'blog':SQL 脚本没执行成功,或者库名写错了。用 Navicat 连上 MySQL,确认左边能看到 blog 库和里面的表。The server time zone value ... is unrecognized:连接 URL 没加serverTimezone=Asia/Shanghai,加上就好。Public Key Retrieval is not allowed:MySQL 8.0 的配置问题,在连接 URL 后面追加allowPublicKeyRetrieval=true。
这些报错看着吓人,其实都是配置层面的小事。排查时养成一个习惯:先确认数据库能通过 Navicat 正常连接,再确认账号密码是复制粘贴的而不是手敲的(手敲容易把字母 O 和数字 0 搞混),最后再看 Spring Boot 的具体异常信息。
4.3 页面样式丢失与静态资源 404
系统跑起来后页面能用,但样式全是裸的,这通常是静态资源配置或拦截器的问题。Spring Boot 默认的静态资源路径是classpath:/static/,HTML 里引用的 CSS 路径要写相对路径或带上下文路径。
如果配置了拦截器,检查是否把/css/**、/js/**、/images/**这些静态资源路径放行了。经验之谈:拦截器配置里宁可多放行也不要少放行,比如/static/**、/webjars/**这些常见前缀,漏一个就掉一个样式的坑。
还有一个隐蔽问题:Thymeleaf 模板路径写错不会立即报错,而是页面渲染时出现 404 或空白。比如@{}表达式引用路径不对,资源找不到只是静默失败。排查时按 F12 打开开发者工具看 Network 面板,红色请求对应的就是缺失的资源。
4.4 常见问题速查表
| 现象 | 大概率原因 | 快速解决办法 |
|---|---|---|
项目启动报Port 8080 was already in use | 端口被占用 | 换个端口或杀掉占用进程 |
编译报cannot find symbol: class HttpServletRequest | 包名或版本不匹配 | 确认是 Spring Boot 2.x 还是 3.x,调整 JDK 版本 |
访问/admin一直跳登录页 | 登录状态没写入 Session | 核对登录逻辑,看 Session 存储的用户标识 |
| 首页能开但图片全部裂开 | 静态资源路径问题 | 检查图片路径和上传目录配置 |
| 中文乱码 | 编码不一致 | 数据库连接 URL 加characterEncoding=utf-8,文件存为 UTF-8 |
| Markdown 内容显示成纯文本 | 没有渲染 | 确认后端是否正确调用渲染组件转成 HTML |
这张表基本覆盖了我见过的 90% 的启动和运行期问题,建议收藏。项目遇到问题时先对着表自查一遍,往往比自己瞎改半天有效。
5. 源码阅读路线与二次开发扩展建议
5.1 一份源码应该按什么顺序去读
拿到源码别打开 IDEA 就乱翻,容易越看越迷茫。我推荐的阅读顺序是:先跑起来 → 再看数据库表 → 再读包结构 → 再按功能链路读代码。
具体一点,你可以从一个完整的请求入口开始顺藤摸瓜。比如“管理员在后台编辑一篇文章并保存”这个操作:
- 找到
AdminArticleController,看它接收了哪个请求路径和参数。 - 进入
ArticleService的保存方法,看它做了哪些校验和组装。 - 看
ArticleMapper的插入或更新 SQL,理解数据库层面的变化。
跟着这样的链路走完两三个功能之后,你会发现整套代码其实就是“请求进来 → 控制器收参数 → 服务层处理 → 数据层存取”的循环。所谓讲解视频,核心价值就在这里——它把这条主线路径直接给你画好了,配合源码读起来效率翻倍。
5.2 二次开发值得动手的 4 个方向
博客系统跑通只是起点,真正提升能力的是二次开发。我根据实际经验给你排了四个由易到难的方向:
接入 Redis 做文章浏览量缓存:每次访问文章都更新数据库的浏览量字段,数据量大了会频繁触发写操作。用 Redis 先做计数,定时同步回 MySQL,这是一个非常经典且实用的缓存练习。
全文搜索改造:现在的搜索大概率是
LIKE %keyword%,数据量一大就慢。试试给文章标题建全文索引,或者引入 Elasticsearch 做搜索服务,后者算是架构层面的升级。第三方登录:后台登录改成支持 GitHub / Gitee OAuth 授权登录。这个功能在企业项目中非常常见,做完以后你对 OAuth2.0 的理解就不是停留在概念上了。
图片上传走 OSS:把本地存储的图片改成上传到阿里云 OSS 或 MinIO,涉及到签名生成、文件类型校验、访问域名配置等一系列实战问题。
每个方向做完,你都可以把效果和踩坑过程整理成一篇文章,这本身就是对自己技术总结能力的一次锻炼。
5.3 文档和视频的正确使用节奏
配套的文档和视频,很多人是拿到手就从头看到尾,看完觉得都会了,一动手还是不会。我建议反过来用:先花十分钟自己尝试跑项目,卡住了再对着运行视频找对应的操作步骤;跑起来之后自己看代码,看不懂的地方再到讲解视频里找对应片段。视频应该是“索引”而不是“替代”,它帮你定位知识盲区,但永远替代不了你自己敲代码和改 bug 的过程。
还有一个使用技巧:运行视频里如果用的数据库账号密码和你的本机不一样,不要照着抄,一定要改成你自己的。看着视频里没问题,直接复制配置到自己的机器上就各种报错,问题就出在这里。
6. 最后分享一个自己的体会
博客系统这种项目,技术难度确实不高,但它在学习路径上的价值被严重低估了。把一个博客从零做成能跑、能上线、能被人访问,你经历的不只是写代码,还有建表设计、配置管理、问题排查、部署发布这一整条真实项目的链条。我见过很多刷了几百道面试题的人,面对“讲讲你做过的项目”这个问题支支吾吾,就是因为从来没有完整地拥有过一个项目。
如果你拿到这套源码,我的建议是别急着收藏吃灰,花一个周末的时间,按文档跑起来,按视频看一遍,再按我上面说的链路跟读两三个核心功能,最后动手改一个小功能——比如给文章加一个阅读时长估算。当你真正把别人的源码变成自己熟悉的东西时,这个项目才算真正属于你了。以后再遇到什么大项目,你会发现无非是多了一些业务复杂度和技术组件,底层的分层思想、配置思路、排错路径,都是一样的。