温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Java 中利用 redis 实现 LBS 服务的示例

发布时间:2021-02-04 11:37:55 来源:亿速云 阅读:158 作者:小新 栏目:编程语言

这篇文章给大家分享的是有关 Java 中利用 redis 实现 LBS 服务的示例的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。

前言

LBS(基于位置的服务) 服务是现在移动互联网中比较常用的功能。例如外卖服务中常用的我附近的店铺的功能,通常是以用户当前的位置坐标为基础,查询一定距离范围类的店铺,按照距离远近进行倒序排序。

自从 redis 4 版本发布后, lbs 相关命令正式内置在 redis 的发行版中。要实现上述的功能,主要用到 redis geo 相关的两个命令

GEOADD 和 GEORADIOUS

命令描述

GEOADD

GEOADD key longitude latitude member [longitude latitude member ...]

这个命令将指定的地理空间位置(纬度、经度、名称)添加到指定的 key 中。

有效的经度从-180度到180度。

有效的纬度从-85.05112878度到85.05112878度。

当坐标位置超出上述指定范围时,该命令将会返回一个错误。

该命令可以一次添加多个地理位置点

GEORADIOUS

GEORADIUS key longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count]

这个命令以给定的经纬度为中心, 返回键包含的位置元素当中, 与中心的距离不超过给定最大距离的所有位置元素。
范围可以使用以下其中一个单位:

  • m 表示单位为米。

  • km 表示单位为千米。

  • mi 表示单位为英里。

  • ft 表示单位为英尺。

在给定以下可选项时, 命令会返回额外的信息:

  • WITHDIST: 在返回位置元素的同时, 将位置元素与中心之间的距离也一并返回。 距离的单位和用户给定的范围单位保持一致。

  • WITHCOORD: 将位置元素的经度和维度也一并返回。

  • WITHHASH: 以 52 位有符号整数的形式, 返回位置元素经过原始 geohash 编码的有序集合分值。 这个选项主要用于底层应用或者调试, 实际中的作用并不大。

  • ASC: 根据中心的位置, 按照从近到远的方式返回位置元素。

  • DESC: 根据中心的位置, 按照从远到近的方式返回位置元素。

  • 在默认情况下, GEORADIUS 命令会返回所有匹配的位置元素。 虽然用户可以使用 COUNT <count> 选项去获取前 N 个匹配元素

接口定义

package com.x9710.common.redis;
import com.x9710.common.redis.domain.GeoCoordinate;
import com.x9710.common.redis.domain.Postion;
import java.util.List;
public interface LBSService {
/**
* 存储一个位置
*
* @param postion 增加的位置对象
* @throws Exception
*/
boolean addPostion(Postion postion);
/**
* 查询以指定的坐标为中心,指定的距离为半径的范围类的所有位置点
*
* @param center 中心点位置
* @param distinct 最远距离,单位米
* @param asc 是否倒序排序
* @return 有效的位置
*/
List<Postion> radious(String type, GeoCoordinate center, Long distinct, Boolean asc);
}

实现的接口

package com.x9710.common.redis.impl;
import com.x9710.common.redis.LBSService;
import com.x9710.common.redis.RedisConnection;
import com.x9710.common.redis.domain.GeoCoordinate;
import com.x9710.common.redis.domain.Postion;
import redis.clients.jedis.GeoRadiusResponse;
import redis.clients.jedis.GeoUnit;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.params.geo.GeoRadiusParam;
import java.util.ArrayList;
import java.util.List;
public class LBSServiceRedisImpl implements LBSService {
private RedisConnection redisConnection;
private Integer dbIndex;

public void setRedisConnection(RedisConnection redisConnection) {
this.redisConnection = redisConnection;
}
public void setDbIndex(Integer dbIndex) {
this.dbIndex = dbIndex;
}
public boolean addPostion(Postion postion) {
Jedis jedis = redisConnection.getJedis();
try {
return (1L == jedis.geoadd(postion.getType(),
postion.getCoordinate().getLongitude(),
postion.getCoordinate().getLatitude(),
postion.getId()));
} finally {
if (jedis != null) {
jedis.close();
}
}
}
public List<Postion> radious(String type, GeoCoordinate center, Long distinct, Boolean asc) {
List<Postion> postions = new ArrayList<Postion>();
Jedis jedis = redisConnection.getJedis();
try {
GeoRadiusParam geoRadiusParam = GeoRadiusParam.geoRadiusParam().withCoord().withDist();
if (asc) {
geoRadiusParam.sortAscending();
} else {
geoRadiusParam.sortDescending();
}
List<GeoRadiusResponse> responses = jedis.georadius(type,
center.getLongitude(),
center.getLatitude(),
distinct.doubleValue(),
GeoUnit.M,
geoRadiusParam);
if (responses != null) {
for (GeoRadiusResponse response : responses) {
Postion postion = new Postion(response.getMemberByString(),
type,
response.getCoordinate().getLongitude(),
response.getCoordinate().getLatitude());
postion.setDistinct(response.getDistance());
postions.add(postion);
}
}
} finally {
if (jedis != null) {
jedis.close();
}
}
return postions;
}
}

测试用例

package com.x9710.common.redis.test;
import com.x9710.common.redis.RedisConnection;
import com.x9710.common.redis.domain.GeoCoordinate;
import com.x9710.common.redis.domain.Postion;
import com.x9710.common.redis.impl.CacheServiceRedisImpl;
import com.x9710.common.redis.impl.LBSServiceRedisImpl;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import java.util.List;
/**
* LBS服务测试类
*
* @author 杨高超
* @since 2017-12-28
*/
public class RedisLBSTest {
private CacheServiceRedisImpl cacheService;
private LBSServiceRedisImpl lbsServiceRedis;
private String type = "SHOP";
private GeoCoordinate center;
@Before
public void before() {
RedisConnection redisConnection = RedisConnectionUtil.create();
lbsServiceRedis = new LBSServiceRedisImpl();
lbsServiceRedis.setDbIndex(15);
lbsServiceRedis.setRedisConnection(redisConnection);
Postion postion = new Postion("2017122801", type, 91.118970, 29.654210);
lbsServiceRedis.addPostion(postion);
postion = new Postion("2017122802", type, 116.373472, 39.972528);
lbsServiceRedis.addPostion(postion);
postion = new Postion("2017122803", type, 116.344820, 39.948420);
lbsServiceRedis.addPostion(postion);
postion = new Postion("2017122804", type, 116.637920, 39.905460);
lbsServiceRedis.addPostion(postion);
postion = new Postion("2017122805", type, 118.514590, 37.448150);
lbsServiceRedis.addPostion(postion);
postion = new Postion("2017122806", type, 116.374766, 40.109508);
lbsServiceRedis.addPostion(postion);
center = new GeoCoordinate();
center.setLongitude(116.373472);
center.setLatitude(39.972528);
}
@Test
public void test10KMRadious() {
List<Postion> postions = lbsServiceRedis.radious(type, center, 1000 * 10L, true);
Assert.assertTrue(postions.size() == 2 && exist(postions, "2017122802") && exist(postions, "2017122803"));
}
@Test
public void test50KMRadious() {
List<Postion> postions = lbsServiceRedis.radious(type, center, 1000 * 50L, true);
Assert.assertTrue(postions.size() == 4
&& exist(postions, "2017122802")
&& exist(postions, "2017122803")
&& exist(postions, "2017122806")
&& exist(postions, "2017122804"));
}
private boolean exist(List<Postion> postions, String key) {
if (postions != null) {
for (Postion postion : postions) {
if (postion.getId().equals(key)) {
return true;
}
}
}
return false;
}
@Before
public void after() {
RedisConnection redisConnection = RedisConnectionUtil.create();
cacheService = new CacheServiceRedisImpl();
cacheService.setDbIndex(15);
cacheService.setRedisConnection(redisConnection);
cacheService.delObject(type);
}
}

测试结果

Java 中利用 redis 实现 LBS 服务的示例

LBS 服务测试结果

感谢各位的阅读!关于“ Java 中利用 redis 实现 LBS 服务的示例”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI