首页 > 数据库 >分享一个 SpringBoot + Redis 实现「查找附近的人」的小技巧

分享一个 SpringBoot + Redis 实现「查找附近的人」的小技巧

时间:2023-09-11 10:01:40浏览次数:38  
标签:SpringBoot RequestParam Redis userId springframework 查找 new import

前言

SpringDataRedis提供了十分简单的地理位置定位的功能,今天我就用一小段代码告诉大家如何实现。

正文

1、引入依赖

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

2、更新用户位置信息

编写一个更新用户位置信息的接口,其中几个参数的含义如下:

  • userId:要更新位置信息或查询附近的人的用户ID。
  • longitude:新的经度值或查询附近的人时指定的中心经度。
  • latitude:新的纬度值或查询附近的人时指定的中心纬度。

@Autowired
private RedisTemplate<String, Object> redisTemplate;

// 更新用户位置信息
@PostMapping("/{userId}/location")
public void updateUserLocation(@PathVariable long userId, 
                               @RequestParam double longitude, 
                               @RequestParam double latitude) {

    String userLocationKey = "user_location";
    // 使用Redis的地理位置操作对象,将用户的经纬度信息添加到指定的key中
    redisTemplate.opsForGeo().add(userLocationKey, 
                        new Point(longitude, latitude), userId);
}

3、获取附近的人

编写一个获取附近的人的接口


@Autowired
private RedisTemplate<String, Object> redisTemplate;

// 获取附近的人
@GetMapping("/{userId}/nearby")
public List<Object> getNearbyUsers(@PathVariable long userId, 
                                   @RequestParam double longitude, 
                                   @RequestParam double latitude,
                                   @RequestParam double radius) {

    String userLocationKey = "user_location";
    Distance distance = new Distance(radius, Metrics.KILOMETERS);
    Circle circle = new Circle(new Point(longitude, latitude), distance);

    // 使用Redis的地理位置操作对象,在指定范围内查询附近的用户位置信息
    GeoResults<GeoLocation<Object>> geoResults = redisTemplate
                                    .opsForGeo()
                                    .radius(userLocationKey, circle);

    List<Object> nearbyUsers = new ArrayList<>();
    for (GeoResult<GeoLocation<Object>> geoResult : geoResults.getContent()) {
        Object memberId = geoResult.getContent().getName();
        // 排除查询用户本身
        if (!memberId.equals(userId)) {
            nearbyUsers.add(memberId);
        }
    }
    return nearbyUsers;
}

其中几个重要属性的含义如下:

  • Distance:Spring Data Redis中的一个类,用于表示距离。它可以用于指定搜索半径或者计算两点之间的距离。在示例代码中,我们创建了一个Distance对象来指定搜索范围的半径,并使用Metrics.KILOMETERS表示以千米为单位的距离。

  • Circle:Spring Data Redis中的一个类,用于表示圆形区域。它由一个中心点(用Point表示)和一个半径(用Distance表示)组成。在示例代码中,我们通过传入中心点和距离创建了一个Circle对象,用于定义附近人搜索的圆形区域。

  • GeoResults:Spring Data Redis中的一个类,用于表示地理位置查询的结果。它包含了一个Content属性,该属性是一个List<GeoResult<GeoLocation<Object>>>类型的列表,其中每个GeoResult对象都包含了地理位置信息以及与该位置相关的其他数据。在示例代码中,我们通过调用redisTemplate.opsForGeo().radius()方法返回了一个GeoResults对象,其中包含了在指定范围内的所有地理位置结果。

4、完整代码如下

为了用更少的代码片段让大家一目了然,所以都写在controller中,应用在项目里面时最好把其中的实现部分都转移到service中。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.geo.Circle;
import org.springframework.data.geo.Distance;
import org.springframework.data.geo.GeoResult;
import org.springframework.data.geo.GeoResults;
import org.springframework.data.geo.Metrics;
import org.springframework.data.geo.Point;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;


@RestController
@RequestMapping("/users")
public class UserController {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    // 更新用户位置信息
    @PostMapping("/{userId}/location")
    public void updateUserLocation(@PathVariable long userId, 
                                   @RequestParam double longitude, 
                                   @RequestParam double latitude) {
                                   
        String userLocationKey = "user_location";
        // 使用Redis的地理位置操作对象,将用户的经纬度信息添加到指定的key中
        redisTemplate.opsForGeo().add(userLocationKey, 
                                new Point(longitude, latitude), userId);
    }

    // 获取附近的人
    @GetMapping("/{userId}/nearby")
    public List<Object> getNearbyUsers(@PathVariable long userId, 
                                       @RequestParam double longitude, 
                                       @RequestParam double latitude, 
                                       @RequestParam double radius) {
                                       
        String userLocationKey = "user_location";
        Distance distance = new Distance(radius, Metrics.KILOMETERS);
        Circle circle = new Circle(new Point(longitude, latitude), distance);
        
        // 使用Redis的地理位置操作对象,在指定范围内查询附近的用户位置信息
        GeoResults<GeoLocation<Object>> geoResults = redisTemplate
                                            .opsForGeo()
                                            .radius(userLocationKey, circle);
                                            
        List<Object> nearbyUsers = new ArrayList<>();
        for (GeoResult<GeoLocation<Object>> geoResult : geoResults.getContent()) {
            Object memberId = geoResult.getContent().getName();
            // 排除查询用户本身
            if (!memberId.equals(userId)) {
                nearbyUsers.add(memberId);
            }
        }
        return nearbyUsers;
    }
}

总结

SpringDataRedis本身也是对Redis底层命令的封装,所以Jedis里面其实也提供了差不多的实现,大家可以自己去试一试。

如果有redis相关的面试,如果能说出Redis的Geo命令,面试官就知道你有研究过,是可以大大加分的。

侧面证明了你对Redis的了解不局限于简单的set、get命令,希望这篇文章对大家有所帮助。


如果喜欢,记得点赞关注↓↓↓,持续分享干货!

标签:SpringBoot,RequestParam,Redis,userId,springframework,查找,new,import
From: https://www.cnblogs.com/fulongyuanjushi/p/17692319.html

相关文章

  • WPF 用于查找控件的工具类:找到父控件、子控件
    WPF 封装查找控件的三个方法:usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;usingSystem.Windows;usingSystem.Windows.Media;namespaceK.Controls.Controls.Helper{///<summary>///用于查找控件的工具类:找到父......
  • redis-实战篇-商户查询缓存
    基本思路添加缓存的原则:动态数据不要加缓存缓存cache:数据交换的缓冲区。一般读写性能较高。比如浏览器缓存,浏览器会将一些经常使用的数据缓存到本机,这样在多次加载时就不需要访问服务器,而浏览器未命中的缓存则会去tomcat获取。缓存的作用:降低后端负载、提高读写效率、降低响应......
  • SpringBoot + 自定义注解,实现用户操作日志(支持SpEL表达式)
    背景一个成熟的系统,都会针对一些关键的操作,去创建用户操作日志。比如:XX人创建了一条订单,订单号:XXXXXXXXX因为操作人或者订单号是动态的,所以有些开发人员,不知道获取,就将这种操作日志和业务代码融在一起。我们当然要杜绝这种现象,一定会有更好的解决方案。当前项目除了......
  • SpringBoot创建Thymeleaf
    1.pom.xml导入依赖<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency> 2.thymelef的默认配置文件springboot工程默认有一个templates文件夹,所有的html页面都放这个文件夹里。......
  • Redis的缓存穿透、缓存雪崩、缓存击穿问题及解决方案
    Redis的缓存穿透、缓存雪崩、缓存击穿问题及解决方案缓存穿透问题及解决思路缓存穿透:缓存穿透是指客户端请求的数据在缓存中和数据库中都不存在,这样缓存永远不会生效,这些请求都会打到数据库。因为我们查数据通常是现在redis缓存查数据,如果redis没有这个数据,就会去数据库查。如......
  • Linux下安装Redis的详细安装步骤
    一.Redis安装1.下载linux压缩包【redis-5.0.5.tar.gz】2.通过FlashFXP把压缩包传送到服务器3.解压缩tar-zxvfredis-5.0.5.tar.gz4.进入redis-5.0.5可以看到redis的配置文件redis.conf5.基本的环境安装使用gcc-v命令查看gcc版本已经是4.8.5了,于是就没有再次安装,直接......
  • 查询Redis
            ......
  • python学习笔记-redis缓存数据库
    一、缓存数据库介绍NoSQL(notonlysql)redis是业界主流的Key-valuenosql数据库之一,和memcached类似redis优点:速度快,每秒可执行大约110000设置操作,81000个/每秒的读取操作支持丰富的数据类型,列表,结合,可排序集合,哈希等操作是原子的二、redis操作安装redisubuntu安装$......
  • 多级缓存-Redis缓存预热
            ......
  • SpringBoot 如何实现文件上传和下载
    当今Web应用程序通常需要支持文件上传和下载功能,SpringBoot提供了简单且易于使用的方式来实现这些功能。在本篇文章中,我们将介绍SpringBoot如何实现文件上传和下载,同时提供相应的代码示例。 文件上传SpringBoot提供了Multipart文件上传的支持。Multipart是HTTP协议中的一种......