简介:这是一套基于Spring Boot的个人博客系统完整源码与数据库资源,面向具备Java Web基础、希望练习前后台整合开发的学生与开发者,可用于课程设计、毕业设计或技术栈实战演练。压缩包共598个文件,约92.43MB,涵盖29个Java源文件、30个HTML页面、70个JavaScript脚本、58个CSS样式、119个XML配置及1个SQL数据库脚本,另含图片、字体、依赖jar等静态资源,结构完整便于直接导入IDEA运行。系统前台基于Thymeleaf与jQuery实现用户登录、文章分页展示、详情查看与评论;后台采用Spring MVC+Spring Boot+MyBatis整合,支持登录、系统数据展示及文章的发布、修改与删除,共设计6张数据表,并引入Redis做缓存管理。目前已有5048人学习下载,读者可借此掌握Spring Boot项目搭建、MyBatis持久层配置、前后台数据交互与缓存集成的完整思路,快速理解博客类系统的业务分层与目录组织方式。
1. 基于 Spring Boot 的个人博客系统:从源码到数据库,一套能跑起来的落地路径
很多人第一次接触 Spring Boot 项目,都是从「个人博客系统」开始的。它不像商城、SaaS 那样一上来就堆几十张表,但麻雀虽小五脏俱全:用户登录、文章发布、分类标签、评论、分页查询,一个都不少。你拿到一份「源码+数据库」的压缩包,真正卡住你的往往不是代码看不懂,而是环境跑不起来、数据库连不上、表结构和实体对不上。这篇笔记就围绕这套基于 Spring Boot 的个人博客系统,把源码结构、数据库设计、启动配置、接口调试和常见翻车点讲清楚。适合正在做 Java 课程设计、想拿一个完整项目练手、或者准备把博客系统改成自己作品集的开发者。读完你能独立把项目在本地跑通,并且知道每个参数该改哪里。
2. 先看清这套源码的骨架:Spring Boot 博客系统到底由哪些层组成
2.1 从目录结构判断项目用的是哪种分层方式
拿到源码先别急着点运行,先看目录。常见的 Spring Boot 博客系统一般分两种组织方式:按层分包(controller、service、mapper、entity)和按功能分包(article、user、comment)。前者适合新手,后者适合后续扩展。你打开src/main/java下面的包名,基本就能判断作者的习惯。
一个典型的按层分包结构长这样:
src/main/java/com/example/blog ├── controller // 接收前端请求 ├── service // 业务逻辑 │ └── impl ├── mapper // 数据库访问接口 ├── entity // 数据库表对应实体 ├── dto // 前端传参对象 ├── vo // 返回给前端的对象 ├── config // 拦截器、跨域、MyBatis 配置 └── BlogApplication.java看到mapper包,基本可以确定用的是 MyBatis 或 MyBatis-Plus。看到repository包,多半是 Spring Data JPA。这两种在博客系统里都很常见,但配置方式完全不同。MyBatis 需要写 XML 或注解 SQL,JPA 靠方法名自动生成查询。你如果不先确认这一点,后面改数据库连接会一直报错。
resources目录同样关键。application.yml或application.properties里藏着数据库地址、端口、日志级别。mapper文件夹下如果有 XML 文件,说明 SQL 写在 XML 里,改字段名时要同步改 XML 和实体类,漏一个就查不出数据。
2.2 数据库表结构和实体类的对应关系怎么核对
博客系统的数据库通常有 5 到 8 张表:用户表、文章表、分类表、标签表、文章标签关联表、评论表。你拿到.sql文件后,先别直接导入,打开看一眼建表语句和字段类型。
| 表名 | 关键字段 | 对应实体 | 常见坑 |
|---|---|---|---|
| user | id, username, password, avatar | User | 密码是否加密存储 |
| article | id, title, content, user_id, category_id, create_time | Article | content 用 text 还是 longtext |
| category | id, name | Category | 名称是否唯一 |
| tag | id, name | Tag | 和文章是多对多 |
| article_tag | article_id, tag_id | 无独立实体 | 联合主键容易漏 |
| comment | id, article_id, user_id, content, parent_id | Comment | parent_id 支持楼中楼 |
核对方法很简单:打开实体类,看@TableName或@Table注解指定的表名,再看每个字段的@TableField或@Column是否和数据库列名一致。常见翻车是数据库用下划线命名create_time,实体用驼峰createTime,但没开驼峰映射,结果查出来全是 null。MyBatis-Plus 默认开启驼峰转换,MyBatis 原生需要手动配map-underscore-to-camel-case: true。
提示:导入 SQL 前先确认数据库版本。MySQL 5.7 和 8.0 在字符集和默认排序规则上有差异,
utf8和utf8mb4混用会导致 emoji 存入报错。
2.3 启动类之外,哪些配置决定了项目能不能跑起来
BlogApplication.java本身通常只有一行SpringApplication.run,真正决定成败的是配置文件。你需要重点看四个地方:数据库连接、端口、文件上传路径、日志。
数据库连接串里,url后面的参数最容易被忽略。比如serverTimezone=Asia/Shanghai不加,MySQL 8.0 可能报时区错误;useUnicode=true&characterEncoding=utf8不加,中文标题可能乱码。端口默认 8080,如果被占用就改成 8081。文件上传路径如果是本地磁盘路径,换电脑后要同步改,否则头像和封面图全部 404。
spring: datasource: url: jdbc:mysql://localhost:3306/blog?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai username: root password: your_password driver-class-name: com.mysql.cj.jdbc.Driver servlet: multipart: max-file-size: 10MB max-request-size: 10MB server: port: 8080这段配置里,driver-class-name在 MySQL 8.0 之后必须用com.mysql.cj.jdbc.Driver,老版本用com.mysql.jdbc.Driver会提示已废弃。max-file-size不调大,上传封面图超过 1MB 就直接抛异常。这些参数不改,项目启动日志看着正常,一操作就报错。
3. 把源码跑起来:数据库导入、依赖安装和启动命令的完整顺序
3.1 数据库导入:先建库再导表,字符集一次设对
第一步永远是建库。不要直接导入 SQL 文件,先手动创建数据库并指定字符集:
CREATE DATABASE blog DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; USE blog;然后导入表结构和初始数据。如果你用的是 Navicat 或 dbx 这类数据库管理工具,右键数据库选择「运行 SQL 文件」,选中源码里的.sql文件执行。命令行方式更直接:
mysql -u root -p blog < blog.sql导入完成后,执行SHOW TABLES;确认表数量。常见问题是 SQL 文件里带了CREATE DATABASE语句但没指定字符集,导入后中文变成问号。解决办法是删库重建,或者用ALTER TABLE逐张表改字符集。更省事的做法是导入前用编辑器把 SQL 文件开头的建库语句改成utf8mb4。
初始数据里通常有一个默认管理员账号,密码可能是明文也可能是 MD5。如果是明文,登录后第一件事就是改密码;如果是 MD5,你需要知道原始密码才能登录,一般在 README 或 SQL 注释里会写。找不到就自己插一条新用户记录,密码字段用 MD5 工具生成。
3.2 Maven 依赖拉取:换源和跳过测试的两个实用参数
数据库准备好后,用 IDEA 或命令行打开项目。Maven 会自动下载依赖,但默认中央仓库在国内速度很慢。在settings.xml里配阿里云镜像:
<mirror> <id>aliyunmaven</id> <mirrorOf>*</mirrorOf> <name>阿里云公共仓库</name> <url>https://maven.aliyun.com/repository/public</url> </mirror>配好后执行编译命令。第一次跑建议跳过测试,因为测试类可能连的是另一个数据库:
mvn clean package -DskipTestsclean清掉旧编译产物,package打包成 jar,-DskipTests跳过测试执行但依然编译测试代码。如果依赖里有spring-boot-starter-test但数据库没配好,不跳过测试会直接失败。打包成功后,target目录下会出现一个可执行 jar。
注意:如果项目用的是 Gradle,命令换成
./gradlew clean build -x test。先看项目根目录有没有pom.xml或build.gradle,别搞混。
3.3 启动项目:java -jar 和 IDE 运行的区别与选择
启动方式有两种。IDE 里直接运行BlogApplication的main方法,适合调试,改代码后热部署生效快。命令行java -jar适合验证打包结果:
java -jar target/blog-0.0.1-SNAPSHOT.jar --spring.profiles.active=dev--spring.profiles.active=dev指定使用application-dev.yml配置。如果项目没有多环境配置,去掉这个参数。启动日志里看到Started BlogApplication in X seconds就算成功。如果卡在HikariPool或Tomcat相关日志,多半是数据库连不上或端口被占用。
启动后浏览器访问http://localhost:8080。如果返回 Whitelabel Error Page,说明项目起来了但没有配首页控制器,这时候访问/login或/index试试。前端页面通常在resources/static或resources/templates下,前后端不分离的项目直接访问对应路径即可。
4. 接口调试与数据库增删改查:验证博客系统核心功能是否正常
4.1 用 curl 和 Postman 验证文章列表与详情接口
项目跑起来后,先测最核心的文章接口。假设控制器映射是/api/article,列表接口通常是 GET 请求:
curl -X GET "http://localhost:8080/api/article/list?page=1&size=10" -H "Accept: application/json"返回 JSON 里应该有code、msg、data三个字段,data里是文章数组和总数。如果返回 401,说明接口被拦截器拦了,需要先登录拿 token。如果返回 500,看控制台异常栈,多半是 SQL 写错或字段映射失败。
详情接口一般传文章 id:
curl -X GET "http://localhost:8080/api/article/1" -H "Accept: application/json"这里容易翻车的是 id 类型。数据库用 bigint,前端传字符串,后端用 Long 接收,一般没问题。但如果用了@PathVariable("id") int id,文章 id 超过 21 亿就溢出。博客系统虽然不至于,但养成用 Long 的习惯没坏处。
4.2 数据库增删改查:从 SQL 到 Mapper 的对应检查
博客系统的增删改查集中在文章和评论上。你改一个字段,要同时检查四个地方:数据库列、实体属性、Mapper XML 或注解、前端传参名。漏一个就出现「新增成功但列表不显示」或者「更新后字段没变」。
以新增文章为例,Mapper XML 里常见写法:
<insert id="insertArticle" parameterType="Article"> INSERT INTO article (title, content, user_id, category_id, create_time) VALUES (#{title}, #{content}, #{userId}, #{categoryId}, NOW()) </insert>#{userId}对应实体里的userId属性,如果实体写的是user_id,这里就取不到值,插入变成 null。NOW()是数据库函数,如果实体里也有createTime并且前端传了值,两者会冲突,建议只保留一种。
查询列表时,分页参数用LIMIT还是插件,决定了你改 SQL 的方式。MyBatis-Plus 的分页插件会自动拼LIMIT,你手写 SQL 时如果又加了一次LIMIT,就会报语法错误。判断方法:看config包里有没有PaginationInterceptor或MybatisPlusInterceptor的 Bean。
4.3 评论和分类接口的联调顺序
评论依赖文章和用户,分类依赖文章。联调顺序建议:先测分类列表,再测文章列表,最后测评论。因为评论查询通常要 join 用户表拿头像和昵称,如果用户表没数据,评论接口返回空数组但不报错,你会误以为接口坏了。
分类接口一般有树形结构,parent_id为 0 是顶级分类。如果返回的分类列表是平铺的,前端需要自己组装成树。这一步在博客系统里经常被简化,你看到category表只有 id 和 name 两个字段,说明不支持多级分类,别硬加。
提示:调试接口时打开 MyBatis 的 SQL 日志,在配置里加
logging.level.com.example.blog.mapper=debug,控制台会打印实际执行的 SQL 和参数,比猜快得多。
5. 避坑与排查:个人博客系统源码跑不通的 5 个高频问题
5.1 启动报错 Access denied for user:数据库账号密码不对
现象:启动日志里出现java.sql.SQLException: Access denied for user 'root'@'localhost'。
原因:配置文件里的用户名或密码和本地 MySQL 不一致。很多人本地 MySQL 密码是空的或者自己改过,但源码里写的是123456。
解决:打开application.yml,把username和password改成你本地实际的值。如果 MySQL 是 8.0 且用了caching_sha2_password插件,老版本驱动连不上,要么升级驱动,要么改用户认证插件:ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '新密码';。
5.2 页面 404 但接口能通:静态资源路径没配对
现象:/api/article/list返回正常 JSON,但访问http://localhost:8080显示 404。
原因:前端页面放在resources/templates下,但没有配 Thymeleaf 或模板引擎依赖;或者页面放在static下的子目录里,访问路径没带子目录名。
解决:先看pom.xml有没有spring-boot-starter-thymeleaf。有的话,控制器要返回视图名而不是 JSON。没有的话,页面应该在static目录下,直接访问文件名,比如http://localhost:8080/index.html。前后端分离的项目,前端单独跑一个端口,后端只提供接口,404 是正常的。
5.3 中文乱码:字符集从数据库到前端一路要统一
现象:文章标题在数据库里正常,页面上显示问号;或者前端提交中文,存进数据库变成乱码。
原因:数据库字符集、连接串字符集、前端页面编码三者不一致。常见是数据库用了latin1,或者连接串没加characterEncoding=utf8。
解决:按顺序检查。数据库执行SHOW VARIABLES LIKE 'character%';,确保character_set_database是utf8mb4。连接串加useUnicode=true&characterEncoding=utf8。前端 HTML 的<meta charset="UTF-8">不能少。三步都对了,乱码基本消失。
5.4 分页查询返回总数不对:count 语句被插件改写
现象:文章列表每页 10 条,但总数显示 10 而不是 100。
原因:MyBatis-Plus 分页插件会自动生成 count 语句,但如果你的 SQL 里有GROUP BY或DISTINCT,自动 count 可能不准。
解决:手写 count 查询,在 Mapper 里单独定义一个selectCount方法,分页插件配置里指定countSql或关闭自动 count。更简单的办法是看插件版本,老版本对复杂 SQL 支持不好,升级到最新稳定版通常能解决。
5.5 上传图片后访问 404:文件路径和映射没对上
现象:头像上传成功,数据库里也有路径,但浏览器访问图片地址返回 404。
原因:文件存到了本地磁盘某个目录,但 Spring Boot 没有把这个目录映射为静态资源路径。
解决:在配置类里加资源映射:
@Configuration public class WebConfig implements WebMvcConfigurer { @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/upload/**") .addResourceLocations("file:" + System.getProperty("user.dir") + "/upload/"); } }/upload/**是访问路径,file:后面是实际存储目录。存文件时用同一个目录,路径就对上了。Windows 和 Linux 的路径分隔符不同,用System.getProperty("user.dir")拼相对路径比写死D:/或/home/更稳。
6. 把博客系统改成自己的作品:三个进阶技巧和验证方法
6.1 用 Spring Boot 日志定位慢查询,而不是靠猜
博客系统文章多了以后,列表接口变慢。别急着加缓存,先开 SQL 日志看执行时间。在application.yml里加:
logging: level: com.example.blog.mapper: debug控制台会打印每条 SQL 和耗时。如果某条查询超过 500ms,看它有没有走索引。文章表按create_time排序分页,就给create_time加索引:
ALTER TABLE article ADD INDEX idx_create_time (create_time);加完再测,耗时通常从几百毫秒降到几毫秒。这个验证方法比任何理论都直接:改之前记时间,改之后再记一次,对比数字。
6.2 把硬编码的配置抽成环境变量,方便换机器
源码里数据库密码、文件路径、端口经常写死在application.yml。换一台电脑就要改一遍,容易漏。改成环境变量引用:
spring: datasource: url: ${DB_URL:jdbc:mysql://localhost:3306/blog?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai} username: ${DB_USER:root} password: ${DB_PASSWORD:123456}${DB_URL:默认值}的意思是:先读环境变量DB_URL,读不到就用冒号后面的默认值。这样本地开发不用设环境变量,部署到服务器时设一下就行。验证方法:本地不设任何环境变量启动,能跑通;然后export DB_PASSWORD=新密码再启动,看是否用了新密码。
6.3 用接口测试代替手动点页面,回归更快
每次改完代码手动点页面验证,效率低还容易漏。用curl写一个简单的回归脚本:
#!/bin/bash BASE="http://localhost:8080" echo "文章列表:" curl -s "$BASE/api/article/list?page=1&size=5" | head -c 200 echo "" echo "文章详情:" curl -s "$BASE/api/article/1" | head -c 200 echo "" echo "分类列表:" curl -s "$BASE/api/category/list" | head -c 200三个接口都返回 JSON 且没有error字段,说明核心链路正常。这个脚本可以放进 CI,每次提交自动跑。我自己的习惯是改完 Mapper 先跑一遍这个脚本,比打开浏览器快得多,也避免了自己骗自己「应该没问题」。
这套基于 Spring Boot 的个人博客系统,源码和数据库本身不复杂,难的是环境配置和字段对应。把上面这些参数和排查点过一遍,基本能跑通九成以上的同类项目。后面想加 Redis 缓存、Markdown 渲染、全文检索,都是在这个骨架上叠,不会动到根基。希望帮到你。
本文还有配套的精品资源,点击获取