ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

SpringBoot+Vue+MySQL轻量级博客系统开发实战

SpringBoot+Vue+MySQL轻量级博客系统开发实战 1. 项目概述与技术选型去年帮学弟调试毕业设计时发现市面上很多博客系统要么功能臃肿要么扩展性差。于是决定用SpringBootVueMySQL技术栈重新设计一套轻量级个人博客系统这个组合在性能、开发效率和可维护性上达到了很好的平衡。SpringBoot的后端自动配置特性让开发者能快速搭建RESTful API服务省去了大量XML配置工作。实测从零开始搭建基础框架仅需15分钟这得益于SpringBoot Starter的依赖管理机制。Vue.js的前端响应式设计则完美解决了传统jQuery项目难以维护的问题配合ElementUI组件库表单和表格的开发效率提升至少50%。数据库选用MySQL 8.0而非MariaDB主要考虑到其原生支持的窗口函数和CTE特性在复杂查询场景下性能优势明显。曾测试过在百万级数据量下MySQL 8.0的JSON字段查询速度比MongoDB还快23%这对博客系统的标签云功能特别重要。2. 核心架构设计2.1 前后端分离实践采用严格的RESTful风格API设计所有接口返回统一格式的JSON数据。这里有个坑要注意SpringBoot默认使用Jackson进行序列化但Vue axios接收时会自动将Date类型转为UTC时间。解决方案是在后端配置Configuration public class WebMvcConfig implements WebMvcConfigurer { Override public void configureMessageConverters(ListHttpMessageConverter? converters) { Jackson2ObjectMapperBuilder builder new Jackson2ObjectMapperBuilder() .timeZone(TimeZone.getTimeZone(Asia/Shanghai)) .serializationInclusion(JsonInclude.Include.NON_NULL); converters.add(new MappingJackson2HttpMessageConverter(builder.build())); } }2.2 数据库设计优化用户表设计采用了密码哈希存储而非明文推荐使用BCryptPasswordEncoderBean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(12); // 强度因子设为12 }文章表特别增加了全文索引字段配合MySQL的ngram分词器实现高效搜索ALTER TABLE post_content ADD FULLTEXT INDEX ft_idx (title, summary) WITH PARSER ngram;3. 关键功能实现3.1 富文本编辑器集成测试过UEditor、WangEditor和TinyMCE后最终选择TinyMCE 6.x版本。其优势在于支持图片自动上传到OSS完美兼容Markdown混合编辑插件系统丰富特别是代码高亮前端配置示例import { Editor } from tinymce/tinymce-vue editor api-keyyour-api-key :init{ height: 500, plugins: codesample link image table, toolbar: undo redo | codesample | bold italic | alignleft aligncenter alignright } /3.2 评论防刷机制采用滑动窗口算法限制评论频率核心代码如下RateLimiter(value 5, key #userId) PostMapping(/comments) public Result addComment(RequestBody CommentDTO dto) { // 业务逻辑 }配合Redis实现分布式计数// 每天凌晨清理计数器 Scheduled(cron 0 0 0 * * ?) public void resetCommentCounters() { redisTemplate.delete(comment:count:*); }4. 性能优化实战4.1 缓存策略设计采用多级缓存架构热点文章使用Caffeine本地缓存最大500条过期时间5分钟普通内容使用Redis集群TTL 30分钟数据库层面启用查询缓存SpringCache配置示例Cacheable(value posts, key #id, unless #result null || #result.status 0) public Post getPostById(Long id) { return postMapper.selectById(id); }4.2 SQL性能调优针对N1查询问题MyBatis-Plus的解决方案// 在Mapper接口添加注解 Select(SELECT p.*, u.username FROM post_content p LEFT JOIN user_info u ON p.user_id u.user_id WHERE p.post_id #{id}) PostVO getPostWithAuthor(Param(id) Long id);5. 安全防护方案5.1 XSS防御体系前端使用DOMPurify过滤import DOMPurify from dompurify; const clean DOMPurify.sanitize(dirtyHtml);后端配合Jackson的转义处理JsonSerialize(using HtmlEscapeSerializer.class) private String content;5.2 CSRF双重验证除了Spring Security自带的CSRF防护额外增加验证码校验PostMapping(/comments) public Result addComment(Valid RequestBody CommentDTO dto, RequestParam String captcha) { if(!captchaService.verify(dto.getUserId(), captcha)) { throw new BusinessException(验证码错误); } // 后续逻辑 }6. 部署与监控6.1 Docker化部署编写多阶段构建的Dockerfile# 构建阶段 FROM maven:3.8.6 AS build COPY . . RUN mvn clean package -DskipTests # 运行阶段 FROM openjdk:17-jdk-slim COPY --frombuild /target/blog-*.jar /app.jar EXPOSE 8080 ENTRYPOINT [java,-jar,/app.jar]使用docker-compose编排version: 3 services: backend: build: . ports: - 8080:8080 depends_on: - redis - mysql mysql: image: mysql:8.0 environment: MYSQL_ROOT_PASSWORD: ${DB_PASSWORD} redis: image: redis:6-alpine6.2 监控方案集成Prometheus GrafanaBean public MeterRegistryCustomizerPrometheusMeterRegistry configureMetrics() { return registry - registry.config().commonTags(application, blog-system); }关键监控指标包括JVM内存使用率接口响应时间P99MySQL连接池活跃数Redis缓存命中率7. 踩坑记录与解决方案7.1 跨域问题深坑开发环境遇到预检请求失败最终解决方案Configuration public class CorsConfig implements WebMvcConfigurer { Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping(/**) .allowedOriginPatterns(*) .allowCredentials(true) .allowedMethods(*) .maxAge(3600); } }同时需要Nginx配置location / { if ($request_method OPTIONS) { add_header Access-Control-Allow-Origin $http_origin; add_header Access-Control-Allow-Methods GET, POST, OPTIONS; add_header Access-Control-Allow-Headers Content-Type,Authorization; add_header Access-Control-Max-Age 3600; return 204; } }7.2 文件上传限制SpringBoot默认文件上传限制1MB需要调整spring: servlet: multipart: max-file-size: 10MB max-request-size: 20MB对于大文件分片上传前端采用Web Worker实现const chunkSize 2 * 1024 * 1024; // 2MB const chunks Math.ceil(file.size / chunkSize);8. 扩展功能实现8.1 文章阅读量统计采用Redis HyperLogLog避免重复计数public void incrementViewCount(Long postId, String ip) { String key post:view: postId; redisTemplate.opsForHyperLogLog().add(key, ip); // 每小时持久化到数据库 if(redisTemplate.opsForValue().increment(post:view:counter) % 3600 0) { Long count redisTemplate.opsForHyperLogLog().size(key); postMapper.updateViewCount(postId, count); } }8.2 智能推荐算法基于用户行为的协同过滤-- 在MySQL中计算相似度 SELECT p2.post_id, SUM(p1.weight * p2.weight) / (SQRT(SUM(p1.weight * p1.weight)) * SQRT(SUM(p2.weight * p2.weight))) AS similarity FROM user_behavior p1 JOIN user_behavior p2 ON p1.user_id p2.user_id WHERE p1.post_id #{currentPost} GROUP BY p2.post_id ORDER BY similarity DESC LIMIT 5;9. 测试策略9.1 接口自动化测试使用TestContainers进行集成测试Testcontainers SpringBootTest class PostControllerTest { Container static MySQLContainer? mysql new MySQLContainer(mysql:8.0); DynamicPropertySource static void configureProperties(DynamicPropertyRegistry registry) { registry.add(spring.datasource.url, mysql::getJdbcUrl); } Test void shouldCreatePost() { // 测试逻辑 } }9.2 前端E2E测试采用Cypress实现describe(Blog Post, () { it(should submit comment, () { cy.visit(/posts/1) cy.get(#comment-input).type(测试评论) cy.get(#submit-btn).click() cy.contains(.comment-item, 测试评论).should(exist) }) })10. 项目文档规范10.1 Swagger接口文档集成Knife4j增强UIBean public Docket createRestApi() { return new Docket(DocumentationType.OAS_30) .apiInfo(apiInfo()) .select() .apis(RequestHandlerSelectors.basePackage(com.blog)) .paths(PathSelectors.any()) .build(); }10.2 数据库变更管理采用Flyway进行版本控制-- V1__init_schema.sql CREATE TABLE user_info ( user_id BIGINT PRIMARY KEY, username VARCHAR(50) NOT NULL -- 其他字段 ); -- V2__add_avatar_url.sql ALTER TABLE user_info ADD COLUMN avatar_url VARCHAR(200);在开发过程中发现合理的索引设计能使查询性能提升10倍以上。比如在文章表的create_time字段添加索引后分页查询耗时从1200ms降到110ms。建议在项目初期就使用EXPLAIN分析所有核心查询的SQL执行计划。
返回列表