1. 项目概述
这个基于SpringBoot的博客系统是我在2020年开发的一个全栈项目,当时是为了解决个人技术博客的托管需求。经过三年多的迭代优化,现在已经发展成为一个功能完善的企业级博客平台。系统采用前后端分离架构,后端基于SpringBoot 2.7.x,前端使用Vue 3.x,数据库选用MySQL 8.0。
提示:项目完整源码已托管在GitHub,文末会提供获取方式。建议先通读全文了解架构设计再动手实践。
2. 技术架构解析
2.1 核心组件选型
后端技术栈:
- SpringBoot 2.7.15(长期支持版本)
- MyBatis-Plus 3.5.3(简化CRUD操作)
- Spring Security 5.8(权限控制)
- Redis 6.2(缓存和会话管理)
- Elasticsearch 7.17(全文检索)
前端技术栈:
- Vue 3.2 + TypeScript
- Element Plus 2.3
- Axios 1.3
- Markdown-it(富文本渲染)
数据库:
- MySQL 8.0.33(主从架构)
- Redis 6.2.13(哨兵模式)
2.2 架构设计要点
系统采用经典的三层架构:
- 表现层:RESTful API + JWT认证
- 业务层:Spring IOC容器管理服务组件
- 数据层:MyBatis-Plus + 多数据源
特色设计:
- 读写分离:通过AbstractRoutingDataSource实现
- 分布式锁:Redisson实现文章发布防重
- 文件存储:MinIO对象存储替代传统FTP
3. 核心功能实现
3.1 用户认证模块
采用Spring Security + JWT方案:
java复制// JWT过滤器核心逻辑
public class JwtAuthenticationFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain chain) {
String token = request.getHeader("Authorization");
if (StringUtils.hasText(token) && token.startsWith("Bearer ")) {
String jwt = token.substring(7);
try {
String username = jwtUtil.extractUsername(jwt);
// ...验证逻辑
UsernamePasswordAuthenticationToken authentication =
new UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(authentication);
} catch (JwtException e) {
response.setStatus(HttpStatus.UNAUTHORIZED.value());
return;
}
}
chain.doFilter(request, response);
}
}
3.2 文章发布流程
- 前端提交Markdown格式内容
- 后端进行XSS过滤(使用Jsoup)
- 生成文章摘要(提取前200字符)
- 同步到Elasticsearch索引
- 清除相关缓存(Redis文章列表)
注意:大文本内容建议先压缩再存储,我们使用GZIP压缩后平均节省60%存储空间。
3.3 评论系统设计
三级评论结构实现方案:
sql复制CREATE TABLE `t_comment` (
`id` BIGINT NOT NULL AUTO_INCREMENT,
`content` TEXT NOT NULL,
`article_id` BIGINT NOT NULL,
`user_id` BIGINT NOT NULL,
`parent_id` BIGINT DEFAULT NULL COMMENT '一级评论ID',
`reply_to` BIGINT DEFAULT NULL COMMENT '回复对象ID',
`level` TINYINT DEFAULT 1 COMMENT '评论层级',
`create_time` DATETIME DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
INDEX `idx_article` (`article_id`),
INDEX `idx_parent` (`parent_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
4. 性能优化实践
4.1 缓存策略
采用多级缓存架构:
- 本地缓存(Caffeine):高频访问的配置项
- Redis缓存:
- 文章列表:30分钟过期
- 热门文章:LFU算法长期保留
- 用户会话:分布式存储
缓存击穿解决方案:
java复制public Article getArticleWithCache(Long id) {
String key = "article:" + id;
Article article = redisTemplate.opsForValue().get(key);
if (article == null) {
RLock lock = redissonClient.getLock("lock:article:" + id);
try {
lock.lock();
// 双重检查
article = redisTemplate.opsForValue().get(key);
if (article == null) {
article = articleMapper.selectById(id);
redisTemplate.opsForValue().set(key, article, 30, TimeUnit.MINUTES);
}
} finally {
lock.unlock();
}
}
return article;
}
4.2 数据库优化
- 索引优化:
- 为所有外键字段添加索引
- 组合索引遵循最左前缀原则
- 查询优化:
- 禁用SELECT *
- 复杂查询使用@Transactional(readOnly=true)
- 连接池配置:
yaml复制spring: datasource: hikari: maximum-pool-size: 20 minimum-idle: 5 connection-timeout: 30000 idle-timeout: 600000 max-lifetime: 1800000
5. 安全防护措施
5.1 常见攻击防护
- XSS防护:
- 前端:vue-dompurify-html插件
- 后端:Jsoup.clean()
- CSRF防护:
- 前后端分离架构天然免疫
- 关键操作要求二次认证
- SQL注入:
- 严格使用MyBatis参数绑定
- 定期执行SQL注入测试
5.2 敏感数据保护
- 密码存储:
java复制@Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(12); } - 数据脱敏:
- 手机号:138****1234
- 邮箱:a***b@example.com
- 日志过滤:
xml复制<filter> <filter-name>requestWrapperFilter</filter-name> <filter-class>com.example.filter.ParameterFilter</filter-class> </filter>
6. 部署方案
6.1 容器化部署
Docker Compose编排文件示例:
yaml复制version: '3.8'
services:
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
volumes:
- mysql_data:/var/lib/mysql
ports:
- "3306:3306"
redis:
image: redis:6.2
command: redis-server --appendonly yes
volumes:
- redis_data:/data
ports:
- "6379:6379"
backend:
build: ./backend
ports:
- "8080:8080"
depends_on:
- mysql
- redis
volumes:
mysql_data:
redis_data:
6.2 性能监控
Prometheus + Grafana监控方案:
- SpringBoot Actuator暴露指标
- Prometheus抓取配置:
yaml复制scrape_configs: - job_name: 'blog-backend' metrics_path: '/actuator/prometheus' static_configs: - targets: ['backend:8080'] - Grafana仪表盘关键指标:
- JVM内存使用
- 接口QPS/RT
- 数据库连接池状态
7. 开发环境搭建
7.1 环境准备
必备工具清单:
- JDK 17(推荐Amazon Corretto)
- MySQL 8.0 + Workbench
- Redis 6.2+
- Node.js 16.x
- IntelliJ IDEA Ultimate(学生可免费申请)
7.2 初始化步骤
- 数据库初始化:
sql复制CREATE DATABASE blog DEFAULT CHARACTER SET utf8mb4; USE blog; SOURCE init.sql; - 后端启动:
bash复制
mvn clean install java -jar target/blog-backend-1.0.0.jar - 前端启动:
bash复制
npm install npm run dev
8. 常见问题排查
8.1 启动报错处理
- 端口冲突:
bash复制
netstat -ano | findstr 8080 taskkill /PID <pid> /F - 数据库连接失败:
- 检查application.yml配置
- 验证MySQL用户权限
- Redis连接超时:
- 确认Redis服务已启动
- 检查防火墙设置
8.2 生产环境问题
- 内存泄漏排查:
bash复制jmap -histo:live <pid> | head -20 - 慢查询优化:
sql复制-- 开启慢查询日志 SET GLOBAL slow_query_log = 'ON'; SET GLOBAL long_query_time = 1; - 死锁分析:
sql复制SHOW ENGINE INNODB STATUS;
项目完整源码和部署文档已整理在GitHub仓库,包含:
- 后端完整工程
- 前端Vue项目
- SQL初始化脚本
- Postman接口文档
- 系统设计文档
获取方式:在公众号「技术实验室」回复关键词「springboot博客」获取仓库地址。建议结合视频教程学习,里面详细演示了从零开始的完整开发过程。