1. 项目概述:一个现代化博客平台的诞生
去年团队重构技术博客时,我们决定采用Spring Boot+Vue.js的分离架构。这个组合带来的开发效率提升令人惊喜——后端接口响应时间控制在200ms内,前端首屏加载速度从原来的4秒优化到1.2秒。这种前后端分离的架构模式,正在成为中大型Web应用的主流选择。
本系统完整实现了博客的核心功能链:
- 后端:基于Spring Boot 2.7构建RESTful API
- 前端:Vue 3组合式API开发管理后台+用户门户
- 数据库:MySQL 8.0关系型存储+Redis缓存层
- 安全:JWT令牌认证+RBAC权限控制
- 部署:Docker容器化打包+Jenkins持续集成
关键提示:选择Spring Boot 2.x而非3.x版本,主要考虑企业现有环境JDK兼容性。Vue 3的Composition API相比Options API更适合复杂前端状态管理。
2. 架构设计与技术选型
2.1 为什么选择前后端分离?
传统单体架构(如JSP/Thymeleaf)在维护大型博客系统时面临三个痛点:
- 前后端耦合导致的部署依赖(每次修改前端需重新打包war)
- 接口协议不统一带来的联调成本(表单提交/JSON混用)
- 技术栈升级的连锁反应(前端框架变更影响后端模板)
我们的解决方案:
graph TD A[浏览器] -->|HTTP| B(Nginx) B -->|API请求| C[Spring Boot] B -->|静态资源| D[Vue.js] C --> E[MySQL] C --> F[Redis]2.2 后端技术栈深度解析
2.2.1 Spring Boot核心配置
// 启动类关键配置 @SpringBootApplication @EnableCaching @EnableAsync public class BlogApplication { public static void main(String[] args) { SpringApplication.run(BlogApplication.class, args); } @Bean public WebMvcConfigurer corsConfigurer() { return new WebMvcConfigurer() { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/api/**") .allowedOrigins("*") .allowedMethods("GET","POST","PUT","DELETE"); } }; } }2.2.2 数据持久层设计
采用MyBatis-Plus + 多数据源策略:
- 主库:MySQL存储核心业务数据
- 从库:Elasticsearch实现全文检索
- 缓存:Redis热点数据缓存
# application.yml关键配置 spring: datasource: master: url: jdbc:mysql://localhost:3306/blog?useSSL=false username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver redis: host: 127.0.0.1 port: 6379 password: database: 02.3 前端架构演进
Vue 3带来的重大改进:
- Composition API替代Mixins实现逻辑复用
<script setup>语法糖简化组件编写- 更好的TypeScript支持
// 典型API调用示例(axios封装) import request from '@/utils/request' export function getArticleList(params) { return request({ url: '/api/articles', method: 'get', params }) }3. 核心功能实现细节
3.1 文章发布流程
3.1.1 富文本编辑器集成
对比测试了Quill、TinyMCE、WangEditor后,最终选择TinyMCE 5.x:
- 支持图片上传(对接阿里云OSS)
- 代码高亮(集成highlight.js)
- 字数统计(自定义插件)
<template> <Editor v-model="content" api-key="your-api-key" :init="editorConfig" /> </template>3.1.2 文章标签系统
采用多对多关系设计:
CREATE TABLE `article_tag` ( `id` bigint NOT NULL AUTO_INCREMENT, `article_id` bigint NOT NULL, `tag_id` bigint NOT NULL, PRIMARY KEY (`id`), KEY `idx_article_id` (`article_id`), KEY `idx_tag_id` (`tag_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;3.2 评论模块设计
三级评论结构实现方案:
- 使用parent_id字段构建树形结构
- 添加level字段标识评论层级(0-2)
- 前端递归渲染评论组件
// 评论分页查询SQL @Select("SELECT * FROM comments WHERE article_id = #{articleId} AND level = 0 ORDER BY create_time DESC LIMIT #{pageSize}") List<Comment> selectRootComments(@Param("articleId") Long articleId, @Param("pageSize") Integer pageSize);4. 安全与性能优化
4.1 安全防护措施
4.1.1 JWT认证流程
用户登录->后端: 用户名/密码 后端-->前端: 签发JWT(含角色信息) 前端->后端: 携带Token访问API 后端-->前端: 返回数据关键配置:
@Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable() .authorizeRequests() .antMatchers("/api/auth/**").permitAll() .antMatchers("/api/admin/**").hasRole("ADMIN") .anyRequest().authenticated() .and() .addFilter(new JwtAuthenticationFilter(authenticationManager())) .sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.STATELESS); } }4.1.2 XSS防御方案
- 前端:DOMPurify过滤富文本内容
- 后端:Jackson自定义序列化器
public class XssStringJsonSerializer extends JsonSerializer<String> { @Override public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException { if (value != null) { gen.writeString(HtmlUtils.htmlEscape(value)); } } }4.2 性能调优实战
4.2.1 缓存策略
采用多级缓存架构:
- 本地缓存:Caffeine(高频访问数据)
- 分布式缓存:Redis(共享会话数据)
- 数据库缓存:MySQL查询缓存
@Cacheable(value = "articles", key = "#id", unless = "#result == null") public Article getArticleById(Long id) { return articleMapper.selectById(id); }4.2.2 SQL优化案例
慢查询优化前:
SELECT * FROM articles WHERE title LIKE '%Spring%' ORDER BY create_time DESC优化后方案:
- 添加全文索引
ALTER TABLE articles ADD FULLTEXT INDEX ft_idx_title(title);- 使用MATCH AGAINST语法
SELECT * FROM articles WHERE MATCH(title) AGAINST('Spring' IN BOOLEAN MODE) ORDER BY create_time DESC5. 部署与运维方案
5.1 Docker化部署
后端Dockerfile示例:
FROM openjdk:11-jre WORKDIR /app COPY target/blog-backend-0.0.1.jar app.jar EXPOSE 8080 ENTRYPOINT ["java","-jar","app.jar"]前端Nginx配置:
server { listen 80; server_name blog.example.com; location / { root /usr/share/nginx/html; index index.html; try_files $uri $uri/ /index.html; } location /api { proxy_pass http://backend:8080; proxy_set_header Host $host; } }5.2 监控体系建设
- Spring Boot Actuator端点监控
management: endpoints: web: exposure: include: health,info,metrics endpoint: health: show-details: always- Prometheus + Grafana监控看板
# application.yml追加 management: metrics: export: prometheus: enabled: true tags: application: ${spring.application.name}6. 开发中的典型问题
6.1 跨域问题解决方案
开发环境配置:
@Configuration public class CorsConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("*") .allowedMethods("*") .allowedHeaders("*") .allowCredentials(true) .maxAge(3600); } }生产环境推荐:
- Nginx反向代理统一域名
- 严格限制allowedOrigins
- 启用CORS预检缓存
6.2 文件上传大小限制
Spring Boot默认限制1MB,需要调整:
spring: servlet: multipart: max-file-size: 10MB max-request-size: 10MB前端分片上传实现要点:
- 使用File.slice()分割文件
- 计算MD5作为文件唯一标识
- 断点续传逻辑处理
7. 项目扩展方向
7.1 微服务化改造
演进路线建议:
- 按功能拆分服务(用户服务/文章服务/评论服务)
- 引入Spring Cloud Alibaba生态
- 配置中心使用Nacos
- 服务网关采用Spring Cloud Gateway
7.2 移动端适配方案
- 响应式布局优化
@media (max-width: 768px) { .article-card { width: 100%; margin-bottom: 15px; } }- PWA离线访问支持:
- 配置manifest.json
- 注册Service Worker
- 实现缓存策略
8. 源码学习建议
8.1 关键代码阅读顺序
- 启动类:BlogApplication.java
- 安全配置:SecurityConfig.java
- 全局异常处理:GlobalExceptionHandler.java
- 实体类:Article.java/Comment.java
- API控制器:ArticleController.java
8.2 调试技巧
IDEA远程调试配置:
- 启动时添加JVM参数:
-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005- IDEA创建Remote JVM Debug配置
- 连接5005端口调试
Vue DevTools使用要点:
- 安装Chrome扩展
- 检查组件层级结构
- 跟踪Vuex状态变化
- 性能分析工具使用