SpringDataRedis提供了十分簡單的地理位置定位的功能,今天我就用一小段程式碼告訴大家如何實現。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
編寫一個更新使用者位置資訊的介面,其中幾個引數的含義如下:
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);
}
編寫一個獲取附近的人的介面
@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
物件,其中包含了在指定範圍內的所有地理位置結果。
為了用更少的程式碼片段讓大家一目瞭然,所以都寫在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命令,希望這篇文章對大家有所幫助。
如果喜歡,記得點贊關注↓↓↓,持續分享乾貨!