资讯动态

JavaEE博客系统实战:Shiro+MySQL+富文本,从部署到答辩避坑指南

发布时间:2026/9/28 12:52:14 来源:尧图企业网站定制
简介这份资源是一套基于JavaEE与MySQL实现的个人博客系统完整项目包面向计算机相关专业的毕业设计、课程设计、大作业及工程实训人群也适合希望从零理解Java Web开发流程的进阶学习者。项目围绕博主端后台管理展开涵盖登录与Shiro安全认证、博客发布与富文本编辑、博客类别维护、评论审核与信息管理、个人信息修改以及友情链接、密码修改、缓存刷新等系统管理模块结构完整、业务闭环清晰。压缩包为zip格式整体约179.66MB内含源码、数据库SQL脚本、论文、答辩PPT及配套视频可分别用于代码复现、数据库建表、文档撰写与答辩演示。目前已有95人学习下载适合需要一套可直接参考的完整赛题方案、快速搭建开发环境并对照论文梳理设计思路的读者。1. 从一份能跑通的 JavaEE 博客系统说起它到底能帮你省下多少时间如果你正在为课程设计或毕业设计找一套能跑通、能改、能写进论文的 JavaEE 项目这套基于 JavaEE MySQL 的个人博客系统值得先看一眼。它不是那种只有几个静态页面的“演示壳”而是把博主端后台该有的模块都做全了Shiro 安全登录、富文本写博客、博客类别管理、评论审核、个人信息维护、友情链接和系统缓存刷新。换句话说从登录到发文到评论审核这条主链路是完整的数据库 SQL、论文、答辩 PPT 和演示视频也一并给了。这套东西最适合两类人一类是刚接触 JavaWeb、想找一个结构清晰的项目照着跑一遍的新手另一类是要交毕设、需要一份能讲清楚模块划分和数据库设计的进阶学习者。它解决的核心问题不是“教你 Java 语法”而是给你一个已经落地的工程骨架让你把精力放在理解流程、改功能和写文档上而不是从零搭环境。下面我按实际拆包和部署的顺序把这份资源怎么用、参数怎么配、哪里容易翻车讲清楚。2. 环境搭建与数据库导入把 MySQL 和 JDBC 连接先理顺2.1 技术栈选型为什么是 Shiro MySQL 富文本这套系统用 Shiro 做安全管理不是随便选的。Shiro 的认证流程比手写 Filter 清晰得多前台提交账号密码Shiro 的 Realm 去数据库查用户密码经过加密运算后再比对。这样做的好处是你后面要加角色权限、记住我、验证码都能在现有配置上扩展不用推翻重来。数据库用 MySQL 也是同类项目里最稳的选择资料多、Navicat 和 Workbench 都能连导入 SQL 文件基本不会遇到字符集之外的坑。富文本编辑器这块原文写的是百度富文本编辑器常见做法是 UEditor 或类似组件。它的作用是把博客正文以 HTML 形式存进数据库前台渲染时直接输出。这里要注意富文本存的是带标签的内容数据库字段类型得够大一般用text或longtext别用varchar(255)否则长文直接截断这是新手最容易踩的坑之一。2.2 数据库导入与字符集设置拿到资源后第一步不是急着启动项目而是先把 MySQL 装好、把 SQL 文件导进去。MySQL 安装教程网上很多这里只讲和这个项目直接相关的部分。导入前先确认两件事数据库版本和字符集。SQL 文件如果是用旧版本导出的在高版本 MySQL 上可能报语法错误常见做法是先用文本编辑器打开 SQL 文件看开头有没有SET NAMES utf8;之类的语句。-- 创建数据库时显式指定字符集避免中文乱码 CREATE DATABASE blog_db DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; -- 导入前先切到目标库 USE blog_db; -- 如果 SQL 文件里没有建库语句就手动建有的话直接 source 导入 -- source /path/to/blog.sql;上面这段的逻辑是先建一个字符集为utf8mb4的库再导入表结构和数据。utf8mb4比utf8多支持 emoji 和部分生僻字博客评论里如果有人发特殊符号不会报错。参数上COLLATE utf8mb4_general_ci是通用排序规则兼容性好如果你对排序精度有要求可以换成utf8mb4_unicode_ci但一般课程设计用默认的就够。导入完成后用SHOW TABLES;确认表都进来了。通常会有用户表、博客表、类别表、评论表、友情链接表这几张核心表。如果表数量明显偏少说明 SQL 文件没导全检查是不是中途报错被中断了。2.3 JDBC 连接配置与常见参数数据库导好后接下来是改项目里的数据库连接配置。JavaEE 项目一般把连接信息放在db.properties或jdbc.properties里也有直接写在 Spring 配置文件中的。你要改的就四个值驱动类、URL、用户名、密码。# db.properties 常见配置项 jdbc.drivercom.mysql.cj.jdbc.Driver jdbc.urljdbc:mysql://localhost:3306/blog_db?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/ShanghaiuseSSLfalse jdbc.usernameroot jdbc.password你的密码这里有几个参数值得说清楚。useUnicodetruecharacterEncodingutf8是保证中文不乱码的关键少了它博客标题和评论里的中文可能变成问号。serverTimezoneAsia/Shanghai是 MySQL 8 之后必须加的不加会报时区错误这是很多人卡住的地方。useSSLfalse是本地开发时关掉 SSL避免连接时的证书警告如果部署到线上建议开启并配置证书。驱动类用com.mysql.cj.jdbc.Driver对应 MySQL 8 的驱动包如果你用的是 5.x 版本驱动类要改成com.mysql.jdbc.Driver这两个别搞混。改完配置后先别急着跑整个项目写一个简单的 JDBC 测试类连一下数据库确认能拿到连接再往下走。这一步能帮你把“环境问题”和“代码问题”分开省得后面排查时一头雾水。3. 登录认证与博客发布链路Shiro 加密和富文本入库怎么调3.1 Shiro 认证流程与密码加密比对登录模块是整个系统的入口也是 Shiro 发挥作用的地方。流程大致是用户提交账号密码 → Shiro 的UsernamePasswordToken封装凭证 → SecurityManager 交给自定义 Realm → Realm 去数据库查用户 → 密码加密后比对 → 成功则放行失败则返回登录页。这套流程的好处是认证逻辑集中在 Realm 里你后面要加登录失败次数限制、验证码校验都在这一个地方改。密码加密这块原文说的是“对前台输入的密码进行加密运算然后与数据库中的进行比较”。常见做法是 MD5 加盐或者用 Shiro 自带的SimpleHash。数据库里存的不是明文而是加密后的字符串。你如果拿到的是源码先看 Realm 里用的什么加密算法再看数据库里用户表的密码字段存的是什么格式。如果两边对不上登录永远失败。// 自定义 Realm 中的认证方法片段 Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { UsernamePasswordToken upToken (UsernamePasswordToken) token; String username upToken.getUsername(); // 根据用户名查数据库 User user userService.findByUsername(username); if (user null) { return null; // 用户不存在Shiro 会抛 UnknownAccountException } // 数据库里存的是加密后的密码这里交给 Shiro 比对 // credentials 传数据库中的密码Shiro 会用配置的 CredentialsMatcher 比对 return new SimpleAuthenticationInfo(user, user.getPassword(), ByteSource.Util.bytes(user.getSalt()), getName()); }这段代码的逻辑是先按用户名查用户查不到就返回 nullShiro 会自动处理异常查到就把用户对象和数据库中的加密密码交给 Shiro由HashedCredentialsMatcher完成加密和比对。参数上ByteSource.Util.bytes(user.getSalt())是盐值如果数据库里没存盐这一步可以去掉但安全性会降低。常见坑是加密算法、迭代次数、盐值这三样配置文件和数据库里的必须完全一致差一个字符都登录不进去。3.2 博客发布富文本内容如何正确入库写博客这个功能表面看就是填标题、选类别、写内容、点发布但实际链路里有两个容易出问题的地方一是富文本内容怎么传二是类别和博客的关联怎么存。富文本编辑器一般会提供一个隐藏的textarea你点发布时编辑器把 HTML 内容同步进去表单再提交给后端。后端拿到的是带标签的 HTML 字符串直接存进博客表的content字段。// Controller 中接收博客发布请求的片段 RequestMapping(value /saveBlog, method RequestMethod.POST) public String saveBlog(Blog blog, RequestParam(typeId) Integer typeId) { // 补全博客的创建时间和初始状态 blog.setCreateTime(new Date()); blog.setClickCount(0); blog.setCommentCount(0); // 保存博客主体 blogService.save(blog); // 维护博客和类别的关联常见做法是单独一张关联表或直接在博客表存 typeId blogService.saveBlogTypeRelation(blog.getId(), typeId); return redirect:/admin/blog/list; }这段代码里blog对象由 Spring MVC 自动封装表单字段typeId单独接收是因为类别选择框的 name 和博客实体字段名不一致。保存完博客后再维护和类别的关联。如果你的项目里博客表直接有type_id字段那第二步可以省掉直接blog.setTypeId(typeId)再保存。参数上createTime用new Date()是常见做法但更规范的是用数据库的NOW()或统一在 Service 层处理避免时区问题。富文本入库后前台展示时要用c:out或类似方式输出别直接${blog.content}否则会有 XSS 风险。课程设计里如果没做过滤答辩时被问到安全问题是会扣分的。3.3 评论审核与状态字段设计评论模块分审核和评论信息管理两部分核心是评论表里要有一个状态字段比如status用 0 表示待审核、1 表示通过、2 表示不通过。游客提交评论后默认状态是 0博主在后台看到待审核列表点通过就改成 1前台才会显示。这个设计不复杂但状态字段的默认值一定要设对否则新评论直接显示审核功能就形同虚设。-- 评论表关键字段示例 ALTER TABLE comment ADD COLUMN status TINYINT DEFAULT 0 COMMENT 0待审核 1通过 2不通过; -- 查询待审核评论 SELECT * FROM comment WHERE status 0 ORDER BY create_time DESC;上面这条 SQL 是给评论表加状态字段并设默认值。TINYINT占一个字节够用且省空间。查询待审核评论时按时间倒序博主能先看到最新的。常见坑是如果数据库里已有评论数据加字段后旧数据的状态是 NULL前台查询时status 1会漏掉它们需要手动UPDATE comment SET status 1 WHERE status IS NULL;补一下。4. 类别、友情链接与缓存刷新后台管理里那些不起眼但会翻车的点4.1 博客类别管理排序序号和前台展示的联动博客类别管理看着简单就是增删改查加排序但它和前台首页的“按日志类别”区域是联动的。类别表里一般有个order_num字段用来控制前台显示顺序。你如果在后台改了排序序号前台刷新后顺序应该跟着变。如果没变先检查两件事一是前台查询类别时有没有ORDER BY order_num二是项目有没有做缓存改了数据但缓存没刷新。-- 类别表结构参考 CREATE TABLE blog_type ( id INT PRIMARY KEY AUTO_INCREMENT, type_name VARCHAR(50) NOT NULL, order_num INT DEFAULT 0, create_time DATETIME ); -- 前台按排序号查询类别 SELECT * FROM blog_type ORDER BY order_num ASC, id ASC;这段 SQL 里order_num默认 0排序时先按它升序再按 id 升序兜底避免排序号相同时顺序乱跳。参数上type_name用VARCHAR(50)对类别名来说足够如果你要支持更长的名称可以调到 100。删除类别时要注意如果该类别下还有博客直接删会导致博客失去类别关联常见做法是先检查或把博客移到默认类别别让数据变成孤儿。4.2 友情链接管理与系统缓存刷新友情链接管理是纯 CRUD没什么技术难点但“刷新系统缓存”这个功能值得单独说。很多 JavaEE 项目会用 Ehcache 或 Redis 做缓存把首页的博客列表、类别列表缓存起来减少数据库查询。你改了友情链接或类别后如果前台没变化大概率是缓存没刷新。系统管理里的“刷新缓存”按钮做的就是清空缓存或重新加载。// 刷新缓存的常见实现 RequestMapping(/refreshCache) public String refreshCache() { // 清空指定缓存区域 cacheManager.getCache(blogCache).clear(); cacheManager.getCache(typeCache).clear(); // 或者重新加载 // blogService.reloadCache(); return redirect:/admin/system; }这段代码的逻辑是拿到 CacheManager清掉博客和类别相关的缓存区域。参数上缓存名称要和配置文件里定义的保持一致写错了清了个寂寞。如果你用的是 Redis清缓存可能是redisTemplate.delete(keys)思路一样。常见坑是开发时为了省事把缓存关了上线后忘了开或者反过来本地测试时缓存没清导致看到旧数据误以为代码没生效。4.3 个人信息修改与头像上传路径个人信息管理里修改昵称、签名、简介都是普通字段更新真正容易出问题的是头像上传。头像文件一般存在服务器某个目录下数据库里只存路径。路径配置不对上传成功但显示裂图这是血泪经验里排前三的坑。# 文件上传路径配置示例 upload.pathD:/blog/upload/ upload.url/upload/upload.path是文件实际存储的磁盘路径upload.url是前台访问的 URL 前缀。两个要对应上否则存进去了但访问不到。如果你部署到 Linux路径要改成/home/xxx/upload/这种别用 Windows 的反斜杠。另外上传目录要有写权限Tomcat 用户没权限写文件也是常见翻车点。5. 避坑与排查这套博客系统最容易卡住的五个地方5.1 启动报错 ClassNotFoundException: com.mysql.cj.jdbc.Driver现象是项目一启动就抛异常提示找不到 MySQL 驱动类。原因通常是pom.xml里没加 MySQL 驱动依赖或者加了但版本和驱动类不匹配。MySQL 8 的驱动类是com.mysql.cj.jdbc.Driver5.x 是com.mysql.jdbc.Driver配置和依赖要对上。解决方法是检查pom.xml里的mysql-connector-java版本8.x 用新驱动类5.x 用旧的改完重新mvn clean install。5.2 中文乱码数据库、连接、页面三处都要查现象是博客标题或评论显示成问号或乱码。原因可能出在三个地方数据库字符集不是utf8mb4、JDBC URL 没加characterEncodingutf8、JSP 页面没设pageEncodingUTF-8。解决方法是逐层排查先SHOW VARIABLES LIKE character%;看数据库字符集再检查 JDBC URL最后看页面头部。三处都对了乱码基本消失。5.3 登录一直失败但账号密码没错现象是输入正确的账号密码还是提示登录失败。原因通常是密码加密方式不匹配数据库里存的是 MD5 加盐后的值但 Realm 里配置的是不加盐的比对或者盐值取错了字段。解决方法是打开 Realm 代码看用的什么CredentialsMatcher再查数据库里密码字段的格式两边对齐。如果数据库里是明文那要么改成密文要么临时把比对器改成明文比对但后者只适合本地调试。5.4 富文本内容存进去后前台显示不全现象是博客正文在后台能看到前台只显示一部分或标签错乱。原因是数据库字段类型太小比如用了varchar(255)长文被截断。解决方法是把content字段改成text或longtexttext最大 64KBlongtext最大 4GB博客长文用longtext更保险。改完字段后重新发布一篇长文测试。5.5 评论审核通过后前台还是不显示现象是后台点了审核通过前台评论列表里还是没有。原因可能是前台查询条件写的是status 1但更新时状态值没改对或者缓存没刷新。解决方法是先直接查数据库SELECT status FROM comment WHERE id ?;确认状态真的变成 1 了如果变了但前台不显示就清缓存或重启项目。如果状态没变检查更新语句的WHERE条件是不是写错了。6. 从能跑到能讲答辩前把数据库设计和模块链路串一遍这套资源里除了源码和 SQL还有论文和答辩 PPT这其实是它比纯代码包更值钱的地方。但论文和 PPT 不能直接照搬你得自己能讲清楚数据库设计和模块之间的调用关系。我一般会做一件事把核心表的 ER 关系画出来然后顺着“登录 → 写博客 → 审核评论 → 前台展示”这条链路走一遍每经过一个模块就问自己“这里用了什么技术、为什么这么选、如果出问题看哪里”。比如数据库设计这块你要能说出用户表、博客表、类别表、评论表之间的关联博客属于某个类别评论属于某篇博客用户既是博主也是评论者。字段设计上博客表的content用longtext评论表的status用TINYINT类别表的order_num控制排序这些细节在答辩时都是加分项。下面这张表可以帮你快速核对核心表的关键字段。表名关键字段作用注意点userid, username, password, salt存博主账号密码加密存储salt 和加密方式匹配blogid, title, content, type_id, create_time存博客主体content 用 longtexttype_id 关联类别blog_typeid, type_name, order_num博客类别order_num 控制前台排序commentid, blog_id, content, status评论status 默认 0审核后改 1linkid, name, url友情链接纯展示注意 URL 格式校验把这张表里的字段和代码里的实体类对一遍再顺着 Service 层的方法看调用关系基本就能把整个系统讲顺。答辩时老师最爱问的就是“你这个评论审核是怎么实现的”“密码为什么要加密”你按上面的链路答不会卡壳。最后说一个我自己的习惯每次拿到这种带论文和 PPT 的资源我都会先把项目跑起来然后故意改坏一个配置看报错信息长什么样再改回来。这样真到答辩现场环境出问题时你至少知道该看哪个日志、查哪个配置。从那以后我每次部署这类 JavaEE 项目都强制先跑一遍数据库连接测试和登录测试再动其他模块。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑