成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

SpringBoot與GeoHash整合,實(shí)現(xiàn)騎手的實(shí)時(shí)就近派單功能

開發(fā) 前端
通過使用GeoHash結(jié)合Redis的地理空間功能,能夠?qū)崟r(shí)管理和查詢騎手的位置信息,并根據(jù)訂單量和評分等因素動(dòng)態(tài)分配最近的騎手來完成配送任務(wù)。

通過使用GeoHash結(jié)合Redis的地理空間功能,能夠?qū)崟r(shí)管理和查詢騎手的位置信息,并根據(jù)訂單量和評分等因素動(dòng)態(tài)分配最近的騎手來完成配送任務(wù)。

我們?yōu)槭裁词褂肎eoHash?

  • 空間索引: GeoHash是一種將地理坐標(biāo)(經(jīng)緯度)編碼為字符串的算法,可以用于空間索引。 這使得我們可以方便地在Redis這樣的內(nèi)存數(shù)據(jù)庫中存儲和檢索地理位置數(shù)據(jù)。
  • 快速篩選附近騎手: 通過GeoHash前綴匹配策略,可以在較短的時(shí)間內(nèi)篩選出一定范圍內(nèi)的騎手。 Redis提供了豐富的地理空間命令(如 GEOADD, GEORADIUS),可以直接利用這些命令來實(shí)現(xiàn)高效的地理空間查詢。
  • 減少計(jì)算開銷: 相比于傳統(tǒng)的距離計(jì)算方法(如Haversine公式),GeoHash可以通過字符串比較來快速確定位置關(guān)系。 這減少了復(fù)雜的數(shù)學(xué)運(yùn)算,提高了查詢性能。
  • 支持多級精度: GeoHash支持多種精度級別,可以根據(jù)需求調(diào)整搜索范圍。 例如,較長的GeoHash字符串表示更精確的位置,而較短的字符串則覆蓋更大的區(qū)域。這為我們提供了靈活性,可以根據(jù)不同的應(yīng)用場景調(diào)整查詢精度。

實(shí)現(xiàn)這個(gè)功能的關(guān)鍵點(diǎn)有哪些?

  • 高效的位置存儲和查詢
  • 動(dòng)態(tài)權(quán)重調(diào)整: 根據(jù)騎手當(dāng)前訂單量、歷史好評率計(jì)算派單優(yōu)先級
  • 實(shí)時(shí)更新騎手位置,實(shí)時(shí)位置數(shù)據(jù)對于準(zhǔn)確派單至關(guān)重要。

代碼實(shí)操

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.5</version>
        <relativePath/><!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>delivery-system</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>delivery-system</name>
    <description>Demo project for Spring Boot and GeoHash integration</description>
    <properties>
        <java.version>11</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

application.properties

server.port=8080
spring.redis.host=localhost
spring.redis.port=6379

Redis Config

package com.example.deliverysystem.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@Configuration
publicclass RedisConfig {

    @Bean
    public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, String> template = new RedisTemplate<>();
        template.setConnectionFactory(factory);
        template.setKeySerializer(new StringRedisSerializer());
        template.setValueSerializer(new StringRedisSerializer());
        return template;
    }
}

騎手

package com.example.deliverysystem.model;

import lombok.Data;

@Data
publicclass Rider {
    private String id;          // 騎手ID
    privatedouble latitude;    // 緯度
    privatedouble longitude;   // 經(jīng)度
    privateint orderCount;     // 當(dāng)前訂單數(shù)量
    privatedouble rating;      // 歷史平均評分(0-5)
}

Repository

package com.example.deliverysystem.repository;

import com.example.deliverysystem.model.Rider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.geo.Circle;
import org.springframework.data.geo.Distance;
import org.springframework.data.geo.Metrics;
import org.springframework.data.geo.Point;
import org.springframework.data.redis.connection.RedisGeoCommands;
import org.springframework.data.redis.core.GeoOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Repository;

import java.util.List;
import java.util.Map;

@Repository
publicclass RiderRepository {

    privatefinal GeoOperations<String, String> geoOps;

    @Autowired
    public RiderRepository(RedisTemplate<String, String> redisTemplate) {
        this.geoOps = redisTemplate.opsForGeo();
    }

    /**
     * 添加騎手到Redis中的地理位置集合
     *
     * @param key   Redis鍵名
     * @param rider 騎手對象
     */
    public void addRider(String key, Rider rider) {
        Point point = new Point(rider.getLongitude(), rider.getLatitude());
        geoOps.add(key, point, rider.getId());
    }

    /**
     * 查找指定半徑范圍內(nèi)的騎手
     *
     * @param key            Redis鍵名
     * @param referencePoint 參考點(diǎn)(經(jīng)緯度)
     * @param distance       半徑距離
     * @return 附近的騎手列表
     */
    public List<RedisGeoCommands.GeoResult<RedisGeoCommands.GeoLocation<String>>> findNearbyRiders(String key, Point referencePoint, Distance distance) {
        Circle circle = new Circle(referencePoint, distance);
        return geoOps.radius(key, circle);
    }

    /**
     * 獲取騎手詳情
     *
     * @param results 附近騎手的結(jié)果列表
     * @return 騎手詳情映射表
     */
    public Map<Object, Object> getRiderDetails(List<RedisGeoCommands.GeoResult<RedisGeoCommands.GeoLocation<String>>> results) {
        // 這里可以進(jìn)一步獲取每個(gè)騎手的詳細(xì)信息,例如從數(shù)據(jù)庫中讀取。
        // 為了簡化示例,我們僅返回騎手ID列表。
        return results.stream()
                     .collect(java.util.stream.Collectors.toMap(
                         result -> result.getContent().getName(),
                         result -> null));
    }
}

Service

package com.example.deliverysystem.service;

import com.example.deliverysystem.model.Rider;
import com.example.deliverysystem.repository.RiderRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.geo.*;
import org.springframework.stereotype.Service;

import java.util.Comparator;
import java.util.List;
import java.util.Map;

@Service
publicclass DeliveryService {

    privatefinal RiderRepository riderRepository;

    @Autowired
    public DeliveryService(RiderRepository riderRepository) {
        this.riderRepository = riderRepository;
    }

    /**
     * 添加騎手到系統(tǒng)
     *
     * @param key   Redis鍵名
     * @param rider 騎手對象
     */
    public void addRider(String key, Rider rider) {
        riderRepository.addRider(key, rider);
    }

    /**
     * 查找最近的騎手
     *
     * @param key                  Redis鍵名
     * @param latitude             目標(biāo)緯度
     * @param longitude            目標(biāo)經(jīng)度
     * @param radiusInKilometers   查詢半徑(公里)
     * @return 最近的騎手列表,按優(yōu)先級排序
     */
    public List<Rider> findNearestRiders(String key, double latitude, double longitude, double radiusInKilometers) {
        Point referencePoint = new Point(longitude, latitude);
        Distance radius = new Distance(radiusInKilometers, Metrics.KILOMETERS);

        List<RedisGeoCommands.GeoResult<RedisGeoCommands.GeoLocation<String>>> nearbyRiders =
                riderRepository.findNearbyRiders(key, referencePoint, radius);

        Map<Object, Object> riderDetails = riderRepository.getRiderDetails(nearbyRiders);

        // 假設(shè)這里可以根據(jù)騎手ID獲取其他屬性。
        // 實(shí)際場景中,這些信息可能來自數(shù)據(jù)庫或其他數(shù)據(jù)源。
        return nearbyRiders.stream()
                           .map(result -> {
                               Rider rider = new Rider();
                               rider.setId(result.getContent().getName());
                               // 根據(jù)實(shí)際需求獲取其他屬性。
                               return rider;
                           })
                           .sorted(Comparator.comparingDouble(this::calculatePriority))
                           .toList();
    }

    /**
     * 計(jì)算騎手的派單優(yōu)先級
     * 
     * @param rider 騎手對象
     * @return 優(yōu)先級值(數(shù)值越大優(yōu)先級越高)
     */
    private double calculatePriority(Rider rider) {
        // 簡單的優(yōu)先級計(jì)算方法:較低的訂單量和較高的評分意味著更高的優(yōu)先級。
        // 具體公式可以根據(jù)實(shí)際業(yè)務(wù)需求調(diào)整。
        return -(rider.getOrderCount() * 1.0 / 5 + rider.getRating());
    }
}

Controller

package com.example.deliverysystem.controller;

import com.example.deliverysystem.model.Rider;
import com.example.deliverysystem.service.DeliveryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/api/delivery")
publicclass DeliveryController {

    privatefinal DeliveryService deliveryService;

    @Autowired
    public DeliveryController(DeliveryService deliveryService) {
        this.deliveryService = deliveryService;
    }

    /**
     * 添加新的騎手
     *
     * @param rider 新的騎手對象
     */
    @PostMapping("/riders")
    public void addRider(@RequestBody Rider rider) {
        deliveryService.addRider("riders", rider);
    }

    /**
     * 查找最近的騎手
     *
     * @param latitude 目標(biāo)緯度
     * @param longitude 目標(biāo)經(jīng)度
     * @param radiusInKilometers 查詢半徑(公里,默認(rèn)5公里)
     * @return 最近的騎手列表
     */
    @GetMapping("/nearest-rider/{latitude}/{longitude}")
    public List<Rider> findNearestRiders(@PathVariable double latitude,
                                         @PathVariable double longitude,
                                         @RequestParam(defaultValue = "5") double radiusInKilometers) {
        return deliveryService.findNearestRiders("riders", latitude, longitude, radiusInKilometers);
    }
}

Application

package com.example.deliverysystem;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DeliverySystemApplication {

    public static void main(String[] args) {
        SpringApplication.run(DeliverySystemApplication.class, args);
    }
}

測試

添加第一個(gè)騎手

curl -X POST http://localhost:8080/api/delivery/riders \
-H "Content-Type: application/json" \
-d '{"id": "rider1", "latitude": 39.9042, "longitude": 116.4074, "orderCount": 2, "rating": 4.5}'

Respons

空響應(yīng)(HTTP狀態(tài)碼200)

添加第二個(gè)騎手

curl -X POST http://localhost:8080/api/delivery/riders \
-H "Content-Type: application/json" \
-d '{"id": "rider2", "latitude": 39.9087, "longitude": 116.3975, "orderCount": 1, "rating": 4.8}'

Respons

空響應(yīng)(HTTP狀態(tài)碼200)

查詢最近的騎手

  • 查詢位置為 (39.9063, 116.4039) 附近5公里范圍內(nèi)的騎手
curl -X GET "http://localhost:8080/api/delivery/nearest-rider/39.9063/116.4039"

Respons

[
    {
        "id": "rider1",
        "latitude": 39.9042,
        "longitude": 116.4074,
        "orderCount": 2,
        "rating": 4.5
    },
    {
        "id": "rider2",
        "latitude": 39.9087,
        "longitude": 116.3975,
        "orderCount": 1,
        "rating": 4.8
    }
]


責(zé)任編輯:武曉燕 來源: Java知識日歷
相關(guān)推薦

2025-04-29 08:36:28

SpringCanal數(shù)據(jù)庫

2025-03-11 09:28:34

2025-02-14 09:07:35

2025-06-19 02:11:00

2025-04-01 08:38:41

2025-03-19 08:36:55

2025-03-26 08:43:17

2025-03-17 08:39:08

SpringApache數(shù)據(jù)

2025-04-23 08:50:00

SpringBootCurator分布式鎖

2025-03-04 08:40:28

2025-06-16 04:00:00

Spring彈幕技術(shù)

2025-02-28 08:40:28

ZooKeeperSpringBoot計(jì)費(fèi)系統(tǒng)

2025-04-08 08:50:37

SpringCamel系統(tǒng)

2025-06-17 08:39:43

2025-05-09 08:34:57

RSocketSpringBoot聊天系統(tǒng)

2025-03-31 08:43:34

SpringTika優(yōu)化

2025-03-03 07:30:00

SpringBootJGraphT網(wǎng)絡(luò)建模

2025-05-06 08:40:21

SpringPostGIS系統(tǒng)

2023-03-30 08:11:52

Spring加解密連接池

2021-08-17 06:48:43

SpringbootKafkaStream
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 国产成人91视频 | 国产精品一区二区在线播放 | 欧美激情视频一区二区三区在线播放 | 精久久久 | 91亚洲精品久久久电影 | 久久久国产一区 | 中国一级大毛片 | 99精品观看 | 免费在线视频一区二区 | 超碰在线免费公开 | 99久久婷婷国产综合精品 | 亚洲视频在线看 | 伊人影院99| 久久久久久国产精品免费 | 午夜免费电影院 | 国产精品欧美一区二区三区不卡 | 有码在线 | 日韩欧美理论片 | 日本在线看片 | 天天干视频网 | 久久99精品国产99久久6男男 | 国产免费a视频 | 欧美一区二区三区国产精品 | 国产欧美精品在线观看 | 久久99这里只有精品 | 中文字幕一页二页 | 国内激情av片 | 国产精品久久久久久影院8一贰佰 | 国产精品视频一二三区 | 欧美久久久久 | 性欧美hd | 在线视频国产一区 | 欧美日韩国产三级 | 日韩乱码一二三 | 免费特级黄毛片 | 国产日韩欧美在线一区 | 操久久| 久久精品二区亚洲w码 | 国产成人免费视频网站视频社区 | 99久久久国产精品 | 国产91丝袜在线18 |