SpringBoot+Vue构建新闻推荐系统全栈实践

发布时间:2026/10/31 6:07:51
SpringBoot+Vue构建新闻推荐系统全栈实践 1. 项目概述与核心价值新闻推荐系统作为企业级内容分发平台的核心组件其技术选型与架构设计直接决定了系统的稳定性、扩展性和用户体验。这套基于SpringBootVueMyBatisMySQL的完整解决方案采用了前后端分离架构后端使用SpringBoot框架提供RESTful API服务前端通过Vue.js实现动态交互数据持久层采用MyBatis操作MySQL数据库。这种技术组合在当前企业级应用中具有典型代表性既能满足高并发场景下的性能需求又保持了良好的可维护性。提示企业级系统区别于普通应用的关键在于需要考虑权限控制、日志审计、性能监控等非功能性需求这在后续的架构设计中会有具体体现。从业务视角看新闻推荐系统需要解决三个核心问题内容管理CMS、用户画像构建和个性化推荐算法。系统管理员通过后台进行新闻采编发布同时系统会收集用户浏览行为数据基于协同过滤或深度学习算法生成推荐结果。这种闭环设计使得系统能够随着用户量增长不断优化推荐精准度。2. 技术架构深度解析2.1 后端SpringBoot设计要点SpringBoot的自动配置特性极大简化了企业级应用的初始搭建工作。在本系统中我们采用多模块化设计news-recommendation ├── recommendation-core // 核心算法模块 ├── recommendation-admin // 管理后台接口 ├── recommendation-api // 用户端接口 └── recommendation-common // 公共组件关键配置示例application.ymlspring: datasource: url: jdbc:mysql://localhost:3306/news_db?useSSLfalseserverTimezoneUTC username: root password: 加密密码 redis: host: 127.0.0.1 port: 6379 password: mybatis: mapper-locations: classpath:mapper/*.xml configuration: map-underscore-to-camel-case: true对于企业级应用需要特别注意使用Spring Security实现RBAC权限控制集成Spring CacheRedis实现热点数据缓存通过Spring AOP统一处理日志和异常配置Druid连接池监控SQL性能2.2 前端Vue.js工程化实践前端项目采用Vue CLI脚手架搭建主要目录结构src/ ├── api/ // 接口定义 ├── assets/ // 静态资源 ├── components/ // 公共组件 ├── router/ // 路由配置 ├── store/ // Vuex状态管理 └── views/ // 页面组件推荐系统特有的前端技术要点使用Vuex管理用户偏好状态通过axios拦截器实现Token验证采用WebSocket实现实时推荐更新使用Element UI或Ant Design Vue构建管理后台关键性能优化手段路由懒加载第三方库按需引入使用keep-alive缓存组件开启Gzip压缩2.3 MyBatis数据持久化方案MyBatis的灵活SQL编写能力特别适合需要复杂查询的推荐系统。建议采用以下最佳实践动态SQL示例根据条件筛选新闻select idselectNewsByCondition resultMapnewsResultMap SELECT * FROM t_news where if testcategoryId ! null AND category_id #{categoryId} /if if testkeywords ! null and keywords ! AND title LIKE CONCAT(%,#{keywords},%) /if if teststatus ! null AND status #{status} /if /where ORDER BY publish_time DESC /select批量操作处理用户行为日志入库Insert(script INSERT INTO user_behavior_log(user_id, news_id, behavior_type) VALUES foreach collectionlist itemitem separator, (#{item.userId}, #{item.newsId}, #{item.behaviorType}) /foreach /script) void batchInsertBehaviorLog(ListUserBehavior behaviors);3. 数据库设计与优化3.1 核心表结构设计新闻推荐系统主要包含以下几类数据表用户基础表userCREATE TABLE user ( id bigint NOT NULL AUTO_INCREMENT, username varchar(50) NOT NULL, password varchar(100) NOT NULL, phone varchar(20) DEFAULT NULL, avatar varchar(255) DEFAULT NULL, gender tinyint DEFAULT 0, tags json DEFAULT NULL COMMENT 用户兴趣标签, create_time datetime NOT NULL, PRIMARY KEY (id), UNIQUE KEY idx_username (username) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;新闻内容表newsCREATE TABLE news ( id bigint NOT NULL AUTO_INCREMENT, title varchar(100) NOT NULL, content longtext NOT NULL, category_id int NOT NULL, cover_image varchar(255) DEFAULT NULL, source varchar(50) DEFAULT NULL, publish_time datetime NOT NULL, status tinyint NOT NULL DEFAULT 1, hot_score int DEFAULT 0 COMMENT 热度评分, PRIMARY KEY (id), KEY idx_category (category_id), KEY idx_hot (hot_score) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;用户行为表user_behaviorCREATE TABLE user_behavior ( id bigint NOT NULL AUTO_INCREMENT, user_id bigint NOT NULL, news_id bigint NOT NULL, behavior_type tinyint NOT NULL COMMENT 1浏览 2点赞 3收藏 4分享, duration int DEFAULT NULL COMMENT 浏览时长(秒), create_time datetime NOT NULL, PRIMARY KEY (id), KEY idx_user_news (user_id,news_id), KEY idx_time (create_time) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;3.2 MySQL性能优化策略索引优化为高频查询条件建立组合索引使用覆盖索引减少回表操作定期使用EXPLAIN分析慢查询分表策略用户行为表按月分表user_behavior_202301使用Sharding-JDBC实现透明访问参数调优# my.cnf关键配置 innodb_buffer_pool_size 4G innodb_log_file_size 256M innodb_flush_log_at_trx_commit 2 sync_binlog 1004. 推荐算法实现4.1 基于用户行为的协同过滤public ListLong recommendByUserCF(Long userId, int size) { // 1. 获取相似用户 MapLong, Double similarUsers userSimilarityService.findSimilarUsers(userId, 10); // 2. 获取相似用户喜欢的新闻 MapLong, Double candidateNews new HashMap(); for (Map.EntryLong, Double entry : similarUsers.entrySet()) { ListUserBehavior behaviors behaviorService.getPositiveBehaviors(entry.getKey()); for (UserBehavior behavior : behaviors) { double score entry.getValue() * getBehaviorWeight(behavior.getBehaviorType()); candidateNews.merge(behavior.getNewsId(), score, Double::sum); } } // 3. 过滤已读新闻并排序 return candidateNews.entrySet().stream() .filter(e - !hasViewed(userId, e.getKey())) .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder())) .limit(size) .map(Map.Entry::getKey) .collect(Collectors.toList()); }4.2 基于内容的推荐public ListLong recommendByContent(Long userId, int size) { // 1. 获取用户兴趣标签 SetString userTags userService.getUserTags(userId); // 2. 计算新闻与用户兴趣的匹配度 ListNews candidateNews newsService.getLatestNews(500); // 取最近500条新闻 MapLong, Double newsScores new HashMap(); for (News news : candidateNews) { SetString newsTags extractTags(news.getContent()); double jaccard jaccardSimilarity(userTags, newsTags); double score jaccard * (1 news.getHotScore() / 100.0); newsScores.put(news.getId(), score); } // 3. 排序返回 return newsScores.entrySet().stream() .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder())) .limit(size) .map(Map.Entry::getKey) .collect(Collectors.toList()); }5. 系统部署与监控5.1 生产环境部署方案推荐使用Docker Compose编排服务version: 3 services: mysql: image: mysql:8.0 environment: MYSQL_ROOT_PASSWORD: ${DB_PASSWORD} volumes: - ./mysql/data:/var/lib/mysql - ./mysql/conf:/etc/mysql/conf.d ports: - 3306:3306 redis: image: redis:6 ports: - 6379:6379 volumes: - ./redis/data:/data backend: build: ./backend ports: - 8080:8080 depends_on: - mysql - redis frontend: build: ./frontend ports: - 80:805.2 监控指标配置Spring Boot Actuator监控端点management.endpoints.web.exposure.includehealth,info,metrics,prometheus management.metrics.export.prometheus.enabledtrue关键监控指标接口响应时间http.server.requestsJVM内存使用jvm.memory.used数据库连接池活跃连接hikaricp.connections.activeRedis命中率redis.commands日志收集方案ELKElasticsearchLogstashKibana或使用LokiGranfa6. 常见问题排查6.1 性能问题定位流程慢接口排查检查SQL执行计划确认是否缺少索引分析是否N1查询问题内存泄漏排查使用jmap生成堆转储文件通过MAT工具分析对象引用检查缓存是否无限增长高CPU问题top命令查看Java进程CPUjstack获取线程栈查找死循环或频繁GC6.2 典型异常处理MyBatis批量插入超时Transactional public void batchInsert(ListNews newsList) { SqlSession session sqlSessionTemplate.getSqlSessionFactory().openSession(ExecutorType.BATCH, false); try { NewsMapper mapper session.getMapper(NewsMapper.class); for (int i 0; i newsList.size(); i) { mapper.insert(newsList.get(i)); if (i % 500 0) { // 每500条提交一次 session.commit(); session.clearCache(); } } session.commit(); } finally { session.close(); } }Vue组件内存泄漏// 在beforeDestroy中清理 beforeDestroy() { clearInterval(this.timer) this.$eventBus.$off(custom-event, this.handler) this.chartInstance?.dispose() }7. 项目扩展方向推荐算法增强引入深度学习模型如DSSM增加实时特征处理Flink实现多目标优化点击率阅读时长架构升级服务拆分微服务化引入消息队列Kafka解耦增加AB测试平台用户体验优化实现无限滚动加载增加推荐理由展示开发暗黑模式在实际开发中我们发现新闻封面图的处理是个容易被忽视的环节。建议使用Thumbnailator库进行图片压缩和裁剪同时将图片存储到OSS等对象存储服务可以显著降低服务器带宽压力。对于用户行为收集采用本地缓存定时批量上报的方式能有效减轻数据库压力。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询