毕业设计实战:基于SpringBoot+Vue的旅游推荐系统,从需求到实现全流程拆解,附避坑指南!

143 阅读13分钟

毕业设计实战:基于SpringBoot+Vue的旅游推荐系统,从需求到实现全流程拆解,附避坑指南!

谁懂啊!当初做旅游推荐系统毕设时,光"协同过滤推荐算法"和"景点关联"就卡了我半个月——一开始算法没调好,结果推荐的景点全是冷门地,导师直接让我"重新设计推荐逻辑"😫 今天把从需求分析到功能实现的全流程经验分享出来,跟着做就能轻松搞定毕设!

一、先搞懂"旅游推荐系统要做什么"!需求分析是关键

刚开始我跳过需求分析就写代码,花三周做了个"深度学习推荐模型",结果导师一句"核心是景点管理、路线规划、用户互动,不是复杂算法"直接打回重改!

1. 核心用户&功能拆解(实战总结版)

旅游推荐系统有三类核心用户:管理员普通用户,功能要区分清楚:

  • 管理员端(系统管理):

    • 景点管理:审核景点信息(名称、类型、门票、图片)、设置景点推荐等级
    • 路线管理:设计旅游路线(景点组合、预算估算、最佳时间)、管理路线分类
    • 用户管理:管理用户账号、查看用户收藏记录、分析用户偏好
    • 内容管理:发布公告、审核论坛帖子、回复用户留言
    • 数据统计:景点热度分析、用户活跃度统计、推荐效果评估
  • 普通用户端(核心功能):

    • 景点浏览:查看景点列表(按类型/热度/评分筛选)、查看景点详情(图片、门票、评价)
    • 路线推荐:获取个性化旅游路线推荐、查看路线详情(景点列表、预算、时间安排)
    • 互动功能:收藏景点/路线、发布景点留言/路线留言、参与论坛讨论
    • 个性化推荐:基于用户浏览历史和收藏记录推荐相关景点和路线
    • 个人中心:管理收藏记录、查看浏览历史、修改个人信息

2. 需求分析避坑指南(血泪教训!)

  • 别闭门造车!找喜欢旅游的同学测试提意见:有同学说"想看到路线的时间安排",我才加了"路线行程表"功能
  • 一定要画用例图!用DrawIO画"用户-收藏景点""系统-个性化推荐"等核心用例
  • 写需求规格文档!约束条件要写清楚:"景点图片必须上传""路线预算要合理""推荐算法要可解释"

3. 可行性分析要专业

导师最爱问"可行吗",从3个角度回答:

  • 技术可行:SpringBoot+Vue+MySQL+推荐算法,技术栈成熟
  • 经济可行:开发工具全免费,地图API可用免费额度
  • 操作可行:界面参考马蜂窝/携程,用户上手快

二、技术选型别追新!实用最重要

刚开始我用Spark+机器学习库,结果部署复杂,本地都跑不起来😫 后来换成SpringBoot+Vue2+MySQL+简单推荐算法,真香!

1. 技术栈对比(附避坑提醒)

技术工具为什么选它避坑提醒!
SpringBoot 2.7快速开发,集成方便别用3.0!生态还不完善
Vue 2生态成熟,Element UI好用别用Vue 3组合式API!增加复杂度
Element UI旅游类组件丰富(卡片、轮播图)按需引入,控制包大小
MySQL 8.0关系型数据存储稳定一定要设计好表关联
推荐算法协同过滤(简单实现)别用太复杂的算法,毕设够用就行
ECharts数据可视化展示用于展示旅游数据统计

2. 开发环境搭建

# 后端
spring init --dependencies=web,mybatis,mysql,lombok travel-recommend

# 前端
vue create travel-frontend
cd travel-frontend
vue add element
npm install axios vue-router vuex echarts

3. 架构图要画!答辩加分

用DrawIO画前后端分离+推荐引擎架构

  • 前端:Vue + Element UI + ECharts
  • 后端:SpringBoot + MyBatis
  • 推荐模块:基于内容的推荐 + 协同过滤
  • 数据层:MySQL + Redis(缓存用户行为)

三、数据库设计:推荐算法的基础

这部分是推荐系统的核心,我当初用户行为表设计不合理,推荐效果很差。

1. 核心实体&ER图

核心表设计

  • 用户表(user):id、用户名、头像、联系方式、旅游偏好标签
  • 景点表(attraction):id、名称、类型、图片、门票、地址、评分、描述
  • 旅游路线表(route):id、名称、类型、预算、适合季节、行程天数、包含景点
  • 收藏表(collection):id、用户ID、收藏对象ID、收藏类型(景点/路线)、收藏时间
  • 浏览记录表(browse_history):id、用户ID、浏览对象ID、浏览类型、浏览时长、浏览时间
  • 留言表(comment):id、用户ID、对象ID、留言类型、内容、评分、时间
  • 用户偏好表(user_preference):id、用户ID、偏好标签(如:自然风光、历史遗迹、美食)、权重

2. 建表SQL示例(关键表)

-- 景点表(核心表)
CREATE TABLE `attraction` (
  `id` int NOT NULL AUTO_INCREMENT,
  `name` varchar(100) NOT NULL COMMENT '景点名称',
  `type` int NOT NULL COMMENT '景点类型(1-自然风光,2-历史遗迹,3-城市地标,4-主题公园)',
  `image` varchar(500) DEFAULT NULL COMMENT '景点图片(JSON数组)',
  `ticket_price` decimal(10,2) DEFAULT NULL COMMENT '门票价格',
  `address` varchar(200) DEFAULT NULL COMMENT '地址',
  `province` varchar(50) DEFAULT NULL COMMENT '省份',
  `city` varchar(50) DEFAULT NULL COMMENT '城市',
  `latitude` decimal(10,6) DEFAULT NULL COMMENT '纬度',
  `longitude` decimal(10,6) DEFAULT NULL COMMENT '经度',
  `description` text COMMENT '景点描述',
  `open_time` varchar(100) DEFAULT NULL COMMENT '开放时间',
  `best_season` varchar(50) DEFAULT NULL COMMENT '最佳季节',
  `visit_duration` int DEFAULT NULL COMMENT '建议游览时长(小时)',
  `popularity` int DEFAULT 0 COMMENT '热度(基于浏览、收藏计算)',
  `average_score` decimal(3,2) DEFAULT 0.00 COMMENT '平均评分',
  `status` int DEFAULT 1 COMMENT '状态(1-正常,0-下架)',
  `create_time` datetime DEFAULT CURRENT_TIMESTAMP,
  `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  KEY `idx_type` (`type`),
  KEY `idx_city` (`city`),
  KEY `idx_popularity` (`popularity`),
  KEY `idx_score` (`average_score`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- 旅游路线表(推荐核心)
CREATE TABLE `travel_route` (
  `id` int NOT NULL AUTO_INCREMENT,
  `name` varchar(100) NOT NULL COMMENT '路线名称',
  `type` int NOT NULL COMMENT '路线类型(1-经典线路,2-深度游,3-亲子游,4-背包客)',
  `budget` decimal(10,2) NOT NULL COMMENT '预算估算',
  `days` int NOT NULL COMMENT '行程天数',
  `suitable_season` varchar(100) DEFAULT NULL COMMENT '适合季节',
  `cover_image` varchar(200) DEFAULT NULL COMMENT '封面图',
  `description` text COMMENT '路线描述',
  `attraction_ids` varchar(500) NOT NULL COMMENT '包含景点ID(JSON数组)',
  `attraction_names` varchar(1000) DEFAULT NULL COMMENT '包含景点名称(用于展示)',
  `day_plan` text COMMENT '每日行程安排(JSON)',
  `view_count` int DEFAULT 0 COMMENT '浏览次数',
  `collect_count` int DEFAULT 0 COMMENT '收藏次数',
  `average_score` decimal(3,2) DEFAULT 0.00 COMMENT '平均评分',
  `status` int DEFAULT 1 COMMENT '状态(1-正常,0-下架)',
  `create_time` datetime DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  KEY `idx_type` (`type`),
  KEY `idx_days` (`days`),
  KEY `idx_budget` (`budget`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- 用户行为表(推荐算法基础)
CREATE TABLE `user_behavior` (
  `id` int NOT NULL AUTO_INCREMENT,
  `user_id` int NOT NULL COMMENT '用户ID',
  `item_id` int NOT NULL COMMENT '项目ID(景点或路线)',
  `item_type` int NOT NULL COMMENT '项目类型(1-景点,2-路线)',
  `behavior_type` int NOT NULL COMMENT '行为类型(1-浏览,2-收藏,3-评论,4-评分)',
  `behavior_value` decimal(3,2) DEFAULT NULL COMMENT '行为值(如评分)',
  `duration` int DEFAULT NULL COMMENT '停留时长(秒)',
  `behavior_time` datetime NOT NULL COMMENT '行为时间',
  `create_time` datetime DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  KEY `idx_user_item` (`user_id`,`item_id`,`item_type`),
  KEY `idx_user_behavior` (`user_id`,`behavior_type`),
  KEY `idx_item_behavior` (`item_id`,`item_type`,`behavior_type`),
  KEY `idx_time` (`behavior_time`),
  CONSTRAINT `fk_behavior_user` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- 收藏表(用户偏好分析)
CREATE TABLE `collection` (
  `id` int NOT NULL AUTO_INCREMENT,
  `user_id` int NOT NULL COMMENT '用户ID',
  `item_id` int NOT NULL COMMENT '收藏项目ID',
  `item_type` int NOT NULL COMMENT '收藏类型(1-景点,2-路线)',
  `collection_time` datetime NOT NULL COMMENT '收藏时间',
  `create_time` datetime DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_user_item` (`user_id`,`item_id`,`item_type`),
  KEY `idx_user` (`user_id`),
  KEY `idx_item` (`item_id`,`item_type`),
  CONSTRAINT `fk_collection_user` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

3. 推荐算法设计(毕设够用版)

方案一(简单版):基于热度的推荐

-- 热门景点推荐(按收藏数+评分)
SELECT a.*, 
       (a.popularity * 0.6 + a.average_score * 100 * 0.4) as recommend_score
FROM attraction a
WHERE a.status = 1
ORDER BY recommend_score DESC
LIMIT 10;

方案二(进阶版):基于内容的推荐

// 根据用户收藏的景点类型推荐相似景点
public List contentBasedRecommend(Integer userId) {
    // 1. 获取用户收藏的景点
    List collectedAttractionIds = collectionMapper.selectCollectedAttractions(userId);
    
    // 2. 分析用户偏好类型
    Map typePreferences = new HashMap<>();
    for (Integer attractionId : collectedAttractionIds) {
        Attraction attraction = attractionMapper.selectById(attractionId);
        typePreferences.merge(attraction.getType(), 1, Integer::sum);
    }
    
    // 3. 按偏好类型推荐(排除已收藏的)
    List preferredTypes = typePreferences.entrySet().stream()
            .sorted(Map.Entry.comparingByValue().reversed())
            .map(Map.Entry::getKey)
            .collect(Collectors.toList());
    
    return attractionMapper.selectRecommendByTypes(
            preferredTypes, 
            collectedAttractionIds, 
            10
    );
}

方案三(高级版):协同过滤推荐

// 基于用户的协同过滤(简化版)
public List collaborativeFilteringRecommend(Integer userId) {
    // 1. 找到相似用户(收藏了相同景点)
    List similarUserIds = collectionMapper.findSimilarUsers(userId, 5);
    
    // 2. 获取相似用户收藏但当前用户未收藏的景点
    List collectedAttractionIds = collectionMapper.selectCollectedAttractions(userId);
    
    // 3. 计算推荐分数(基于相似用户的收藏数)
    Map attractionScores = new HashMap<>();
    for (Integer similarUserId : similarUserIds) {
        List similarUserCollections = collectionMapper.selectCollectedAttractions(similarUserId);
        for (Integer attractionId : similarUserCollections) {
            if (!collectedAttractionIds.contains(attractionId)) {
                attractionScores.merge(attractionId, 1, Integer::sum);
            }
        }
    }
    
    // 4. 按分数排序返回
    return attractionScores.entrySet().stream()
            .sorted(Map.Entry.comparingByValue().reversed())
            .limit(10)
            .map(entry -> attractionMapper.selectById(entry.getKey()))
            .collect(Collectors.toList());
}

四、功能实现:核心模块详解

1. 个性化推荐模块(必做!亮点)

推荐策略组合

  • 新用户:热门推荐 + 地域推荐
  • 老用户:协同过滤 + 基于内容推荐
  • 实时推荐:基于当前浏览记录

实现代码示例

@Service
public class RecommendationService {
    
    @Autowired
    private AttractionMapper attractionMapper;
    
    @Autowired
    private CollectionMapper collectionMapper;
    
    @Autowired
    private UserBehaviorMapper userBehaviorMapper;
    
    // 综合推荐入口
    public List getRecommendations(Integer userId, String city) {
        List recommendations = new ArrayList<>();
        
        // 检查用户是否有行为记录
        boolean hasBehavior = userBehaviorMapper.hasUserBehavior(userId);
        
        if (!hasBehavior) {
            // 新用户推荐:热门 + 同城
            recommendations.addAll(getPopularRecommendations(city, 5));
            recommendations.addAll(getLocalRecommendations(city, 5));
        } else {
            // 老用户推荐:协同过滤 + 基于内容
            recommendations.addAll(getCollaborativeFilteringRecommendations(userId, 6));
            recommendations.addAll(getContentBasedRecommendations(userId, 4));
        }
        
        // 去重并返回
        return recommendations.stream()
                .distinct()
                .limit(10)
                .collect(Collectors.toList());
    }
    
    // 热门推荐
    private List getPopularRecommendations(String city, int limit) {
        return attractionMapper.selectPopularByCity(city, limit);
    }
    
    // 同城推荐
    private List getLocalRecommendations(String city, int limit) {
        return attractionMapper.selectByCity(city, limit);
    }
    
    // 更多推荐方法...
}

2. 旅游路线规划模块(核心功能)

路线生成逻辑

  1. 用户选择兴趣点(自然风光、美食、购物等)
  2. 系统推荐匹配的景点
  3. 根据地理位置和开放时间智能排序
  4. 生成合理的行程安排和预算估算

路线详情数据结构

{
  &#34;id&#34;: 1,
  &#34;name&#34;: &#34;北京经典三日游&#34;,
  &#34;days&#34;: 3,
  &#34;budget&#34;: 1500.00,
  &#34;dayPlan&#34;: [
    {
      &#34;day&#34;: 1,
      &#34;title&#34;: &#34;皇家园林之旅&#34;,
      &#34;attractions&#34;: [
        {&#34;id&#34;: 1, &#34;name&#34;: &#34;故宫&#34;, &#34;duration&#34;: 4, &#34;time&#34;: &#34;09:00-13:00&#34;},
        {&#34;id&#34;: 2, &#34;name&#34;: &#34;景山公园&#34;, &#34;duration&#34;: 2, &#34;time&#34;: &#34;14:00-16:00&#34;}
      ],
      &#34;transport&#34;: &#34;地铁1号线&#34;,
      &#34;tips&#34;: &#34;故宫需提前预约&#34;
    }
  ]
}

3. 景点详情展示模块

功能要点

  • 图片轮播展示
  • 基本信息(门票、开放时间、地址)
  • 地图位置展示(集成百度/高德地图)
  • 用户评价和评分
  • 相关推荐(相似景点、组合路线)

前端实现


  <div class="attraction-detail">
    
    
      
        <img src="img" class="carousel-image"/>
      
    
    
    
    <div class="basic-info">
      <h1>{{ attraction.name }}</h1>
      <div class="tags">
        {{ attraction.typeName }}
        门票¥{{ attraction.ticketPrice }}
        免费
      </div>
      
      
      
        {{ isCollected ? '已收藏' : '收藏' }}
      
    </div>
    
    
    <div class="map-section">
      <h3>位置信息</h3>
      <div id="map-container"></div>
    </div>
    
    
    <div class="recommendations">
      <h3>猜你喜欢</h3>
      
    </div>
  </div>

4. 用户行为分析模块

行为收集

// 用户行为埋点
@PostMapping(&#34;/trackBehavior&#34;)
public Result trackBehavior(@RequestBody UserBehaviorDTO dto) {
    UserBehavior behavior = new UserBehavior();
    behavior.setUserId(dto.getUserId());
    behavior.setItemId(dto.getItemId());
    behavior.setItemType(dto.getItemType());
    behavior.setBehaviorType(dto.getBehaviorType());
    behavior.setBehaviorValue(dto.getValue());
    behavior.setDuration(dto.getDuration());
    behavior.setBehaviorTime(new Date());
    
    userBehaviorMapper.insert(behavior);
    
    // 实时更新景点热度
    if (dto.getItemType() == 1) { // 景点
        attractionMapper.incrementPopularity(dto.getItemId());
    }
    
    return Result.success(&#34;行为记录成功&#34;);
}

五、前端页面设计要点

1. 首页设计

  • 搜索框:支持景点/路线搜索,支持城市筛选
  • 轮播图:推荐热门景点和路线
  • 推荐区域:个性化推荐卡片展示
  • 分类导航:按景点类型快速筛选

2. 景点列表页

  • 筛选器:按类型、门票价格、评分、距离筛选
  • 排序:默认按热度,支持按评分、价格排序
  • 展示模式:列表模式/网格模式切换
  • 分页加载:滚动加载更多

3. 路线推荐页

  • 路线筛选:按天数、预算、适合人群筛选
  • 行程预览:展示路线概览(景点数量、总预算)
  • 一键收藏:收藏感兴趣的路线
  • 行程详情:点击查看详细行程安排

4. 个人中心页

  • 我的收藏:景点收藏、路线收藏分开展示
  • 浏览历史:最近浏览记录,可清除
  • 推荐偏好:展示系统分析的用户偏好标签
  • 个人信息:头像、昵称、旅游偏好设置 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述

六、测试:这些场景必须测!

1. 功能测试用例

表1:推荐功能测试

测试场景操作步骤预期结果
新用户访问新注册用户访问首页看到热门景点和本地推荐
收藏后推荐用户收藏几个自然景点推荐更多自然类景点
浏览行为影响用户浏览多个历史遗迹推荐相关历史景点

表2:路线规划测试

测试场景操作步骤预期结果
生成路线选择兴趣点生成路线路线包含相关景点,时间安排合理
路线收藏收藏一条路线在个人中心能看到收藏
路线分享点击分享按钮生成分享链接或二维码

2. 性能测试

  • 推荐响应时间:推荐算法应在500ms内返回结果
  • 并发访问:模拟100个用户同时访问景点详情页
  • 大数据量:测试10000个景点数据时的查询性能

3. 推荐效果评估(加分项)

  • 准确率:推荐内容与用户实际兴趣的匹配度
  • 覆盖率:推荐系统能覆盖多少景点/路线
  • 新颖性:推荐的景点/路线是否多样

七、部署与答辩准备

1. 项目打包部署

# 后端打包
mvn clean package -DskipTests

# 前端打包
npm run build

# 部署
# 1. 上传jar包和dist文件夹
# 2. 导入SQL脚本(含测试数据)
# 3. 启动后端服务
# 4. 配置Nginx反向代理

2. 答辩准备(3个加分技巧)

  1. 演示流程要生动

    • 用户注册→设置偏好→查看个性化推荐
    • 浏览景点→收藏→查看推荐变化
    • 规划路线→查看行程安排
  2. 重点讲技术亮点

    • 推荐算法的设计与实现(展示算法逻辑图)
    • 用户行为数据的收集与分析
    • 路线规划的智能算法
  3. 准备常见问题

    • Q:推荐算法怎么实现的? A:采用混合推荐策略,新用户用热门推荐,老用户用协同过滤+基于内容推荐
    • Q:如何保证推荐准确性? A:①收集用户行为数据 ②定期评估推荐效果 ③支持用户反馈
    • Q:系统如何扩展? A:①推荐算法可替换 ②支持插件化推荐策略 ③数据存储可分库分表

八、毕设文档结构

旅游推荐系统/
├── 毕业论文.docx          # 完整论文(含算法章节)
├── 开题报告.docx          # 研究背景、创新点
├── 中期检查表.docx        # 进度汇报
├── 源码/
│   ├── backend/          # SpringBoot后端
│   ├── frontend/         # Vue前端
│   ├── algorithm/        # 推荐算法实现
│   └── database/         # 数据库脚本
├── 演示视频.mp4          # 10分钟功能演示(重点展示推荐)
├── 答辩PPT.pptx          # 15分钟答辩展示
└── 算法说明文档.md       # 推荐算法详细说明

最后:真心话时间

旅游推荐系统是技术含量较高的毕设选题,能很好展示你的算法能力和工程能力。关键是推荐算法要设计合理,用户交互要友好,数据可视化要做好。

需要完整源码(含推荐算法实现)、数据库脚本(含旅游测试数据)、答辩PPT模板的同学,评论区扣"旅游推荐",我发你。遇到具体技术问题(比如推荐算法、地图集成),也可以留言讨论!

这篇干货整理了我所有经验教训,点赞收藏,毕设路上不迷路!祝大家顺利毕业!🏞️✨