• SpringBoot集成redis的LBS功能


    下面的代码实现了添加经纬度数据 和 搜索经纬度数据的功能:

    import java.util.List;
    
    import com.longge.goods.dto.BuildingDto;
    import com.longge.goods.dto.BuildingLbsDto;
    
    /**
     * LBS相关的服务
     * @author yangzhilong
     *
     */
    public interface LbsService {
        /**
         * 新增或者修改楼宇的经纬度
         * @param buildDto
         */
        void saveBuildingLonAndLat(BuildingDto buildDto);
        
        /**
         * 查询指定经纬度附近的楼宇
         * @param lon 经度
         * @param lat 纬度
         * @param limit 记录数
         * @return
         */
        List<BuildingLbsDto> listNearbyBuilding(double lon, double lat, int limit);
        
    }
      1 import java.util.ArrayList;
      2 import java.util.HashMap;
      3 import java.util.List;
      4 import java.util.Map;
      5 
      6 import javax.annotation.Resource;
      7 
      8 import org.apache.commons.lang3.StringUtils;
      9 import org.springframework.beans.factory.annotation.Autowired;
     10 import org.springframework.beans.factory.annotation.Value;
     11 import org.springframework.data.geo.Circle;
     12 import org.springframework.data.geo.Distance;
     13 import org.springframework.data.geo.GeoResults;
     14 import org.springframework.data.geo.Metrics;
     15 import org.springframework.data.geo.Point;
     16 import org.springframework.data.redis.connection.RedisGeoCommands;
     17 import org.springframework.data.redis.connection.RedisGeoCommands.GeoLocation;
     18 import org.springframework.data.redis.connection.RedisGeoCommands.GeoRadiusCommandArgs;
     19 import org.springframework.data.redis.core.GeoOperations;
     20 import org.springframework.data.redis.core.StringRedisTemplate;
     21 import org.springframework.stereotype.Service;
     22 import org.springframework.util.CollectionUtils;
     23 
     24 import com.alibaba.fastjson.JSONObject;
     25 import com.longge.core.util.BeanMapper;
     26 import com.longge.goods.api.BuildingService;
     27 import com.longge.goods.api.LbsService;
     28 import com.longge.goods.constants.BuildingConstant;
     29 import com.longge.goods.dto.BuildingDto;
     30 import com.longge.goods.dto.BuildingLbsDto;
     31 import com.longge.goods.util.GoodsRedisKeyUtils;
     32 
     33 import lombok.extern.slf4j.Slf4j;
     34 
     35 @Service
     36 @Slf4j
     37 public class LbsServiceImpl implements LbsService {
     38     @Autowired
     39     private BuildingService buildingService;
     40     // 搜索范围
     41     @Value("${lbs.distance:3}")
     42     private Double lbsDistance;
     43     @Resource
     44     private StringRedisTemplate redisTemplate;
     45 
     46     @Override
     47     public void saveBuildingLonAndLat(BuildingDto buildDto) {
     48         log.info("开始处理楼宇的经纬度数据,楼宇:{}", JSONObject.toJSONString(buildDto));
     49         GeoOperations<String, String> ops = redisTemplate.opsForGeo();
     50         String member = String.valueOf(buildDto.getId());
     51         // 查询楼宇的geo数据是否存在
     52         List<String> list = ops.hash(GoodsRedisKeyUtils.getBuildingLbsKey(), member);
     53         if (!CollectionUtils.isEmpty(list)) {
     54             log.info("该楼宇数据存在,先进行删除操作");
     55             // 存在,先删除,后新增
     56             ops.remove(GoodsRedisKeyUtils.getBuildingLbsKey(), member);
     57         }
     58         ops.add(GoodsRedisKeyUtils.getBuildingLbsKey(),
     59                 new RedisGeoCommands.GeoLocation<String>(member, new Point(buildDto.getLon(), buildDto.getLat())));
     60         log.info("楼宇经纬度信息处理完成");
     61     }
     62 
     63     @Override
     64     public List<BuildingLbsDto> listNearbyBuilding(double lon, double lat, int limit) {
     65         log.info("查询LBS楼宇信息,经度:{},纬度:{},条数:{}", lon, lat, limit);
     66         GeoOperations<String, String> ops = redisTemplate.opsForGeo();
     67         
     68         // 获取redis里全局的配置,实现参数动态化
     69         String redisLbsDistance = (String)RedisCache.hGet("config:global", "lbsDistance");
     70         if(StringUtils.isNotBlank(redisLbsDistance)) {
     71             lbsDistance = Double.valueOf(redisLbsDistance);
     72         }
     73         
     74         Point center = new Point(lon, lat);
     75         Distance radius = new Distance(lbsDistance, Metrics.KILOMETERS);
     76         Circle within = new Circle(center, radius);
     77         // order by 距离 limit 20 ,同时返回距离中心点的距离
     78         GeoRadiusCommandArgs args = GeoRadiusCommandArgs.newGeoRadiusArgs().includeDistance().limit(limit).sortAscending();
     79         
     80         GeoResults<GeoLocation<String>> result = ops.radius(GoodsRedisKeyUtils.getBuildingLbsKey(), within, args);
     81         log.info("查询redis后的经纬度数据:{}", JSONObject.toJSONString(result));
     82         if(null != result) {
     83             Map<Long, Double> data = new HashMap<>();
     84             List<Long> buildings = new ArrayList<>();
     85             
     86             result.forEach(item -> {
     87                 data.put(Long.valueOf(item.getContent().getName()), item.getDistance().getValue());
     88                 buildings.add(Long.valueOf(item.getContent().getName()));
     89             });
     90             if(!CollectionUtils.isEmpty(buildings)) {
     91                 List<BuildingDto> buildingList = buildingService.getBuildList(buildings);
     92                 if(!CollectionUtils.isEmpty(buildingList)) {
     93                     List<BuildingLbsDto> resp = new ArrayList<>();
     94                     buildingList.stream().forEach(item -> {
     95                         BuildingLbsDto dto = BeanMapper.map(item, BuildingLbsDto.class);
     96                         if(BuildingConstant.BuildingStatusEnum.OPENED.getValue() == dto.getStatus()) {
     97                             dto.setDistance(data.get(item.getId()));
     98                             resp.add(dto);
     99                         }
    100                     });
    101                     log.info("查询LBS楼宇信息的结果:{}", JSONObject.toJSONString(resp));
    102                     return resp;
    103                 }
    104             }
    105         }
    106         log.warn("未查询LBS楼宇信息");
    107         return null;
    108     }
    109 }
    import java.util.Date;
    
    /**
     * 楼宇信息dto
     *
     */
    @Data
    public class BuildingDto {
        private Long id;
    
        private Short status;
        /**
         * 纬度
         */
        private Double lat;
        /**
         * 经度
         */
        private Double lon;
    }
    import java.io.Serializable;
    
    import lombok.Getter;
    import lombok.Setter;
    
    /**
     * 包含距离定位点距离的楼宇dto
     * @author yangzhilong
     *
     */
    @Getter
    @Setter
    public class BuildingLbsDto extends BuildingDto implements Serializable{
        /**
         * 
         */
        private static final long serialVersionUID = 3224249189169148012L;
        // 距离,单位:千米
        private Double distance;
    }
  • 相关阅读:
    《程序员修炼之道:从小工到专家》阅读笔记02
    第二阶段团队冲刺10
    第二阶段团队冲刺09
    周总结
    第二阶段团队冲刺08
    第二阶段团队冲刺07
    小A和小B和幽灵追两人(双向BFS)
    C. 真假亚瑟王(暴力)
    小A的柱状图(栈的应用,找左右边界)
    小A买彩票
  • 原文地址:https://www.cnblogs.com/yangzhilong/p/9888884.html
Copyright © 2020-2023  润新知