ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

SpringBoot个人博客系统:Thymeleaf+MyBatis-Plus毕设实战指南

SpringBoot个人博客系统:Thymeleaf+MyBatis-Plus毕设实战指南 简介这是一套基于SpringBoot 2.x、Thymeleaf与MyBatis-Plus开发的完整个人博客系统专为Java初学者与毕业设计学生打造覆盖MVC分层架构、Markdown文档编辑、博客目录自动生成等核心功能可作为Web全栈开发入门与课程设计的高质量参考项目。资源包共2899个文件涵盖360个HTML页面、875个JS脚本、213个CSS样式、128个Java后端类及273个PNG图像等完整呈现前后端一体化开发结构压缩包大小104.24MB内容包含项目源码、配置文件、静态资源及部分构建脚本如sh、bat、yaml目录组织规范便于模块化学习与二次开发。已有791人下载学习读者可直接运行Tomcat部署快速掌握SpringBoot整合Thymeleaf模板引擎、MyBatis-Plus简化CRUD、前端动态交互及开源插件集成等实战技能。1. 为什么毕业设计选个人博客系统SpringBoot Thymeleaf MyBatis-Plus 这套组合不是“凑数”而是能跑通、能答辩、能展示工程能力的最小可行闭环很多同学拿到“个人博客系统”这个毕设题目第一反应是不就是增删改查几页HTML但真正搭过三遍以上的人才知道——它恰恰是检验你是否真把 Web 开发主干链路串起来的试金石从请求进 Controller 的那一刻起路径怎么映射、参数怎么绑定、表单怎么校验、数据怎么落库、模板怎么渲染、分页怎么不翻车、富文本怎么安全插入、静态资源怎么加载、前后端交互边界在哪……全在这一套里暴露无遗。而 SpringBoot Thymeleaf MyBatis-Plus 这个组合不是随便拼的“热门词堆砌”它是当前高校教学与企业轻量后台开发中收敛度最高、文档最全、出错反馈最明确、调试路径最短的技术栈。Thymeleaf 原生支持 HTML 模板即视即得避免前端框架引入额外复杂度MyBatis-Plus 提供开箱即用的 CRUD 和分页插件省去手写 XML 的玄学调试SpringBoot 自动装配和 Actuator 健康检查让答辩时演示“系统活着”这件事变得毫无压力。这不是一个炫技项目而是一个能让你在 3 天内跑通首页、文章页、后台管理页并在第 4 天开始调样式、加校验、补日志的真实工程切片——适合想扎实走完一遍 Web 开发全流程的毕业生也适合需要快速交付可演示成果的课程设计。2. 从零初始化项目用 Spring Initializr 搭建骨架并确认三大组件版本兼容性2.1 创建项目并勾选核心依赖非默认项必须手动加Spring Initializr 官网或 IDE 内置向导创建新项目时基础依赖默认包含Spring Web和Lombok但以下三项需主动勾选或手动添加缺一不可Spring Boot DevTools开发期热重载必备答辩前可移除Spring Boot Configuration Processor自动生成application.yml提示写配置不靠猜Thymeleaf注意不要选Thymeleaf Layout Dialect它已过时且与 SpringBoot 3.x 不兼容提示若使用 SpringBoot 3.x推荐 3.2.x务必确认 JDK 版本 ≥ 17若用 2.7.x则 JDK 8–17 均可但 MyBatis-Plus 3.5.x 起已不再支持 JDK 8。生成项目后在pom.xml中检查并补全 MyBatis-Plus 依赖Initializr 不提供!-- MyBatis-Plus StarterSpringBoot 3.x 专用 -- dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-spring-boot3-starter/artifactId version4.3.0/version /dependency逻辑说明mybatis-plus-spring-boot3-starter是 SpringBoot 3.x 专属 starter它自动注册MybatisPlusAutoConfiguration并接管SqlSessionFactory创建。若误用旧版mybatis-plus-boot-starter启动时会报NoSuchBeanDefinitionException: No qualifying bean of type org.apache.ibatis.session.SqlSessionFactory——这是新手最常卡住的第一关。2.2 验证 Thymeleaf 模板能否被正确解析写一个“活口测试页”在src/main/resources/templates/下新建index.html!DOCTYPE html html xmlns:thhttp://www.thymeleaf.org head title博客首页/title /head body h1 th:text${title} ?: 欢迎来到我的博客占位标题/h1 p th:text当前时间 ${#dates.format(#dates.createNow(), yyyy-MM-dd HH:mm:ss)}时间占位/p /body /html再写一个 ControllerController public class IndexController { GetMapping(/) public String index(Model model) { model.addAttribute(title, 我的第一篇博客系统); return index; // 对应 templates/index.html } }启动应用访问http://localhost:8080/。若看到带格式的时间字符串和正确标题说明 Thymeleaf 解析链路通畅若返回白页或 404请立即检查templates/是否在src/main/resources/下不是src/main/java/spring.thymeleaf.cachefalse是否已在application.yml中设置开发期必开spring.thymeleaf.suffix: .html是否显式声明某些低版本 starter 默认为.xhtml3. 数据建模与 MyBatis-Plus 快速接入用实体类驱动数据库表结构3.1 设计博客核心四张表user、article、category、tag含逻辑关系毕业设计无需过度设计但字段必须覆盖常见业务场景。以下是经答辩验证过的最小可用模型MySQL 语法-- 用户表仅管理员不实现注册登录 CREATE TABLE user ( id bigint NOT NULL AUTO_INCREMENT, username varchar(50) NOT NULL COMMENT 用户名, password varchar(100) NOT NULL COMMENT BCrypt 加密密码, PRIMARY KEY (id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; -- 分类表 CREATE TABLE category ( id bigint NOT NULL AUTO_INCREMENT, name varchar(30) NOT NULL COMMENT 分类名, sort_order int DEFAULT 0 COMMENT 排序序号越小越靠前, PRIMARY KEY (id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; -- 标签表多对多中间表后续用 article_tag 关联 CREATE TABLE tag ( id bigint NOT NULL AUTO_INCREMENT, name varchar(20) NOT NULL, PRIMARY KEY (id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; -- 文章主表含富文本 content 字段 CREATE TABLE article ( id bigint NOT NULL AUTO_INCREMENT, title varchar(100) NOT NULL, slug varchar(100) COMMENT URL 友好别名如 /post/springboot-thymeleaf, content longtext NOT NULL COMMENT Markdown 或 HTML 内容, category_id bigint DEFAULT NULL, status tinyint DEFAULT 1 COMMENT 1-发布0-草稿, create_time datetime DEFAULT CURRENT_TIMESTAMP, update_time datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (id), KEY idx_category (category_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;参数说明slug字段用于 SEO 友好 URL如/post/my-first-blog避免?id123content用longtext而非text防止长文截断update_time的ON UPDATE CURRENT_TIMESTAMP是 MySQL 原生能力MyBatis-Plus 不需额外处理。3.2 用 MyBatis-Plus Generator 自动生成 Entity、Mapper、Service含 Lombok 注解不手写 POJO用官方代码生成器提升效率与一致性。添加依赖dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-generator/artifactId version3.5.6/version /dependency dependency groupIdorg.freemarker/groupId artifactIdfreemarker/artifactId /dependency编写生成器主类放在test/java下运行一次即可public class CodeGenerator { public static void main(String[] args) { AutoGenerator generator new AutoGenerator(); GlobalConfig config new GlobalConfig(); config.setOutputDir(System.getProperty(user.dir) /src/main/java); config.setAuthor(student); // 仅用于类注释 config.setOpen(false); // 生成后不自动打开文件夹 config.setSwagger2(true); // 启用 Swagger 注释答辩展示用 DataSourceConfig dataSourceConfig new DataSourceConfig(); dataSourceConfig.setUrl(jdbc:mysql://localhost:3306/blog_db?useSSLfalseserverTimezoneAsia/Shanghai); dataSourceConfig.setDriverName(com.mysql.cj.jdbc.Driver); dataSourceConfig.setUsername(root); dataSourceConfig.setPassword(123456); PackageConfig packageConfig new PackageConfig(); packageConfig.setModuleName(blog); packageConfig.setParent(com.example); StrategyConfig strategyConfig new StrategyConfig(); strategyConfig.setInclude(user, article, category, tag); // 指定表名 strategyConfig.setRestControllerStyle(true); strategyConfig.setEntityLombokModel(true); // 自动加 Data NoArgsConstructor 等 strategyConfig.setLogicDeleteFieldName(deleted); // 若需软删除此处声明字段名 generator.setGlobalConfig(config) .setDataSource(dataSourceConfig) .setPackageInfo(packageConfig) .setStrategy(strategyConfig); generator.execute(); } }运行后自动生成entity/User.java含TableName(user)、TableId(type IdType.AUTO)mapper/UserMapper.java继承BaseMapperUserservice/IUserService.java与UserServiceImpl.javacontroller/UserController.java含 RESTful 接口关键经验生成器默认不加TableField(fill FieldFill.INSERT_UPDATE)但update_time字段必须自动填充。需手动在Article实体类中添加TableField(fill FieldFill.INSERT_UPDATE) private LocalDateTime updateTime;并在MybatisPlusConfig中注册自动填充处理器见下节。4. 配置 MyBatis-Plus 高级能力自动填充、分页插件、SQL 性能分析4.1 注册 MetaObjectHandler 实现 create_time / update_time 自动赋值新建config/MybatisPlusConfig.javaConfiguration public class MybatisPlusConfig { Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor new MybatisPlusInterceptor(); // 分页插件必须在最前 interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); // 乐观锁插件按需启用 // interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor()); return interceptor; } Bean public MyMetaObjectHandler myMetaObjectHandler() { return new MyMetaObjectHandler(); } } Component class MyMetaObjectHandler implements MetaObjectHandler { Override public void insertFill(MetaObject metaObject) { this.strictInsertFill(metaObject, createTime, LocalDateTime.class, LocalDateTime.now()); // 起始版本号 3.3.0 this.strictInsertFill(metaObject, updateTime, LocalDateTime.class, LocalDateTime.now()); } Override public void updateFill(MetaObject metaObject) { this.strictUpdateFill(metaObject, updateTime, LocalDateTime.class, LocalDateTime.now()); } }逻辑说明strictInsertFill会检测字段是否为 null 再填充避免覆盖已有值LocalDateTime.now()返回的是 JVM 本地时间若服务器时区非东八区需在application.yml中统一配置spring: jackson: time-zone: GMT8 date-format: yyyy-MM-dd HH:mm:ss4.2 配置分页插件并验证/article/list?page1size10能返回 Page
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进