当前位置: 首页 > news >正文

重学SpringBoot3-集成Redis(十一)之地理位置数据存储

更多SpringBoot3内容请关注我的专栏:《SpringBoot3》
期待您的点赞👍收藏⭐评论✍

重学SpringBoot3-集成Redis(十一)之地理位置数据存储

  • 1. GEO 命令简介
  • 2. 项目环境配置
    • 2.1. 依赖引入
    • 2.2. Redis 配置
  • 3. GEO 数据存储和查询实现
    • 3.1. 服务层实现
    • 3.2. 控制层
  • 4. 使用示例
    • 4.1. 添加城市位置信息
    • 4.2. 查询城市位置信息
    • 4.3. 计算两城市之间的距离
    • 4.4. 查询指定城市附近的其他城市
  • 5. 总结

Redis 是一个强大的内存数据存储工具,不仅可以用来缓存和存储传统数据,还支持存储地理位置信息。通过 Redis 提供的 GEO 命令集,开发者可以方便地进行地理位置的存储、查询和计算操作。本文将介绍如何通过 Spring Boot 3 与 Redis 集成来实现地理位置数据存储功能,并进行相关的操作。


1. GEO 命令简介

Redis 的 GEO 命令主要用于存储经纬度和关联的数据,并支持基于这些数据进行距离计算和范围查询。常用的 GEO 命令有:

  • GEOADD:添加地理位置。
  • GEOPOS:获取指定成员的地理位置(经纬度)。
  • GEODIST:计算两个地理位置之间的距离。
  • GEORADIUS:以给定的经纬度为中心,查询某个范围内的地理位置。
  • GEORADIUSBYMEMBER:以给定的成员位置为中心,查询某个范围内的地理位置。

2. 项目环境配置

2.1. 依赖引入

首先,在 pom.xml 中引入 Spring Boot 3Redis 的相关依赖,具体参考重学SpringBoot3-集成Redis(一)之基本使用:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

2.2. Redis 配置

application.yml 中配置 Redis 连接:

spring:data:redis:host: localhostport: 6379            # Redis 端口password: redis123456 # 如果有密码可以在这里配置lettuce:pool:max-active: 100    # 最大并发连接数max-idle: 50       # 最大空闲连接数min-idle: 10       # 最小空闲连接数

3. GEO 数据存储和查询实现

3.1. 服务层实现

我们将通过 StringRedisTemplate 来操作 Redis 的 GEO 命令。

package com.coderjia.boot310redis.service;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.geo.Distance;
import org.springframework.data.geo.GeoResult;
import org.springframework.data.geo.GeoResults;
import org.springframework.data.geo.Point;
import org.springframework.data.redis.connection.RedisGeoCommands;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;import java.util.ArrayList;
import java.util.List;/*** @author CoderJia* @create 2024/10/9 下午 10:10* @Description**/
@Service
public class GeoLocationService {@Autowiredprivate StringRedisTemplate redisTemplate;private static final String GEO_KEY = "city_locations";// 添加地理位置public void addGeoLocation(String cityName, double longitude, double latitude) {redisTemplate.opsForGeo().add(GEO_KEY, new Point(longitude, latitude), cityName);}// 获取地理位置public Point getGeoLocation(String cityName) {List<Point> positions = redisTemplate.opsForGeo().position(GEO_KEY, cityName);return positions != null && !positions.isEmpty() ? positions.get(0) : null;}// 计算两个城市之间的距离public Distance getDistance(String city1, String city2) {return redisTemplate.opsForGeo().distance(GEO_KEY, city1, city2, RedisGeoCommands.DistanceUnit.KILOMETERS);}// 查找指定范围内的城市public List<String> getCitiesWithinRadius(String cityName, double radius) {GeoResults<RedisGeoCommands.GeoLocation<String>> results = redisTemplate.opsForGeo().radius(GEO_KEY, cityName, new Distance(radius, RedisGeoCommands.DistanceUnit.KILOMETERS));List<String> cities = new ArrayList<>();if (results != null) {for (GeoResult<RedisGeoCommands.GeoLocation<String>> result : results) {cities.add(result.getContent().getName());}}return cities;}
}

3.2. 控制层

为了方便测试,我们可以通过简单的控制器来调用这些服务。

package com.coderjia.boot310redis.demos.web;import com.coderjia.boot310redis.service.GeoLocationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.geo.Distance;
import org.springframework.data.geo.Point;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;import java.util.List;/*** @author CoderJia* @create 2024/10/9 下午 10:14* @Description**/
@RestController
@RequestMapping("/geo")
public class GeoLocationController {@Autowiredprivate GeoLocationService geoLocationService;// 添加城市位置@PostMapping("/add")public String addCity(@RequestParam("city") String city, @RequestParam("lon") double lon, @RequestParam("lat") double lat) {geoLocationService.addGeoLocation(city, lon, lat);return "Added " + city;}// 查询城市位置@GetMapping("/location")public Point getCityLocation(@RequestParam("city") String city) {return geoLocationService.getGeoLocation(city);}// 计算两个城市之间的距离@GetMapping("/distance")public Distance getDistance(@RequestParam("city1") String city1, @RequestParam("city2") String city2) {return geoLocationService.getDistance(city1, city2);}// 查找指定城市附近的城市@GetMapping("/nearby")public List<String> getNearbyCities(@RequestParam("city") String city, @RequestParam("radius") double radius) {return geoLocationService.getCitiesWithinRadius(city, radius);}
}

4. 使用示例

4.1. 添加城市位置信息

通过 POST 请求添加城市位置信息,城市经纬度查询参考:https://lbs.amap.com/tools/picker

添加北上广深杭五座城市:

POST localhost:8080/geo/add?city=Beijing&lon=116.40&lat=39.90
POST localhost:8080/geo/add?city=Shanghai&lon=121.47&lat=31.23
POST localhost:8080/geo/add?city=GuangZhou&lon=113.26&lat=23.14
POST localhost:8080/geo/add?city=ShenZhen&lon=114.06&lat=22.54
POST localhost:8080/geo/add?city=HangZhou&lon=120.12&lat=30.22

添加城市位置信息

4.2. 查询城市位置信息

查询城市的经纬度信息:

GET localhost:8080/geo/location?city=Beijing

查询城市位置信息

4.3. 计算两城市之间的距离

计算两个城市之间的距离:

GET localhost:8080/geo/distance?city1=Beijing&city2=Shanghai

计算两城市之间的距离

4.4. 查询指定城市附近的其他城市

查询上海附近的其他城市(比如 200 公里内的城市):

GET localhost:8080/geo/nearby?city=Shanghai&radius=200

查询指定城市附近的其他城市

5. 总结

通过 Redis 的 GEO 命令集与 Spring Boot 3 集成,我们可以轻松实现地理位置的存储与查询功能。这种方式不仅方便,而且具有很高的性能,尤其适用于地理位置相关的应用场景,如地图服务、物流系统、附近商家查询等。

使用 Redis 进行地理位置存储的优势在于其操作简单、高效,并且能够借助 Redis 内置的命令进行实时的距离计算和范围查询。如果你的应用涉及地理信息,Redis 提供的 GEO 功能会是一个非常不错的选择。

相关文章:

重学SpringBoot3-集成Redis(十一)之地理位置数据存储

更多SpringBoot3内容请关注我的专栏&#xff1a;《SpringBoot3》 期待您的点赞&#x1f44d;收藏⭐评论✍ 重学SpringBoot3-集成Redis&#xff08;十一&#xff09;之地理位置数据存储 1. GEO 命令简介2. 项目环境配置2.1. 依赖引入2.2. Redis 配置 3. GEO 数据存储和查询实现3…...

Docker-compose 单节点管理、consul 注册中心、registrator、template

consul是一个基于分布式的服务发现和配置管理工具。它具有快速构建分布式架构&#xff0c;提供服务发现和服务注册功能。consul职能&#xff1a;1、自动发现、注册&#xff1b;2、自动配置&#xff1b;3、自动更新 服务发现&#xff1a;自动检查网络中的服务&#xff08;如数据…...

制药企业MES与TMS的数据库改造如何兼顾安全与效率双提升

*本图由AI生成 在全球制造业加速数字化转型的浪潮中&#xff0c;一家来自中国的、年营业额超过200亿元的制药企业以其前瞻性的视角和果断的行动&#xff0c;成为该行业里进行国产化改造的先锋。通过实施数据库改造试点项目&#xff0c;该企业实现了其关键业务系统MES&#xff0…...

Spring Boot比Spring多哪些注解

Spring Boot 是 Spring 框架的扩展&#xff0c;它旨在简化 Spring 应用程序的初始搭建以及开发过程。与 Spring 相比&#xff0c;Spring Boot 提供了许多额外的注解来进一步简化配置和开发工作。以下是 Spring Boot 特有的一些核心注解&#xff0c;这些注解在 Spring 中不可用&…...

985研一学习日记 - 2024.10.17

一个人内耗&#xff0c;说明他活在过去&#xff1b;一个人焦虑&#xff0c;说明他活在未来。只有当一个人平静时&#xff0c;他才活在现在。 日常 1、起床6:00√ 2、健身1个多小时 今天练了二头和背部&#xff0c;明天练胸和三头 3、LeetCode刷了3题 旋转图像&#xff1a…...

牛客SQL29详解 计算用户的平均次日留存率

牛客SQL29详解 计算用户的平均次日留存率 牛客SQL29详解 计算用户的平均次日留存率 叮嘟&#xff01;这里是小啊呜的学习课程资料整理。好记性不如烂笔头&#xff0c;今天也是努力进步的一天。一起加油进阶吧&#xff01; 牛客SQL29详解 计算用户的平均次日留存率 题目&#x…...

Redis --- 第四讲 --- 常用数据结构 --- 其他类型stream、bitmap……。补充内容scan命令。

通过前面的学习&#xff0c;我们已经学习了Redis最关键的五个数据结构&#xff1a;String、List、Hash、Set、ZSet。这五个数据结构应用广泛&#xff0c;频繁使用。 redis中包含的所有类型&#xff0c;下面将要介绍不常用的类型。 一、streams类型介绍 事件、epoll/IO多路复…...

Java多线程--实现跑马小游戏

线程的实现方式 继承Thread类&#xff1a;void run()方法没有返回值&#xff0c;无法抛异常实现Runnable接口&#xff1a;void run()方法没有返回值&#xff0c;无法抛异常实现Callable接口&#xff1a;V call() throws Exception 返回结果&#xff0c;能够抛异常 实现Callab…...

扫雷(C 语言)

目录 一、游戏设计分析二、各个步骤的代码实现1. 游戏菜单界面的实现2. 游戏初始化3. 开始扫雷 三、完整代码四、总结 一、游戏设计分析 本次设计的扫雷游戏是展示一个 9 * 9 的棋盘&#xff0c;然后输入坐标进行判断&#xff0c;若是雷&#xff0c;则游戏结束&#xff0c;否则…...

有源滤波器(一)

滤波器设计工具 | 滤波器设计向导 | Analog Devices 一种带通滤波器&#xff1a; 有源滤波器完美规避了这个带不带负载滤波参数变化的问题&#xff0c;但是有源滤波器只能处理小电流和小电压&#xff1a; 鼠标所指的电路图是一阶同相滤波器&#xff0c;右上角的是他的幅频特性…...

Flume面试整理-常见的Channel类型

Apache Flume提供了多种Channel(通道)类型,作为Source(源)和Sink(汇)之间的缓冲区,确保数据的可靠传输。不同类型的Channel提供了不同的性能和可靠性,适用于不同的应用场景。以下是Flume中常见的Channel类型及其特点: 1. Memory Channel ● 描述:Memory Channel将数…...

【前端】如何制作一个自己的网页(6)

接上文 网络中的图片 我们也可以在百度等网站搜索自己喜欢的图片。 此时对图片点击右键&#xff0c;选择【复制图片地址】&#xff0c;即可获得该图片的网络地址。 其实在HTML中&#xff0c;除了图片以外&#xff0c;我们还可以利用地址找到另一个网页。 如右图所示&#…...

Linux系统性能调优技巧

Linux系统性能调优是一个复杂而持续的过程&#xff0c;需要综合考虑硬件、软件、内核参数、进程管理等多个方面。以下是一些具体的调优技巧&#xff1a; 一、硬件优化 增加物理内存&#xff1a;内存不足时&#xff0c;系统会频繁进行交换&#xff08;swapping&#xff09;活动…...

数学建模算法与应用 第5章 插值与拟合方法

目录 5.1 插值方法 Matlab代码示例&#xff1a;线性插值 Matlab代码示例&#xff1a;样条插值 5.2 曲线拟合的线性最小二乘法 Matlab代码示例&#xff1a;线性拟合 5.3 最小二乘优化与多项式拟合 Matlab代码示例&#xff1a;多项式拟合 5.4 曲线拟合与函数逼近 Matlab代…...

3D Slicer 教程二 ---- 数据集

上一章下载3d slicer的软件,这章从加载数据集来弄清楚3dslicer怎么使用. 一. 加载数据集 如果没有数据集,也可用用样本数据. (1) "File" --> "add Data" 可以添加图片文件夹,(试了MP4不行,内镜的视频估计不支持),添加单个图片的话,会出现一些选项, …...

【建议收藏】30个Java异常的知识点,你能撑到第几个?

文章目录 问题1&#xff1a;Error 和 Exception 区别是什么&#xff1f;问题2&#xff1a;运行时异常和一般异常(受检异常)区别是什么&#xff1f;问题3&#xff1a;JVM 是如何处理异常的&#xff1f;问题4&#xff1a;throw 和 throws 的区别是什么&#xff1f;问题5&#xff…...

【Linux系统编程】环境基础开发工具使用

目录 1、Linux软件包管理器yum 1.1 什么是软件包 1.2 安装软件 1.3 查看软件包 1.4 卸载软件 2、Linux编辑器-vim 2.1 vim的概念 2.2 vim的基本操作 2.3 vim的配置 3、Linux编译器-gcc/g 3.1 gcc编译的过程​编辑​编辑​编辑 3.2 详解链接 动态链接 静态链接 4…...

滚雪球学Redis[6.2讲]:Redis脚本与Lua:深入掌握Redis中的高效编程技巧

全文目录&#xff1a; &#x1f4dd;前言&#x1f6a6;正文&#x1f31f;6.2.1 Lua脚本的优势&#x1f58b;️6.2.2 EVAL命令与Lua脚本编写&#x1f435;编写Lua脚本的基本步骤&#x1f436;示例&#xff1a;简单的GET和SET操作&#x1f431;示例&#xff1a;Lua实现自增和过期…...

上市不到一月,极氪7X交付破万台!论纯电,极氪真“遥遥领先”

承认吧&#xff0c;在纯电这条赛道上&#xff0c;极氪真就“遥遥领先”~ 推出的第一款原生纯电猎装极氪001&#xff0c;就常年霸榜25万级豪华纯电销冠 主打豪华大车的极氪009&#xff0c;成为40万以上高端“保姆车”的不二之选 第一次面向主流纯电市场推出的豪华大五座——极…...

【Linux】理解文件系统与软硬链接,观察inode号理解<“软链接是包含路径的新文件“,“硬链接是关于文件名的机制“>,最终明白<什么是真正删除一个文件>

前言 大家好吖&#xff0c;欢迎来到 YY 滴Linux系列 &#xff0c;热烈欢迎&#xff01; 本章主要内容面向接触过C的老铁 主要内容含&#xff1a; 欢迎订阅 YY滴C专栏&#xff01;更多干货持续更新&#xff01;以下是传送门&#xff01; YY的《C》专栏YY的《C11》专栏YY的《Lin…...

全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比

目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec&#xff1f; IPsec VPN 5.1 IPsec传输模式&#xff08;Transport Mode&#xff09; 5.2 IPsec隧道模式&#xff08;Tunne…...

Springboot社区养老保险系统小程序

一、前言 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受用户的喜爱&#xff0c;社区养老保险系统小程序被用户普遍使用&#xff0c;为方…...

C++.OpenGL (14/64)多光源(Multiple Lights)

多光源(Multiple Lights) 多光源渲染技术概览 #mermaid-svg-3L5e5gGn76TNh7Lq {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-3L5e5gGn76TNh7Lq .error-icon{fill:#552222;}#mermaid-svg-3L5e5gGn76TNh7Lq .erro…...

腾讯云V3签名

想要接入腾讯云的Api&#xff0c;必然先按其文档计算出所要求的签名。 之前也调用过腾讯云的接口&#xff0c;但总是卡在签名这一步&#xff0c;最后放弃选择SDK&#xff0c;这次终于自己代码实现。 可能腾讯云翻新了接口文档&#xff0c;现在阅读起来&#xff0c;清晰了很多&…...

Qemu arm操作系统开发环境

使用qemu虚拟arm硬件比较合适。 步骤如下&#xff1a; 安装qemu apt install qemu-system安装aarch64-none-elf-gcc 需要手动下载&#xff0c;下载地址&#xff1a;https://developer.arm.com/-/media/Files/downloads/gnu/13.2.rel1/binrel/arm-gnu-toolchain-13.2.rel1-x…...

深度学习之模型压缩三驾马车:模型剪枝、模型量化、知识蒸馏

一、引言 在深度学习中&#xff0c;我们训练出的神经网络往往非常庞大&#xff08;比如像 ResNet、YOLOv8、Vision Transformer&#xff09;&#xff0c;虽然精度很高&#xff0c;但“太重”了&#xff0c;运行起来很慢&#xff0c;占用内存大&#xff0c;不适合部署到手机、摄…...

ubuntu22.04有线网络无法连接,图标也没了

今天突然无法有线网络无法连接任何设备&#xff0c;并且图标都没了 错误案例 往上一顿搜索&#xff0c;试了很多博客都不行&#xff0c;比如 Ubuntu22.04右上角网络图标消失 最后解决的办法 下载网卡驱动&#xff0c;重新安装 操作步骤 查看自己网卡的型号 lspci | gre…...

xmind转换为markdown

文章目录 解锁思维导图新姿势&#xff1a;将XMind转为结构化Markdown 一、认识Xmind结构二、核心转换流程详解1.解压XMind文件&#xff08;ZIP处理&#xff09;2.解析JSON数据结构3&#xff1a;递归转换树形结构4&#xff1a;Markdown层级生成逻辑 三、完整代码 解锁思维导图新…...

node.js的初步学习

那什么是node.js呢&#xff1f; 和JavaScript又是什么关系呢&#xff1f; node.js 提供了 JavaScript的运行环境。当JavaScript作为后端开发语言来说&#xff0c; 需要在node.js的环境上进行当JavaScript作为前端开发语言来说&#xff0c;需要在浏览器的环境上进行 Node.js 可…...

UE5 音效系统

一.音效管理 音乐一般都是WAV,创建一个背景音乐类SoudClass,一个音效类SoundClass。所有的音乐都分为这两个类。再创建一个总音乐类&#xff0c;将上述两个作为它的子类。 接着我们创建一个音乐混合类SoundMix&#xff0c;将上述三个类翻入其中&#xff0c;通过它管理每个音乐…...