资讯动态

个人博客系统源码:Spring Boot与Mybatis-Plus架构下的二次开发与部署避坑

发布时间:2026/10/14 23:00:50 来源:尧图企业网站定制
简介这是一套基于 SSH2SpringStruts2Hibernate3与 Oracle 数据库的 SmartBlog 个人博客系统源码面向 Java Web 初中级开发者可用于学习 SSH 整合与博客项目分层实现。压缩包共 159 个文件、约 1.51MB以 gif 图片、jsp 页面、java 源码、xml 配置和编译后的 class 类为主还包含少量 jar、css、js 等资源适合直接导入工程分析。项目实现了首页展示、日志分页、评论、验证码登录以及后台日志新增、修改、删除、查询等模块从代码中可掌握随机验证码生成、分页查询、SSH 三层结构调用和 Oracle 数据表设计等常见技能。已有 1162 人学习下载对课程设计或 SSH 项目实践有不错的参考价值。1. 个人博客系统源码先搞清楚这包代码到底能干嘛想做个人博客最省力的路子不是从零写而是把手头这份个人博客系统源码跑起来再改。它解决的不只是「能发文章」而是把用户登录、文章发布、分类标签、评论管理、搜索和后台面板这一整套前后端分离的骨架都搭好了你拿到的是可以直接部署的产品级代码不是 demo。适合三类人课程设计交作业的学生、想快速上线自己博客的开发者、以及想学一个完整项目怎么分层的人。新手能照着本文把环境跑通熟手可以直接跳到第四章看改动边界第五、六章讲的是部署时最容易翻车的地方和一条自测脚本这往往是文档里不写但实际最值钱的部分。2. 拆包看结构源码包的四层边界先分清拿到压缩包先别急着进 IDE解压后先看根目录和两个关键文件。这种个人博客系统源码一般分两块一块是后端服务一块是前端页面。后端目录里必然有构建文件Maven 项目就是 pom.xmlGradle 则是 build.gradle前端目录里有 package.json。我一般会先读 pom.xml因为版本号会直接告诉你 JDK 基线、持久层框架和数据库适配两分钟内就能判断这份源码能不能在你当前机器上跑。2.1 技术栈识别从构建文件判断后端框架以最常见的组合为例pom.xml 里通常会看到这样一段依赖声明parent groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-parent/artifactId version2.6.3/version /parent dependencies dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-boot-starter/artifactId version3.5.2/version /dependency dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId scoperuntime/scope /dependency /dependencies这里有几个判断点spring-boot-starter-parent 的版本是 2.6.x意味着 JDK 8 或 11 都能跑但如果你机器装了 JDK 17 就要小心mybatis-plus 出现说明大部分单表查询不用手写 SQL 映射改字段时少一层功夫mysql-connector-java 则明确数据库是 MySQL。如果还有 spring-boot-starter-security 加 jwt 相关依赖说明后台登录是 token 鉴权后面调接口时记得带 Authorization 头。这些信息在解压后的第一眼就能确认别等到启动报错才回头看。2.2 数据库脚本表结构里藏着功能边界sql 目录下通常有 init.sql 或 blog.sql 这种初始化脚本。看建表语句比看代码更快因为表名和字段就是需求文档。个人博客系统常见的是五张核心表user、article、category、tag、comment加上一张 article_tag 关联表。以文章表为例典型结构是这样CREATE TABLE article ( id bigint(20) NOT NULL AUTO_INCREMENT, title varchar(200) NOT NULL COMMENT 文章标题, summary varchar(500) DEFAULT NULL COMMENT 摘要, content longtext COMMENT 正文 HTML, category_id bigint(20) DEFAULT NULL COMMENT 分类 ID, status tinyint(4) DEFAULT 0 COMMENT 0 草稿 1 已发布, view_count int(11) DEFAULT 0 COMMENT 浏览量, create_time datetime DEFAULT NULL, PRIMARY KEY (id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;看这张表能推出一堆事status 字段决定文章只在后台可见还是前台也展示这套代码的发布流程就是改这个字段category_id 没有建外键约束说明删除分类时要自己处理文章的归属问题content 用 longtext 存 HTML意味着前端详情页直接渲染富文本你要是想换 Markdown 编辑器后端字段不用动只动前端解析层。再往下看 comment 表一般有 article_id、parent_id、audit_status 三个关键字段parent_id 非空就支持楼中楼回复audit_status 决定评论是否需要审核才能在前台显示。表结构看清楚功能边界心里就有数了。2.3 前台展示与后台管理代码里两条并行路径前端代码有两种组织方式先识别再动手。一种是两个独立工程blog-web 管首页、文章列表、详情、标签归档blog-admin 管登录、文章编辑、分类维护、评论审核。另一种是一个 Vue 工程用路由分割路由表里以 admin 开头的页面走管理布局公开页面走另一个布局。区别如下路径对应工程/路由主要页面前台展示blog-web 或路由不带 admin首页、文章列表、文章详情、标签页、关于页后台管理blog-admin 或 /admin 前缀登录、文章编辑、分类标签管理、评论审核、系统设置判断方式很简单搜路由配置文件里的 path 字段出现大量 /admin 前缀说明是单工程。双工程的好处是后台改动不影响前台构建坏处是要维护两套依赖单工程的坑在于如果路由懒加载没写好首屏 JS 会非常大。改代码之前先确认你手上这份是哪种组织方式因为第四章要说的改动入口完全不一样找错目录等于白忙。3. 本地复现环境匹配与双端启动全流程第一次跑这套系统大部分人栽在版本不匹配而不是代码本身。先对齐环境基线再初始化数据库最后才启动这个顺序能省掉至少一个小时的排查时间。3.1 版本基线最稳组合是 JDK 8 配 MySQL 5.7这类源码包的作者环境大概率是 JDK 1.8、Spring Boot 2.x、MySQL 5.7、Node 14 左右。第一次复现先照这个基线来后面再考虑升级。实测中常见的组合和问题如下组件推荐版本不兼容的常见表现JDK1.8 或 11JDK 17 直接报 UnsupportedClassVersionErrorMySQL5.7 或 8.08.0 要注意驱动版本和时区参数Node14 或 16Node 18 下 node-sass 编译失败Maven3.6 以上3.6 以下拉不到部分新依赖如果你机器上只有 JDK 17不用急着换系统两个选择把 pom.xml 里的 java.version 改成 11或者装一个 JDK 8 然后在 IDE 里切换项目 SDK。我一般会直接装 JDK 8因为源码里可能用了过时 API高版本编译时 warning 会刷屏个别情况下直接编译失败。Node 版本的问题集中在 node-sass 这类原生模块装依赖时报错先看是不是这个原因。3.2 数据库初始化与三处必改配置步骤就三步。第一建库并导入脚本第二改数据库连接信息第三改文件上传路径。别跳过这三步是八成启动失败的来源。mysql -uroot -p -e CREATE DATABASE blog DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; mysql -uroot -p blog sql/blog.sql建库用 utf8mb4 是为了让 emoji 和特殊字符能存进 content 字段导入时如果报 1366 错误说明终端字符集没配对Linux 下先执行 export LANGen_US.UTF-8 再导入。然后打开后端配置文件一般是 application.yml 或 application.propertiesserver: port: 8080 servlet: context-path: /api spring: datasource: url: jdbc:mysql://localhost:3306/blog?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai username: root password: your_password servlet: multipart: max-file-size: 10MB blog: upload-path: D:/blog-upload/三个必改项password 改成你的数据库密码serverTimezone 不写会报时区偏差异常blog.upload-path 要改成绝对路径否则打包成 jar 后上传目录会落在临时目录一重启文件就丢。注意context-path 配成 /api 是常见做法但加了这个前缀后前端所有请求都要带后面第五章 5.1 的 404 坑就跟它直接相关。提示改配置时注意把注释删干净yml 对缩进敏感一个多余的空格会导致「端口没生效但又不报错」的诡异状态。3.3 双端启动与验证顺序先起后端再起前端。后端在项目根目录执行前端进入对应目录先装依赖再跑mvn clean install -DskipTests mvn spring-boot:runcd blog-web npm install npm run devmvn clean install 先打一次包是为了把依赖下全-DskipTests 跳过测试节省时间。看到 Tomcat started on port 8080 代表后端就绪npm run dev 成功后会提示本地访问端口一般是 3000 或 5173。验证时不要直接开页面先 curl 两个接口curl http://localhost:8080/api/health curl http://localhost:8080/api/article/list?page1size10第一个返回 JSON 说明后端活着第二个返回文章列表说明数据库连接正常。两步都过了再开前端页面不然出了问题你分不清是前端报错还是接口挂了。这个顺序是我从一次「前端白屏排查了两小时最后发现是接口没通」里学到的白屏大概率不是页面问题而是数据层没就绪。4. 二次开发把通用博客改成你的专属产品跑通只是第一步改造成自己的才是目的。新手最容易犯的错是全局搜索替换一顿乱改结果把路由搞崩。下面三个改动点按频次排从简单到复杂每一步都说明边界在哪。4.1 首页信息改造头像、导航、页脚三处入口首页顶部导航、侧边栏头像、页脚版权信息是三个最高频的改动点。位置取决于前端结构双工程结构在 blog-web/src/components/Header.vue 这类文件里单工程结构在 src/layout/components 下。偷懒的定位方法是直接搜「关于我」或者「ICP 备案」这类关键词比逐个找组件快得多。改的时候注意导航项在路由表里通常绑定了 name 而不是路径路径如果你只改了显示文本、没改 name点击后页面会空白。这种小问题最容易让人怀疑人生其实根源就是路由 name 没对上。另外页脚的版权年份是写死的改完记得同步更新否则年底了还挂着去年时间容易被访客截图当反面教材。4.2 新增文章分类数据表、接口、界面三层联动很多人上来就改前端想加一个分类结果后端接口返回的列表里根本没有白改。分类是三层联动的东西先插数据库再确认接口能查到最后才是前端渲染。基准做法是INSERT INTO category (name, sort, status) VALUES (技术漫谈, 3, 1);curl http://localhost:8080/api/category/list插入后先看返回的 JSON 里有没有新分类。如果查不到检查 category 表的 status 字段为 0 的话接口会把它过滤掉这是「插了看不到」的最常见原因。接口返回正常后前端侧边栏一般是通过 v-for 遍历数组自动渲染不用改模板如果列表是写死的静态数组去 CategoryList.vue 里把静态数据删掉换成接口数据。标签的加法同理只是多一张关联表。删除分类时记得把该分类下的文章先移动到「未分类」否则前台文章列表会出现分类为空的尴尬情况。4.3 替换富文本编辑器引包、初始化、数据回显默认编辑器可能是 textarea 或者一个精简版 Markdown很多人想换成带图片上传的富文本。常见选型是 wangEditor中文文档友好或 editor.mdMarkdown 风格。以 wangEditor 为例改动集中在两个文件管理端的文章编辑页和文章详情页。编辑页的核心代码import { createEditor, createToolbar } from wangeditor/editor import wangeditor/editor/dist/css/style.css const editor createEditor({ selector: #editor-container, html: article.content, // 回显服务端存的 HTML config: { MENU_CONF: { uploadImage: { server: /api/file/upload, fieldName: file, maxFileSize: 5 * 1024 * 1024 } } } })关键在 MENU_CONF 里的 server 接口后端要接收 multipart 的 file 字段并返回 { url: ... } 这种格式否则图片插入会一直转圈报错。另一个关键点是回显编辑时用 html 字段保存时把 editor.getHtml() 的结果原样存进 content 字段不要做转义。代价是安全——存的是原始 HTML如果保存接口没做 XSS 过滤别人可以在文章里塞 script 脚本。我一般会在后端保存接口里加一层 HTML 标签白名单过滤只放行 p、img、a、pre、code 这几个常用标签其他全剥掉。5. 部署避坑五个反复出现的问题与现场处理这些坑我在不同机器、不同部署方式下反复撞到过每条按现象、原因、解决写清楚。大部分不是代码 bug而是环境与配置的隐性约束。5.1 静态资源 404页面裸奔现象前端页面能打开但 CSS、JS 全部 404浏览器里只剩 HTML 骨架样式全丢。原因后端设置了 context-path/api但前端构建时 base 路径没同步或者 Nginx 部署时静态资源路径没配全。前后端分离项目里这类问题九成出在路径前缀不一致。解决先看前端构建配置里的 base 和 publicPath把它改成和部署子路径一致。如果是本地联调去看 webpack 的 proxy 配置target 后面补上 /api 前缀。如果已经上了 Nginx给静态资源单独配一个 location不要让它走到 API 的转发规则里。5.2 图片上传成功但访问不到现象后台传图提示成功前台图片却显示成 localhost:8080 开头的链接点开直接 404。原因上传接口回显的 URL 是后端拼接的用了相对路径或者带端口号域名一变就失效。这种问题在本地开发时完全正常一部署就暴露。解决改上传接口的返回逻辑图片地址统一存相对路径形如 /files/xxx.jpg前端展示时再补全域名。同时在后端配置类里加虚拟映射把 /files/** 指到磁盘上的上传目录这样 Nginx 不需要额外处理图片请求。5.3 启动时数据库连不上时区与驱动两个隐形坑现象后端启动报 Communications link failure或者偶尔能启动、跑几分钟就断连。原因MySQL 8.0 的驱动要求 url 里带 serverTimezone 参数另外 mysql-connector-java 8.x 在部分环境下默认不允许公钥检索导致认证阶段直接失败。这两个都属于「本地没触发、服务器必踩」的隐形项。解决url 拼上 serverTimezoneAsia/Shanghai 和 useSSLfalse再追加 allowPublicKeyRetrievaltrue。如果服务器上是 MySQL 5.7反而要把驱动降到 8.0 之前的版本否则会报 authentication plugin 不兼容。一句话先确认 MySQL 大版本再决定驱动版本别盲目升级。5.4 文章列表接口慢N1 查询现象首页打开要两秒开发者工具里看接口耗时 900ms但文章只有几十篇。原因列表接口每查一篇文章就单独查一次分类名和标签列表几十篇文章就是几十条 SQL数据库来回耗时全耗在这里。这是 MyBatis 写法里最常见的性能欠账。解决看 Mapper XML 里能不能用 left join 把分类名合并进文章查询标签是多对多常见做法是先查全部文章的标签再在内存里按 articleId 分组。改完以后接口时间大概率降到 200ms 以内。数据量没到上千条之前先不改也行但要知道这个优化的位置在哪真慢了不用慌。5.5 Nginx 反代后 POST 接口全部 405现象本地一切正常套了 Nginx 之后登录、发文章全部失败浏览器 Network 里显示 405 Method Not Allowed。原因proxy_pass 后面没带 URI 部分导致 Nginx 把不带斜杠的请求 301 跳转到带斜杠的地址POST 请求被重定向后变成 GET自然 405。解决location /api/ { proxy_pass http://127.0.0.1:8080/api/; } 这种写法保持路径不变。如果后端 jar 没设置 context-path后端是根路径就写成 proxy_pass http://127.0.0.1:8080;。排查时看 Nginx 日志发现 301 后面跟 405 的规律基本就是这个问题不用怀疑业务代码。6. 验证技巧一条 shell 脚本把部署全链路跑一遍部署完最怕的是「页面能开但深层功能悄悄坏」。我从某次上线后三天才发现评论接口一直 500 里学到的教训是每次部署完强制跑一遍接口自测脚本。脚本按业务顺序打五个接口健康检查、公开列表、管理员登录拿 token、带 token 创建文章、清理测试数据。任何一步状态码不对直接定位到对应模块。#!/bin/bash BASEhttps://your-domain.com/api echo 1. 健康检查 curl -s -o /dev/null -w %{http_code}\n $BASE/health echo 2. 文章列表 curl -s -o /dev/null -w %{http_code}\n $BASE/article/list?page1size5 echo 3. 管理员登录拿 token TOKEN$(curl -s -X POST $BASE/user/login \ -H Content-Type: application/json \ -d {username:admin,password:your-pass} | jq -r .data.token) echo 4. 创建文章带 token NEW_ID$(curl -s -X POST $BASE/article/save \ -H Authorization: Bearer $TOKEN \ -H Content-Type: application/json \ -d {title:deploy-check,content:ptest/p,status:1} | jq -r .data.id) echo created id$NEW_ID echo 5. 清理测试文章 curl -s -X POST $BASE/article/delete \ -H Authorization: Bearer $TOKEN \ -d id$NEW_ID -o /dev/null -w %{http_code}\n第 3 步拿 token 是关键很多系统登录接口返回结构不一样data.token 可能叫 token 也可能在顶层先手动执行一次看 JSON 路径再填 jq。第 4 步如果返回 401说明 token 过期策略或拦截器配置有问题返回 400 则多半是字段校验没过看返回体的具体提示。第 5 步用创建时返回的 id 清理避免误删真实数据。这套脚本跑三遍没红我才敢把前端页面交给别人用——从那以后我每次部署完都强制走一遍这五步前后不超过两分钟但能挡住一大半「上线即翻车」。希望帮到你。本文还有配套的精品资源点击获取

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

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

免费获取报价 →
↑