【开源】基于SpringBoot的海南旅游景点推荐系统的设计和实现

在这里插入图片描述


目录

  • 一、摘要
    • 1.1 项目介绍
    • 1.2 项目录屏
  • 二、功能模块
    • 2.1 用户端
    • 2.2 管理员端
  • 三、系统展示
  • 四、核心代码
    • 4.1 随机景点推荐
    • 4.2 景点评价
    • 4.3 协同推荐算法
    • 4.4 网站登录
    • 4.5 查询景点美食
  • 五、免责说明


一、摘要

1.1 项目介绍

基于Vue+SpringBoot+MySQL的海南旅游推荐系统,基于协同推荐算法,包括用户网页和管理后台,包含景点类型模块、旅游景点模块、行程推荐模块、美食推荐模块、景点排名模块,还包含系统自带的用户管理、部门管理、角色管理、菜单管理、日志管理、数据字典管理、文件管理、图表展示等基础模块,海南旅游推荐系统基于角色的访问控制,给景点管理员、游客使用,可将权限精确到按钮级别,您可以自定义角色并分配权限,系统适合设计精确的权限约束需求。

项目编号: S 023 ,源码已在 B i l i b i l i 中上架,需要的朋友请自行下载。 \color{red}{项目编号:S023,源码已在 Bilibili 中上架,需要的朋友请自行下载。} 项目编号:S023,源码已在Bilibili中上架,需要的朋友请自行下载。

https://gf.bilibili.com/item/detail/1104039029

为了帮助小白入门 Java,博主录制了本项目配套的《项目手把手启动教程》,希望能给同学们带来帮助。

1.2 项目录屏


二、功能模块

2.1 用户端

  1. 景点推荐:根据用户个性化偏好给用户推荐感兴趣的景点
    【景点信息包含:景点名称、景点类型、评分、收藏量、门票价格、门票预订(提供购买链接,用户可以通过点击链接到其他平台购买门票)、开放时间、景区地址(所在市区、详细地址)、景点介绍】
  2. 景点筛选:用户可通过设置自己想要的景点类型、景点门票价格范围、景区地址(海口市、三亚市、儋州市、三沙市等)来筛选满足自身需求的景点
    筛选:【注:若用户只设置了一个筛选条件则只需满足一个筛选条件就推荐给用户,若设置两个以上,则需都满足才给用户推荐】
  3. 旅游攻略:用户可以通过搜索景点名称来获取景点周边美食以及行程路线的相关信息
    (1)交通指南:起点、终点、交通方式、行程路线
    (2)周边美食:美食图片、名称、类型、简介、人均消费
  4. 景点数据:景点数据可视化
    (1)好评度排名:管理员可以看到好评度高的前十个景点【排名、景点名称、好评度】
    (2)景点收藏量:管理员可以看到收藏量排名前十的景点【排名、景点名称、收藏量】
  5. 个人中心:
    (1)个人信息:账号、姓名、联系方式、身份证号(用户可以更新个人信息、退出登录)
    (2)景点收藏:用户可以查看、取消收藏过的景点

2.2 管理员端

  1. 个人中心:管理员个人信息
  2. 景点信息管理:
    (1)查询:可通过搜索景点名称、地址、景点类型来获取需要的景点数据(搜索到需要的景点数据后可进行查看、修改、删除景点信息操作)
    (2)添加:可以添加新的景点信息
  3. 用户信息管理:
    (1)查询:可通过搜索用户账号来查询需要的用户(查询到需要的用户后可对用户信息进行查看、修改、删除操作)
    (2)添加:可添加新用户信息
  4. 行程信息管理:
    (1)查询:可通搜索景点地址来获取景点行程路线信息(查询到需要的行程信息后可对其进行查看、修改、删除操作)
    (2)添加:可添加信息
  5. 美食信息管理:
    (1)查询:可通搜索景点地址来获取景点周边美食信息(查询到需要的信息后可对其进行查看、修改、删除操作)
    (2)添加:可添加新的美食信息
  6. 景点数据:景点数据可视化(同用户端的景点数据可视化)
    (1)好评度排名:管理员可以看到好评度高的前十个景点【排名、景点名称、好评度】
    (2)景点收藏量:管理员可以看到收藏量排名前十的景点【排名、景点名称、收藏量】

三、系统展示

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


四、核心代码

4.1 随机景点推荐

@RequestMapping(value = "/getRecommendList2OnWeb", method = RequestMethod.GET)
@ApiOperation(value = "查询推荐的景点")
public Result<List<ScenicSpot>> getRecommendList2(){List<ScenicSpot> spotList = iScenicSpotService.list();int[] arr = new int[spotList.size()];for(int i = 1; i < spotList.size(); i ++) {arr[i - 1] = i;}int[] ints = selectM(arr, 10);List<ScenicSpot> ans = new ArrayList<>();for (int i : ints) {ans.add(spotList.get(i));}return new ResultUtil<List<ScenicSpot>>().setData(ans);
}public static int[] selectM(int[] arr,int m){int len=arr.length;if(m>arr.length) {throw new RuntimeException("xxxxx");}int[] res=new int[m];for(int i=0;i<m;i++){int randomIndex=len-1-new Random().nextInt(len-i);res[i]=arr[randomIndex];int tmp=arr[randomIndex];arr[randomIndex]=arr[i];arr[i]=tmp;}return res;
}

4.2 景点评价

@RequestMapping(value = "/addEvaluate", method = RequestMethod.GET)
@ApiOperation(value = "新增评价")
public Result<Evaluate> addEvaluate(@RequestParam String id, @RequestParam BigDecimal level, @RequestParam String message){ScenicSpot ss = iScenicSpotService.getById(id);if(ss == null) {return ResultUtil.error("景点不存在");}User currUser = securityUtil.getCurrUser();QueryWrapper<Evaluate> qw = new QueryWrapper<>();qw.eq("spot_id",ss.getId());qw.eq("user_id",currUser.getId());qw.last("limit 1");Evaluate evaluate = iEvaluateService.getOne(qw);if(evaluate == null) {evaluate = new Evaluate();evaluate.setSpotId(ss.getId());evaluate.setSpotName(ss.getTitle());evaluate.setUserId(currUser.getId());evaluate.setUserName(currUser.getNickname());}evaluate.setLevel(level);evaluate.setMessage(message);evaluate.setTime(DateUtil.now());iEvaluateService.saveOrUpdate(evaluate);return ResultUtil.success();
}

4.3 协同推荐算法

@Scheduled(cron = "0 0/1 * * * ?")
@ApiOperation(value = "景点数据更新")
public void job(){List<ScenicSpot> spotList = iScenicSpotService.list();for (ScenicSpot vo : spotList) {Long evaluateSum = 0L;QueryWrapper<Evaluate> evalQw = new QueryWrapper<>();evalQw.eq("spot_id",vo.getId());List<Evaluate> evaluateList = iEvaluateService.list(evalQw);for (Evaluate evaluate : evaluateList) {evaluateSum += evaluate.getLevel().longValue();}// 收藏 10分QueryWrapper<Collection> coQw = new QueryWrapper<>();coQw.eq("spot_id",vo.getId());evaluateSum += iCollectionService.count(coQw);// 浏览 1分String viewStr = redisTemplate.get("SPOT_VIEW:" + vo.getId());if(!ZwzNullUtils.isNull(viewStr)) {try {long viewNumber = Long.parseLong(viewStr);evaluateSum += viewNumber;} catch (Exception e) {}}vo.setValue(evaluateSum);}Collections.sort(spotList, new Comparator<ScenicSpot>() {@Overridepublic int compare(ScenicSpot o1, ScenicSpot o2) {return (int)(o2.getValue() - o1.getValue());}});if(spotList.size() > 10) {spotList = spotList.subList(0,10);}for (ScenicSpot vo1 : spotList) {// 评分BigDecimal evaluateSum = BigDecimal.ZERO;QueryWrapper<Evaluate> evalQw = new QueryWrapper<>();evalQw.eq("spot_id",vo1.getId());List<Evaluate> evaluateList = iEvaluateService.list(evalQw);for (Evaluate evaluate : evaluateList) {evaluateSum = evaluateSum.add(evaluate.getLevel());}if(evaluateList.size() > 0) {vo1.setStar(evaluateSum.divide(BigDecimal.valueOf(evaluateList.size()),2, RoundingMode.DOWN));} else {vo1.setStar(BigDecimal.valueOf(-1));}// 收藏QueryWrapper<Collection> coQw = new QueryWrapper<>();coQw.eq("spot_id",vo1.getId());vo1.setCollection(iCollectionService.count(coQw));}redisTemplate.set("SPOT_JOB_DATA", JSON.toJSONString(spotList));System.out.println("缓存完毕!");
}

4.4 网站登录

@RequestMapping(value = "/loginOnWeb", method = RequestMethod.GET)
@ApiOperation(value = "网站前台登陆")
public Result<String> loginOnWeb(@RequestParam String userName, @RequestParam String password){QueryWrapper<User> qw = new QueryWrapper<>();qw.eq("username",userName);List<User> userList = iUserService.list(qw);if(userList.size() < 1) {return ResultUtil.error("用户不存在");}User user = userList.get(0);if(!new BCryptPasswordEncoder().matches(password, user.getPassword())){return ResultUtil.error("密码不正确");}String accessToken = securityUtil.getToken(user.getUsername(), true);UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(new SecurityUserDetails(user), null, null);SecurityContextHolder.getContext().setAuthentication(authentication);return new ResultUtil<String>().setData(accessToken);
}

4.5 查询景点美食

@RequestMapping(value = "/getByPage", method = RequestMethod.GET)
@ApiOperation(value = "查询美食")
public Result<IPage<DeliciousFood>> getByPage(@ModelAttribute DeliciousFood deliciousFood ,@ModelAttribute PageVo page){QueryWrapper<DeliciousFood> qw = new QueryWrapper<>();if(!ZwzNullUtils.isNull(deliciousFood.getTitle())) {qw.like("title",deliciousFood.getTitle());}if(!ZwzNullUtils.isNull(deliciousFood.getContent())) {qw.like("content",deliciousFood.getContent());}if(!ZwzNullUtils.isNull(deliciousFood.getSpotId())) {qw.eq("spot_id",deliciousFood.getSpotId());}IPage<DeliciousFood> data = iDeliciousFoodService.page(PageUtil.initMpPage(page),qw);return new ResultUtil<IPage<DeliciousFood>>().setData(data);
}

五、免责说明

  • 本项目仅供个人学习使用,商用授权请联系博主,否则后果自负。
  • 博主拥有本软件构建后的应用系统全部内容所有权及独立的知识产权,拥有最终解释权。
  • 如有问题,欢迎在仓库 Issue 留言,看到后会第一时间回复,相关意见会酌情考虑,但没有一定被采纳的承诺或保证。

下载本系统代码或使用本系统的用户,必须同意以下内容,否则请勿下载!

  1. 出于自愿而使用/开发本软件,了解使用本软件的风险,且同意自己承担使用本软件的风险。
  2. 利用本软件构建的网站的任何信息内容以及导致的任何版权纠纷和法律争议及后果和博主无关,博主对此不承担任何责任。
  3. 在任何情况下,对于因使用或无法使用本软件而导致的任何难以合理预估的损失(包括但不仅限于商业利润损失、业务中断与业务信息丢失),博主概不承担任何责任。
  4. 必须了解使用本软件的风险,博主不承诺提供一对一的技术支持、使用担保,也不承担任何因本软件而产生的难以预料的问题的相关责任。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/122463.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

P1022 [NOIP2000 普及组] 计算器的改良 题解

文章目录 题目背景题目描述输入格式输出格式样例样例输入样例输出 思路及部分实现完整代码 题目背景 NCL 是一家专门从事计算器改良与升级的实验室&#xff0c;最近该实验室收到了某公司所委托的一个任务&#xff1a;需要在该公司某型号的计算器上加上解一元一次方程的功能。实…

2017年上半年上午易错题(软件设计师考试)

CPU 执行算术运算或者逻辑运算时&#xff0c;常将源操作数和结果暂存在&#xff08; &#xff09;中。 A &#xff0e; 程序计数器 (PC) B. 累加器 (AC) C. 指令寄存器 (IR) D. 地址寄存器 (AR) 某系统由下图所示的冗余部件构成。若每个部件的千小时可靠度都为 R &…

【Python机器学习】零基础掌握partial_dependence检验、检查

在医疗健康的领域,有一个问题一直困扰着专家——如何从多个健康指标中找出影响患者健康最关键的因素?在这样的场景下,做出准确的预测非常关键,因为它直接关联到患者的生命安全。 解决这一问题的一个有效方法是利用机器学习算法,具体来说就是通过偏依赖图(Partial Depend…

微信小程序在线预览PDF文件

需求&#xff1a;微信小程序在线预览PDF合同文件&#xff0c;加载完成后强制阅读10秒才可点击同意按钮 H5代码&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" cont…

如何使用手机蓝牙设备作为电脑的解锁工具像动态锁那样,蓝牙接近了电脑,电脑自动解锁无需输入开机密码

环境&#xff1a; Win10 专业版 远程解锁 蓝牙解锁小程序 问题描述&#xff1a; 如何使用手机蓝牙设备作为电脑的解锁工具像动态锁那样&#xff0c;蓝牙接近了电脑&#xff0c;电脑自动解锁无需输入开机密码 手机不需要拿出来&#xff0c;在口袋里就可以自动解锁&#xff…

nlp之加载电商评论集

目录 代码代码解读 代码 import pandas as pddf pd.read_csv("../data/Clothing Reviews.csv") print(df.info())df[Review Text] df[Review Text].astype(str) x_train df[Review Text] y_train df[Rating]from tensorflow.keras.preprocessing.text import To…

Geeker-Admin中ProTable表格分页之自定义接口页码、尺寸参数

最近挖了个新玩意儿&#xff0c;Geeker-Admin&#xff0c;看起来感觉挺好。 鼓捣了半天搞定了与服务端的API接口对接&#xff0c;但在表格分页的时候又遇到了问题&#xff0c;系统默认是pageNum/pageSize这两个参数名用来分页&#xff0c;而服务端是current/size&#xff0c;开…

C#,数值计算——分类与推理,基座向量机的 Svmgenkernel的计算方法与源程序

1 文本格式 using System; namespace Legalsoft.Truffer { public abstract class Svmgenkernel { public int m { get; set; } public int kcalls { get; set; } public double[,] ker { get; set; } public double[] y { get; set…

微信小程序瀑布流组件

话不多说直接上干货: 现在component中创建一个waterfull的文件夹&#xff0c;并创建对应的wxml,wxss,jx,json文件 wxml&#xff1a; <view class"content"><view class"content-left"><block wx:for"{{list}}" wx:key"…

机器学习-特征选择:如何使用互信息特征选择挑选出最佳特征?

一、引言 特征选择在机器学习中扮演着至关重要的角色&#xff0c;它可以帮助我们从大量的特征中挑选出对目标变量具有最大预测能力的特征。互信息特征选择是一种常用的特征选择方法&#xff0c;它通过计算特征与目标变量之间的互信息来评估特征的重要性。 互信息是信息论中的一…

前端线上部署,如何通知用户有新版本

前言 version-polling 是一个轻量级的 JavaScript 库&#xff0c;它可以实时检测 web 应用的 index.html 文件内容是否有变化。当服务端发布新版本后&#xff0c;前端会自动弹出更新提示&#xff0c;让用户刷新页面&#xff0c;以加载最新的资源和功能。这样可以提高用户体验和…

verilog vscode linux

安装 vscode 插件 插件&#xff1a;Verilog-HDL/SystemVerilog/Bluespec SystemVerilog 功能&#xff1a;.xdc .ucf .v 等代码高亮、代码格式化、语法检查&#xff08;Linting&#xff09;、光标放到变量上提示变量的信息等 关于其他语言的依赖工具等信息查看插件说明 代码对齐…

Csdn文章编写参考案例

这里写自定义目录标题 欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants 创建一个自定义列表如何创建一个…

解决visual studio Just-In-Time Debugger调试

解决visual studio Just-In-Time Debugger调试 网上流行很多方法&#xff0c;最后一直不行&#xff0c;其实有最简单的方法比较实用 方法一&#xff1a;把 C:\WINDOWS\system32\vsjitdebugger.exe,删除了&#xff0c;若怕出问题&#xff0c;可以把它改名或者做个rar文件暂时保留…

cosover是什么?crossover23又是什么软件

cosover是篮球里的过人技巧。 1.crossover在篮球中的本意是交叉步和急速交叉步。crossover 是篮球术语&#xff0c;有胯下运球、双手交替运球&#xff0c;交叉步过人、急速大幅度变向等之意。 2.在NBA里是指包括胯下运球、变向、插花在内的过人的技巧。 NBA有很多著名的Cross…

获取客户端请求IP及IP所属城市

添加pom依赖 <dependency> <groupId>org.lionsoul</groupId> <artifactId>ip2region</artifactId> <version>2.6.5</version> </dependency> public class IpUtil { private…

Linux进程等待

一、进程等待是什么&#xff1f; 通过系统调用wait/waitpid&#xff0c;来对子进程进行状态检验与回收的工作。 二、为什么要有进程等待 1、子进程退出&#xff0c;父进程如果不管不顾&#xff0c;就可能造成‘僵尸进程’的问题&#xff0c;进而造成内存泄漏。 另外&#xf…

数据库分库分表的原则

目录 1、数据库分库分表是什么 2、为什么要对数据库分库分表 3、何时选择分库分表 4、⭐分库分表遵循的原则 5、分库分表的方式 6、数据存放在表和库中的规则&#xff08;算法&#xff09; 7、分库分表的架构模式 8、分库分表的问题 小结 1、数据库分库分表是什么 数…

vscode提取扩展出错xhr

在 Visual Studio Code (VSCode) 中提取扩展出现 XHR 错误通常意味着在下载扩展或进行扩展管理操作时出现了网络请求问题。XHR (XMLHttpRequest) 是一种用于在浏览器中进行 HTTP 请求的技术&#xff0c;通常用于获取数据或资源。在 VSCode 中&#xff0c;它也可用于管理扩展的下…

redirect导致的循环重定向问题(史上最全)

目录 PathVariable注解和redirect的作用 使用场景 返回值未命中 返回值路径讲解 起因&#xff1a;#记录一下学习编程遇到的最难受的一个bug PathVariable注解和redirect的作用 首先了解一下PathVariable和redirect 在Spring框架中&#xff0c;PathVariable 注解主要用于…