
简介这份基于Java的个人博客系统设计与实现资料包面向计算机相关专业毕业生和Java学习者可作为毕业设计选题、系统开发、文档撰写与答辩准备的完整参考。压缩包大小为178.52MB内含项目报告、答辩PPT、源代码、数据库文件及演示录像各文件分工明确报告覆盖设计与实现过程PPT用于答辩展示源码可导入开发工具运行数据库文件便于快速构建数据环境录像则直观呈现系统功能效果。目前已有141人学习下载尤其适合博客系统或内容管理类毕设项目。由于项目已通过验收并具备可运行性读者既能借助报告梳理论文结构也能通过源码和数据库进行二次开发再配合演示录像查漏补缺能够有效节省从零搭建、编码到最终汇报的周期整体上手门槛对有一定Java基础的读者较为友好。1. 基于Java的个人博客系统难的不是写代码而是交付完整链路一个基于Java的个人博客系统放在课程设计或毕业设计里难度并不在CRUD本身。用户注册、文章发布、评论、分类标签这些功能任何一个学过Java基础的人都能写出来。真正拉开差距的是这套题目背后挂着的「项目报告答辩PPT源代码数据库演示录像」完整交付物。评审老师拿到压缩包后会先看目录层级是否合理再抽几个核心技术点提问最后直接运行源码验证。代码、文档、答辩材料任何一环有短板整体评价都会掉一档。这篇顺着一名Java开发做完这个题目的完整思路来写从技术选型开始到数据库设计与核心实现再到报告、PPT与演示录像的组织把一条两周内能落地的路径讲清楚。适合正在做课程设计、毕设重构以及想用完整个人项目补充简历的Java从业者。2. Java个人博客系统的技术栈选型与三层架构落法2.1 先从「答辩会被追问什么」倒推选型个人博客系统的功能边界很清晰核心模块是用户、文章、分类、评论、标签外加一个后台管理界面。可「怎么做」的前提是答辩时能说清每个请求从浏览器进来之后经过哪几层。这些年课程设计里最常见的有三条路纯Servlet JSP JDBC的手写MVC方案Spring Boot Thymeleaf MyBatis的服务端渲染方案以及Spring Boot Vue的前后端分离方案。选型如果只追求代码量最少Spring Boot全家桶几乎不需要思考但如果是数据库课程设计或者J2EE课程结课评审往往会顺着「请求处理链路」往下追问。所以选型第一步不是看哪个流行而是看你手头这门课讲的什么。课程内容围绕Servlet展开就用手写MVC把web.xml的映射背下来能答很多题课程没有强制约束用Spring Boot是更接近行业习惯的选择。提示选型没有绝对对错但报告里必须写清「为什么不用另一套」。多数被扣分的项目不是技术选错而是没有交代选型依据。2.2 三种技术方案的取舍参数用一个表把关键差异列出来写报告时可以直接引用这组对比对比维度Servlet JSP JDBCSpring Boot ThymeleafSpring Boot Vue 前后端分离答辩追问深度低可逐层解释请求流转中需说清自动配置高需解释跨域、Token与接口规约编码量与调试成本中低高报告常用术语MVC、Filter、Session自动配置、事务、AOP、MapperREST、JWT、Axios、跨域SEO与页面直出直出直出需要额外做SSR演示准备时间短短长个人博客有SEO诉求搜索引擎抓取的是服务端渲染出来的HTML正文这是Thymeleaf方案比前后端分离更适合这个题目的重要理由。第二个理由是Thymeleaf的模板和原生HTML几乎同构改样式、加页面不用重新编译演示时快速调整也方便。第三项目的权限模型只有游客、登录用户和管理员三类引入Spring Security的完整过滤器链路会掩盖核心业务代码量反而拖累答辩讲解。2.3 三层架构落到代码包里应该长什么样无论底层是Servlet还是Spring Boot代码包结构上都要能看出Controller、Service、DAO三层。src/main/java/com/example/blog/ ├── controller/ # 请求入口PostController、UserController、CommentController ├── service/ # 业务接口与实现PostService、CommentService、TagService ├── mapper/ # MyBatis Mapper接口对应 resource/mapper/*.xml ├── model/ # 实体User、Post、Category、Comment、Tag ├── config/ # 拦截器注册、WebMvc配置 └── common/ # 统一返回对象、全局异常、工具类controller层只做参数接收、校验和结果包装service层处理业务规则与事务mapper层负责SQL映射。个人博客里最简单的两条规则——“只有登录用户能发文”“用户只能删除自己的文章”——必须放在service层而不是controller里。答辩时评委问控制层为什么这么薄这个结构本身就是答案。2.3.1 登录与权限检查放在哪里拦截器是最合适的位置。Spring Boot里注册拦截器只需要实现WebMvcConfigurerConfiguration public class WebConfig implements WebMvcConfigurer { Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new LoginInterceptor()) .addPathPatterns(/admin/**) .excludePathPatterns(/admin/login); } }/admin/**是后台管理路径白名单只放行登录页本身未登录请求会被重定向到登录页。这个设计在演示录像里比直接弹401更友好而且在报告里展示“访问控制”模块时评审能看到一个完整的请求被拦截链路而不是零散写在每个Controller里的重复判断。2.4 Spring Boot 2.7.x的最小依赖与三个关键配置以JDK 8环境为例pom.xml里放这几项起步依赖就够用dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-thymeleaf/artifactId /dependency dependency groupIdorg.mybatis.spring.boot/groupId artifactIdmybatis-spring-boot-starter/artifactId version2.3.2/version /dependency dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId scoperuntime/scope /dependencyspring-boot-starter-web内置Tomcat和Jackson序列化不需要额外配服务器thymeleaf用于服务端页面渲染mybatis-spring-boot-starter必须显式给版本号因为社区版的坐标跟Spring Boot的BOM不是完全同步的2.3.x是在JDK 8下兼容性最好的一个线。对应的application.yml里三个参数对运行结果影响最直接spring: datasource: url: jdbc:mysql://localhost:3306/blog_db?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver thymeleaf: cache: false mybatis: mapper-locations: classpath:mapper/*.xml type-aliases-package: com.example.blog.model configuration: map-underscore-to-camel-case: true第一serverTimezoneAsia/Shanghai是MySQL 8.x驱动的必填参数缺失时启动直接报连接异常第二map-underscore-to-camel-case: true把create_time自动映射为实体的createTime省掉每个实体写Results的样板代码第三thymeleaf.cache: false在演示阶段关闭模板缓存改动HTML后刷新页面即可生效不需要重启应用。把这三点写进项目报告的配置说明里信息量比贴整份配置要高。2.4.1 手写Servlet方案的编码过滤器配置如果学校课程要求走Servlet/JSP那么web.xml里最容易被忽略的是编码过滤器filter filter-nameencodingFilter/filter-name filter-classorg.springframework.web.filter.CharacterEncodingFilter/filter-class init-param param-nameencoding/param-name param-valueUTF-8/param-value /init-param init-param param-nameforceEncoding/param-name param-valuetrue/param-value /init-param /filter filter-mapping filter-nameencodingFilter/filter-name url-pattern/*/url-pattern /filter-mappingforceEncoding必须为true它同时控制请求编码与响应编码。只写encodingUTF-8时Servlet容器对POST表单体默认按ISO-8859-1解码中文标题打出来全是问号。个人博客系统里所有中文输入都走这条过滤器这一处配置错了后续的代码再正确也白搭。3. 个人博客系统的数据库设计与核心功能实现从核心表结构到文章发布链路3.1 博客系统最少需要几张表课程设计层面的个人博客表数量控制在5到7张比较合理。太少显得系统单薄太多会在报告篇幅和答辩时间上失控。推荐的最小集合是六张表用户表、文章表、分类表、评论表、标签表再加一张文章与标签的关联表。表名核心字段关联关系说明t_userid, username, password, nickname, avatar, create_time文章表作者、评论表评论人t_categoryid, category_name, description文章通过category_id关联t_postid, title, content, summary, category_id, user_id, views, status, create_time多对一关联分类多对一关联作者t_commentid, post_id, user_id, content, create_time多对一关联文章与用户t_tagid, tag_name标签主表t_post_tagpost_id, tag_id多对多关系拆出的关联表字段设计上面有三个决策点。t_post.content用LONGTEXT而不是TEXT因为正文要存Markdown原文还可能渲染出一两万字符的HTMLTEXT的64KB上限在极端情况下会踩边界status用TINYINT而不是布尔值发布、草稿、审核中这三种状态未来都能扩展username必须建唯一索引登录查询每条都依赖它。3.2 建表SQL里需要体现的设计细节CREATE TABLE t_post ( id BIGINT NOT NULL AUTO_INCREMENT COMMENT 文章ID, title VARCHAR(100) NOT NULL COMMENT 文章标题, content LONGTEXT NOT NULL COMMENT 正文内容(Markdown原文), summary VARCHAR(255) DEFAULT NULL COMMENT 摘要, category_id BIGINT NOT NULL COMMENT 分类ID, user_id BIGINT NOT NULL COMMENT 作者ID, views INT NOT NULL DEFAULT 0 COMMENT 浏览量, status TINYINT NOT NULL DEFAULT 0 COMMENT 0-草稿 1-发布, create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (id), KEY idx_category (category_id), KEY idx_create_time (create_time) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT文章表;CHARSET用utf8mb4而不是utf8MySQL 8的utf8实际上是utf8mb3遇到生僻字或数学符号会存储失败这也是“数据库课程设计”里被问得最多的问题之一。update_time用ON UPDATE CURRENT_TIMESTAMP自动维护Java侧就不用每次拼时间字符串。idx_create_time和idx_category是给首页按时间倒序、按分类筛选这两个高频查询用的。这里刻意不建物理外键个人博客的分类删除需要应用层先处理文章归属物理外键会在批量更新时引入顺序约束报告里写“通过应用层保证参照完整性”即可自圆其说。3.3 文章发布一个一分钟场景拆成四步文章发布是个人博客里最能体现工程细节的模块。前端提交来的表单里包含标题、正文、分类ID、标签列表后端要把这四类数据组织到三张表里。核心方法这样写Override Transactional(rollbackFor Exception.class) public Long createPost(PostCreateRequest request, Long userId) { // 1. 标题与正文必须存在标题上限100字避免超长title撑破页面 if (!StringUtils.hasText(request.getTitle()) || !StringUtils.hasText(request.getContent())) { throw new BlogException(标题和正文都不能为空); } // 2. 摘要缺省时取正文去标签后的前200字 Post post Post.builder() .title(request.getTitle().trim()) .content(request.getContent()) .summary(resolveSummary(request)) .categoryId(request.getCategoryId()) .userId(userId) .status(1) .build(); postMapper.insert(post); // 3. 标签去重并建立关联关系 handleTags(post.getId(), request.getTags()); return post.getId(); } private String resolveSummary(PostCreateRequest request) { if (StringUtils.hasText(request.getSummary())) { return request.getSummary(); } String plainText htmlToText(request.getContent()); return plainText.length() 200 ? plainText.substring(0, 200) : plainText; }Transactional(rollbackFor Exception.class)这个参数是答辩时会被专门追问的地方。Spring默认只对RuntimeException和Error回滚自定义的BlogException如果继承的是Exception而不加这个属性文章主表写入了、标签关联失败了事务也不会回滚数据库里就留下了一篇无标签的孤儿文章。resolveSummary先调htmlToText去掉HTML标签再截断避免摘要里残留div这类不闭合标签。handleTags内部先按标签名查询存在就复用tagId不存在则插入新标签最后向t_post_tag批量写入关联。3.4 列表查询用动态SQL处理三个可选条件首页列表通常同时支持分类筛选和标题模糊搜索再加上分页。三个条件任意组合用where标签最干净select idselectPageByCondition resultTypecom.example.blog.model.Post SELECT p.id, p.title, p.summary, p.views, p.create_time, c.category_name AS categoryName FROM t_post p LEFT JOIN t_category c ON p.category_id c.id where if testcategoryId ! null AND p.category_id #{categoryId} /if if testkeyword ! null and keyword ! AND p.title LIKE CONCAT(%, #{keyword}, %) /if AND p.status 1 /where ORDER BY p.create_time DESC LIMIT #{offset}, #{pageSize} /selectwhere标签会自动去掉第一个条件前面的多余AND三个条件全部为空时生成的SQL依然合法。模糊匹配用CONCAT(%, #{keyword}, %)而不是在Java里拼%后者会把用户输入里的特殊符号直接拼进SQL存在注入窗口。分页直接手写LIMIT个人博客单表数据量万级以内手动分页的效率与可读性都优于引入PageHelper插件还少一个版本兼容问题需要防守。3.5 项目报告里的数据库章节按什么顺序写报告里的数据库设计部分建议按四个小节组织概念结构设计画E-R图、关系模式转换说明重点写出多对多如何拆关联表、物理设计说明字段类型与字符集选择依据、索引设计说明。很多人的报告只贴三样东西——ER图、建表SQL、功能截图缺少“为什么这样设计”的论证。写索引时不需要把每条查询都建索引只需说清楚“列表按时间倒序所以建create_time索引分类聚合频繁所以建category_id索引”这比罗列全部索引更能体现设计判断力。4. 个人博客系统的项目报告与答辩PPT组织顺序4.1 报告目录对齐三个可验证维度项目报告不需要堆功能列表需要让评审在10分钟内确认系统是真实的、可运行的、可扩展的。推荐目录顺序是需求分析、概要设计、数据库设计、详细设计与核心代码、测试与部署、总结。整份报告里最重的是“详细设计”这一章而这一章的每一小节都应该遵循“功能需求 → 流程时序 → 关键代码 → 验证方式”的顺序组稿。写报告时有一组对比很常见看一眼就知道差距在哪评分项常见错误写法推荐写法需求分析复制题目要求原文从游客、博主、管理员三个角色画用例图概要设计只贴模块清单系统架构图加请求流转描述数据库设计直接贴全部建表SQLER图加表清单加字段选择理由详细设计整段贴Controller代码贴核心Service方法加时序说明系统测试写“功能均正常”写前置条件、操作步骤、预期与实际结果测试部分不是用来展示测试理论的给两张截图就够了一张是文章发布成功后列表页出现新数据的截图一张是未登录访问后台被重定向到登录页的截图。这两张图分别证明“写入链路通”和“访问控制生效”比一张全页面截图有效得多。4.2 答辩PPT页数与每页停留时长一份合格的答辩PPT控制在12到15页页数越多评委越容易抓着边缘内容问。建议的时间分配如下页码区间内容推荐讲解时长1-2封面、系统功能结构图30秒3技术选型对比与依据30秒4-6数据库核心表ER图与关系模式60秒7-10核心功能截图与关键代码高亮90秒11难点与解决过程60秒12-13测试结果与总结30秒第11页“难点”不是用来卖惨的挑两个真问题写中文编码问题如何通过过滤器解决、事务回滚边界如何通过rollbackFor修正。每个难点都按“现象 → 排查 → 修复 → 验证”四步写评委看到的是解决问题的能力而不是代码堆砌。4.3 安全模块要准备的三行代码答辩里高频追问之一是“密码怎么存的”。最低限度的正确做法是BCrypt哈希BCryptPasswordEncoder encoder new BCryptPasswordEncoder(); // 注册时加密存储登录时只比对结果不还原明文 String encodedPwd encoder.encode(rawPassword); boolean matched encoder.matches(inputPassword, encodedPwd);BCrypt每次encode产生的密文都不同因为内部带随机盐matches会从密文中解析盐重新计算。相比MD5加盐BCrypt的哈希计算被刻意设计得更慢暴力破解的成本高一个数量级。个人博客登录频率很低单次几十毫秒的额外开销完全可接受。这组代码放进报告安全性问题基本就过关了。4.4 应对“你的系统跟前人有什么区别”这道题考察的是独立工作量和思考深度。可以从三个方向提前准备一是用AOP切面统一记录操作日志而不是在每个Controller里重复写日志代码二是用ThreadLocal持有当前登录用户而不是让Controller之间通过参数层层传递userId三是讲清楚为什么在服务端渲染场景下选Session而不是JWT。三者不需要全写进报告选一个做深就能形成明显区分度。这和Java面试八股文里常问的事务传播、过滤器与拦截器本质上是同一组知识能把它在项目里讲出落地场景比背概念更有说服力。5. 个人博客系统演示录像录制前必调的三个运行参数5.1 JVM编码参数中文不乱码是录像的地基Windows环境下JVM默认文件编码是GBKSpring Boot应用打印中文日志或处理路径里的中文文件名时控制台可能出现乱码。录制前在IDEA的VM options里加上-Dfile.encodingUTF-8并在启动命令中一并带上-Dfile.encodingUTF-8 -jar blog-0.0.1-SNAPSHOT.jar。编码类的Bug在开发时容易被忽略一旦录进视频里非常显眼。如果视频中出现了乱码后期重录的成本远高于提前加上这个参数。5.2 HikariCP空闲回收参数避免录制中偶发500演示节奏通常是操作几秒钟、讲解几十秒页面长时间停在某个位置。此时MySQL连接被HikariCP空闲回收下一次点击文章详情需要重新建连接如果中途遇到网络抖动或驱动超时就会在录像里出现一次无法解释的500。建议把空闲回收时间调大spring: datasource: hikari: maximum-pool-size: 10 connection-timeout: 30000 idle-timeout: 600000maximum-pool-size: 10对个人博客系统绰绰有余idle-timeout: 600000表示连接空闲10分钟才回收覆盖一段完整的录像录制时间。这个参数值不需要写进项目报告但放在演示环境里能显著降低翻车概率。5.3 种子数据与自增ID的两种准备演示录像里最影响观感的是空页面。录制前准备8到10篇测试文章覆盖四种形态标题超过30个字符的长标题、包含代码块的正文、摘要超过两行的文章、同一分类下至少3篇文章。这些数据能一次性验证列表布局、摘要截断、分类聚合和分页交互四个功能点。如果担心内容重复影响观感再执行一遍TRUNCATE并重置自增ID让数据库里的ID从1开始连续排列答辩时被问到数据量时也能给出干净的回答。录制完成后用播放器快速过一遍关键操作节点重点看每次页面跳转是否与讲解对得上。分辨率选1280x720还是1920x1080并不重要重要的是视频里数据库控制台和浏览器页面两个窗口不要互相遮挡评审在快进时依然能通过视频右侧的时间戳定位到对应功能阶段。本文还有配套的精品资源点击获取