【开源】基于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)周边美食:美食图片、名称、类型、简介、人均消费 - 景点数据:景点数据可视化
(1)好评度排名:管理员可以看到好评度高的前十个景点【排名、景点名称、好评度】
(2)景点收藏量:管理员可以看到收藏量排名前十的景点【排名、景点名称、收藏量】 - 个人中心:
(1)个人信息:账号、姓名、联系方式、身份证号(用户可以更新个人信息、退出登录)
(2)景点收藏:用户可以查看、取消收藏过的景点
2.2 管理员端
- 个人中心:管理员个人信息
- 景点信息管理:
(1)查询:可通过搜索景点名称、地址、景点类型来获取需要的景点数据(搜索到需要的景点数据后可进行查看、修改、删除景点信息操作)
(2)添加:可以添加新的景点信息 - 用户信息管理:
(1)查询:可通过搜索用户账号来查询需要的用户(查询到需要的用户后可对用户信息进行查看、修改、删除操作)
(2)添加:可添加新用户信息 - 行程信息管理:
(1)查询:可通搜索景点地址来获取景点行程路线信息(查询到需要的行程信息后可对其进行查看、修改、删除操作)
(2)添加:可添加信息 - 美食信息管理:
(1)查询:可通搜索景点地址来获取景点周边美食信息(查询到需要的信息后可对其进行查看、修改、删除操作)
(2)添加:可添加新的美食信息 - 景点数据:景点数据可视化(同用户端的景点数据可视化)
(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 留言,看到后会第一时间回复,相关意见会酌情考虑,但没有一定被采纳的承诺或保证。
下载本系统代码或使用本系统的用户,必须同意以下内容,否则请勿下载!
- 出于自愿而使用/开发本软件,了解使用本软件的风险,且同意自己承担使用本软件的风险。
- 利用本软件构建的网站的任何信息内容以及导致的任何版权纠纷和法律争议及后果和博主无关,博主对此不承担任何责任。
- 在任何情况下,对于因使用或无法使用本软件而导致的任何难以合理预估的损失(包括但不仅限于商业利润损失、业务中断与业务信息丢失),博主概不承担任何责任。
- 必须了解使用本软件的风险,博主不承诺提供一对一的技术支持、使用担保,也不承担任何因本软件而产生的难以预料的问题的相关责任。
相关文章:

【开源】基于SpringBoot的海南旅游景点推荐系统的设计和实现
目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 用户端2.2 管理员端 三、系统展示四、核心代码4.1 随机景点推荐4.2 景点评价4.3 协同推荐算法4.4 网站登录4.5 查询景点美食 五、免责说明 一、摘要 1.1 项目介绍 基于VueSpringBootMySQL的海南旅游推荐系统ÿ…...

字符串中的assert和strcat
assert:函数原型是:void assert( int expression );其作用是现计算表达式 expression ,如果其值为假(即为0),那么它先 stderr 打印一条出信息,然后通过调用 abort 来终止程序运行。使用assert 的缺点是,频繁的调用会影…...

方舟生存进化ARK个人服务器搭建教程保姆级
方舟生存进化ARK个人服务器搭建教程保姆级 大家好我是艾西,在很久之前我有给大家分享过方舟生存进化的搭建架设教程,但时间久远且以前的教程我现在回头看去在某些地方说的并不是那么清楚。最近也是闲暇无事打算重新巩固下方舟生存进化的搭建架设教程&…...
SpringBoot可以连接RabbitMQ集群吗 ?
目录 一、SpringBoot可以连接RabbitMQ集群吗?二、springboot连接到rabbitmq集群可以负载均衡吗?三、SpringBoot既然可以配置负载均衡,为什么还需要Haproxy做负载均衡? 一、SpringBoot可以连接RabbitMQ集群吗? Spring …...
【机器学习】KNN算法-模型选择与调优
KNN算法-模型选择与调优 文章目录 KNN算法-模型选择与调优1. 交叉验证2. 超参数搜索-网格搜索(Grid Search)3. 模型选择与调优API4. 鸢尾花种类预测-代码和输出结果5. 计算距离 问题背景:KNN算法的K值不好确定 1. 交叉验证 交叉验证&#x…...

NPM【问题 01】npm i node-sass@4.14.1报错not found: python2及Cannot download问题处理
node-sass安装问题处理 1.问题2.处理2.1 方案一【我的环境失败】2.2 方案二【成功】2.3 方案三【成功】 1.问题 gyp verb which failed Error: not found: python2 # 1.添加Python27的安装路径到环境变量 gyp verb check python checking for Python executable "python…...
redis集群中节点fail,noaddr
文章目录 1. 问题:fail,noaddr2. cluster nodes节点信息解读2.1 每个字段的含义2.2 flags字段各标记含义 3. redis集群fail,noaddr问题解决4. cluster指令5. 相关文章(1) redis集群搭建(2) 华为云两台机器内网互联(3) /etc/rc.d/init.d 详解|程序开机自启(4) Redis5…...
Fourier分析导论——第1章——Fourier分析的起源(E.M. Stein R. Shakarchi)
第 1 章 Fourier分析的起源 (The Genesis of Fourier Analysis) Regarding the researches of dAlembert and Euler could one not add that if they knew this expansion, they made but a very imperfect use of it. They were both persuaded that an arbitrary and d…...

使用Node.js软件包管理器(npm)安装TypeScript
安装node.js node.js的安装很简单,这里不再赘述,如果大家有需要,可以看一下这个:https://blog.csdn.net/David_house/article/details/123218488 检验电脑上node.js是否安装成功,或者是否已经安装node.js,…...

鸿蒙ArkUI-X跨端应用开发,一套代码构建多平台应用
文章目录 一、项目介绍二、技术架构三、Gitee仓库地址四、ArkUI-X开发者文档五、快速开始——环境准备1、下载DevEco Studio,版本V4.0 Beta2以上2、打开DevEco,下载相关环境配置3、配置开发环境3.1、OpenHarmony SDK3.2、安装ArkUI-X SDK3.2、Android SD…...

【鸿蒙软件开发】ArkTS基础组件之Gauge(环形图表)、LoadingProgress(动态加载)
文章目录 前言一、Gauge环形图表1.1 子组件1.2 接口参数介绍 1.2 属性1.3 示例代码二、LoadingProgress2.1 子组件2.2 接口2.3 属性2.4 示例代码 总结 前言 Gauge:数据量规图表组件,用于将数据展示为环形图表。 LoadingProgress:用于显示加载…...

C++模板类用作参数传递
前言 在模板类<>传递参数的一种实现。记不住,以此记录。 // dome.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。 // #define _CRT_SECURE_NO_WARNINGS #include <iostream> //#include "tools.h" #include <fu…...

SQL server 代理服务启动和查看
设置重启 使用管理员权限登录到运行 SQL Server 代理服务的计算机。 打开 Windows 服务管理器。可以通过按下 Windows 键 R,然后键入 "services.msc" 并按 Enter 来打开服务管理器。 在服务列表中,找到 "SQL Server Agent" 服务&…...

单例模式详解【2023年最新】
一、单例模式概念 单例模式是一种创建型设计模式,它确保一个类只有一个实例,并提供一个全局访问点来访问该实例。它的目的是限制一个类只能创建一个对象,以确保在整个应用程序中只有一个共享的实例。 单例模式通常用于以下情况:…...

读高性能MySQL(第4版)笔记21_读后总结与感想兼导读
1. 基本信息 高性能MySQL:经过大规模运维验证的策略(第4版) High Performance MySQL, Fourth Edition [美] Silvia Botros(西尔维亚博特罗斯);Jeremy Tinley(杰里米廷利) 电子工业出版社,2022年10月出版 1.1. 读薄率 书籍总字…...
放学辣[简单版]
链接:登录—专业IT笔试面试备考平台_牛客网 来源:牛客网 题目描述 本题和 D 题的唯一区别是 NNN 的范围。 校园里目前有 NNN 名学生,这些学生属于 MMM 个班级。第 iii(i1,2,...,Ni 1,2,...,Ni1,2,...,N)个人属于第…...
面向对象设计——原型模式
原型设计模式是一种创建型设计模式,其主要目标是创建对象的新实例,同时尽量减少与使用者的交互,以降低对象创建的复杂性。这通过复制(或克隆)现有对象的实例来实现,以获得新对象,而不是通过实例化类来创建。 以下是原型设计模式的关键概念: 原型接口(Prototype Inter…...

SpringAOP源码解析之advice执行顺序(三)
上一章我们分析了Aspect中advice的排序为Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class,然后advice真正的执行顺序是什么?多个Aspect之间的执行顺序又是什么?就是我们本章探讨的问题。 准备工作 既…...

CentOS 安装 tomcat 并设置 开机自启动
CentOS 安装 tomcat 并设置 开机自启动 下载jdk和tomcat curl https://download.oracle.com/java/21/latest/jdk-21_linux-x64_bin.tar.gz curl https://dlcdn.apache.org/tomcat/tomcat-10/v10.1.15/bin/apache-tomcat-10.1.15.tar.gz解压jdk和tomcat并修改目录名称 tar -z…...

论文阅读——ELECTRA
论文下载:https://openreview.net/pdf?idr1xMH1BtvB 另一篇分析文章:ELECTRA 详解 - 知乎 一、概述 对BERT的token mask 做了改进。结合了GAN生成对抗模型的思路,但是和GAN不同。 不是对选择的token直接用mask替代,而是替换为…...

深入剖析AI大模型:大模型时代的 Prompt 工程全解析
今天聊的内容,我认为是AI开发里面非常重要的内容。它在AI开发里无处不在,当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗",或者让翻译模型 "将这段合同翻译成商务日语" 时,输入的这句话就是 Prompt。…...
如何为服务器生成TLS证书
TLS(Transport Layer Security)证书是确保网络通信安全的重要手段,它通过加密技术保护传输的数据不被窃听和篡改。在服务器上配置TLS证书,可以使用户通过HTTPS协议安全地访问您的网站。本文将详细介绍如何在服务器上生成一个TLS证…...

多模态大语言模型arxiv论文略读(108)
CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文标题:CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文作者:Sayna Ebrahimi, Sercan O. Arik, Tejas Nama, Tomas Pfister ➡️ 研究机构: Google Cloud AI Re…...

【开发技术】.Net使用FFmpeg视频特定帧上绘制内容
目录 一、目的 二、解决方案 2.1 什么是FFmpeg 2.2 FFmpeg主要功能 2.3 使用Xabe.FFmpeg调用FFmpeg功能 2.4 使用 FFmpeg 的 drawbox 滤镜来绘制 ROI 三、总结 一、目的 当前市场上有很多目标检测智能识别的相关算法,当前调用一个医疗行业的AI识别算法后返回…...

短视频矩阵系统文案创作功能开发实践,定制化开发
在短视频行业迅猛发展的当下,企业和个人创作者为了扩大影响力、提升传播效果,纷纷采用短视频矩阵运营策略,同时管理多个平台、多个账号的内容发布。然而,频繁的文案创作需求让运营者疲于应对,如何高效产出高质量文案成…...
Spring Security 认证流程——补充
一、认证流程概述 Spring Security 的认证流程基于 过滤器链(Filter Chain),核心组件包括 UsernamePasswordAuthenticationFilter、AuthenticationManager、UserDetailsService 等。整个流程可分为以下步骤: 用户提交登录请求拦…...

消息队列系统设计与实践全解析
文章目录 🚀 消息队列系统设计与实践全解析🔍 一、消息队列选型1.1 业务场景匹配矩阵1.2 吞吐量/延迟/可靠性权衡💡 权衡决策框架 1.3 运维复杂度评估🔧 运维成本降低策略 🏗️ 二、典型架构设计2.1 分布式事务最终一致…...

python基础语法Ⅰ
python基础语法Ⅰ 常量和表达式变量是什么变量的语法1.定义变量使用变量 变量的类型1.整数2.浮点数(小数)3.字符串4.布尔5.其他 动态类型特征注释注释是什么注释的语法1.行注释2.文档字符串 注释的规范 常量和表达式 我们可以把python当作一个计算器,来进行一些算术…...

第2课 SiC MOSFET与 Si IGBT 静态特性对比
2.1 输出特性对比 2.2 转移特性对比 2.1 输出特性对比 器件的输出特性描述了当温度和栅源电压(栅射电压)为某一具体数值时,漏极电流(集电极电流...

可下载旧版app屏蔽更新的app市场
软件介绍 手机用久了,app越来越臃肿,老手机卡顿成常态。这里给大家推荐个改善老手机使用体验的方法,还能帮我们卸载不需要的app。 手机现状 如今的app不断更新,看似在优化,实则内存占用越来越大,对手机性…...