在java中接入百度地图

1,登录百度地图开放平台,获取ak

2,在配置文件application.yml里面配置

复制代码
  baidu-map:
    ak: pwBiRaplyK5VkkT******172Od4
    nearby-radius: 100000
    nearby-limit: 0
    default-region: 重庆市永川区

3,编写配置类BaiduMapProperties,接受配置文件的配置

复制代码
package com.smart.common.properties;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Data
@Component
@ConfigurationProperties(prefix = "smart.baidu-map")
public class BaiduMapProperties {
    private String ak;
    private Integer nearbyRadius = 100000;
    private Integer nearbyLimit = 0;
    private String defaultRegion = "重庆市永川区";
}

4,编写写百度地图工具类,BaiduMapUtil.java

复制代码
package com.smart.common.utils;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.smart.common.exception.BaseException;
import com.smart.common.properties.BaiduMapProperties;
import com.smart.pojo.vo.MapPlaceSearchVO;
import com.smart.pojo.vo.MapPointVO;
import com.smart.pojo.vo.MapRouteVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

@Slf4j
@Component
public class BaiduMapUtil {
    //百度地点检索接口
    private static final String PLACE_SEARCH_URL = "https://api.map.baidu.com/place/v2/search";
   //百度坐标转换接口
    private static final String GEO_CONVERT_URL = "https://api.map.baidu.com/geoconv/v1/";
    //百度驾车路线规划接口
    private static final String DRIVING_ROUTE_URL = "https://api.map.baidu.com/directionlite/v1/driving";

    @Autowired
    private BaiduMapProperties baiduMapProperties;
    /**
     * 批量坐标转换
     */

    public List<MapPointVO> convertPoints(List<MapPointVO> points, String fromCoordType, String toCoordType) {
        List<MapPointVO> safePoints = points == null ? new ArrayList<MapPointVO>() : points;
        if (safePoints.isEmpty()) {
            return new ArrayList<>();
        }

        String normalizedFrom = normalizeCoordType(fromCoordType);
        String normalizedTo = normalizeCoordType(toCoordType);
        if (normalizedFrom.equals(normalizedTo)) {
            return copyPoints(safePoints);
        }

        StringBuilder coordsBuilder = new StringBuilder();
        for (MapPointVO point : safePoints) {
            if (point == null || point.getLatitude() == null || point.getLongitude() == null) {
                continue;
            }
            if (coordsBuilder.length() > 0) {
                coordsBuilder.append(";");
            }
            coordsBuilder.append(point.getLongitude()).append(",").append(point.getLatitude());
        }
        if (coordsBuilder.length() == 0) {
            return new ArrayList<>();
        }

        Map<String, String> params = new HashMap<>();
        params.put("coords", coordsBuilder.toString());
        params.put("from", resolveCoordTypeCode(normalizedFrom));
        params.put("to", resolveCoordTypeCode(normalizedTo));
        params.put("ak", getRequiredAk());

        JSONObject response = doGetJson(GEO_CONVERT_URL, params, "坐标转换");
        JSONArray results = response.getJSONArray("result");
        if (results == null || results.isEmpty()) {
            throw new BaseException("坐标转换失败");
        }

        List<MapPointVO> convertedPoints = new ArrayList<>();
        for (int i = 0; i < results.size(); i++) {
            JSONObject item = results.getJSONObject(i);
            if (item == null) {
                continue;
            }
            convertedPoints.add(MapPointVO.builder()
                    .latitude(item.getDouble("y"))
                    .longitude(item.getDouble("x"))
                    .build());
        }
        return convertedPoints;
    }
    /**
     * 单个坐标转换
     */
    public MapPointVO convertPoint(Double latitude, Double longitude, String fromCoordType, String toCoordType) {
        if (latitude == null || longitude == null) {
            throw new BaseException("坐标不能为空");
        }
        List<MapPointVO> convertedPoints = convertPoints(buildSinglePointList(latitude, longitude), fromCoordType, toCoordType);
        if (convertedPoints.isEmpty()) {
            throw new BaseException("坐标转换失败");
        }
        return convertedPoints.get(0);
    }
    /**
     * 地点检索
     */
    public List<MapPlaceSearchVO> searchPlace(String keyword, String region) {
        Map<String, String> params = new HashMap<>();
        params.put("query", keyword);
        params.put("region", region);
        params.put("page_size", "10");
        params.put("scope", "2");
        params.put("output", "json");
        params.put("ak", getRequiredAk());

        JSONObject response = doGetJson(PLACE_SEARCH_URL, params, "地点检索");
        JSONArray results = response.getJSONArray("results");
        List<MapPlaceSearchVO> placeList = new ArrayList<>();
        if (results == null) {
            return placeList;
        }

        for (int i = 0; i < results.size(); i++) {
            JSONObject item = results.getJSONObject(i);
            if (item == null || item.getJSONObject("location") == null) {
                continue;
            }
            JSONObject location = item.getJSONObject("location");
            placeList.add(MapPlaceSearchVO.builder()
                    .name(item.getString("name"))
                    .address(item.getString("address"))
                    .province(item.getString("province"))
                    .city(item.getString("city"))
                    .area(item.getString("area"))
                    .latitude(location.getDouble("lat"))
                    .longitude(location.getDouble("lng"))
                    .build());
        }
        return placeList;
    }
    /*
     * 任意坐标转成百度坐标系 bd09
     */
    public MapPointVO convertToBd09(Double latitude, Double longitude, String coordType) {
        return convertPoint(latitude, longitude, coordType, "bd09");
    }
    /**
     * 路线规划
     */
    public MapRouteVO planDrivingRoute(Double fromLatitude, Double fromLongitude, Double toLatitude, Double toLongitude) {
        Map<String, String> params = new HashMap<>();
        params.put("origin", fromLatitude + "," + fromLongitude);
        params.put("destination", toLatitude + "," + toLongitude);
        params.put("output", "json");
        params.put("ak", getRequiredAk());

        JSONObject response = doGetJson(DRIVING_ROUTE_URL, params, "路线规划");
        JSONObject result = response.getJSONObject("result");
        if (result == null || result.getJSONArray("routes") == null || result.getJSONArray("routes").isEmpty()) {
            throw new BaseException("未查询到可用路线");
        }

        JSONObject route = result.getJSONArray("routes").getJSONObject(0);
        List<MapPointVO> polylinePoints = parsePolylinePoints(route.getJSONArray("steps"));
        if (polylinePoints.isEmpty()) {
            polylinePoints.add(MapPointVO.builder().latitude(fromLatitude).longitude(fromLongitude).build());
            polylinePoints.add(MapPointVO.builder().latitude(toLatitude).longitude(toLongitude).build());
        }

        Integer distanceMeters = route.getInteger("distance");
        Integer durationSeconds = route.getInteger("duration");
        return MapRouteVO.builder()
                .distanceMeters(distanceMeters)
                .durationSeconds(durationSeconds)
                .distanceText(formatDistance(distanceMeters))
                .durationText(formatDuration(durationSeconds))
                .origin(MapPointVO.builder().latitude(fromLatitude).longitude(fromLongitude).build())
                .destination(MapPointVO.builder().latitude(toLatitude).longitude(toLongitude).build())
                .polylinePoints(polylinePoints)
                .build();
    }

    /**
     * 统一异常处理
     */
    private JSONObject doGetJson(String url, Map<String, String> params, String actionName) {
        String responseText = HttpClientUtil.doGet(url, params);
        if (responseText == null || responseText.trim().isEmpty()) {
            throw new BaseException(actionName + "失败,未获取到响应");
        }
        JSONObject response = JSONObject.parseObject(responseText);
        Integer status = response.getInteger("status");
        if (status != null && status != 0) {
            String message = response.getString("message");
            throw new BaseException(actionName + "失败" + (message == null || message.trim().isEmpty() ? "" : ":" + message));
        }
        return response;
    }
    /**
     * 解析路线规划的轨迹点
     *
     * */
    private List<MapPointVO> parsePolylinePoints(JSONArray steps) {
        List<MapPointVO> points = new ArrayList<>();
        if (steps == null || steps.isEmpty()) {
            return points;
        }

        Set<String> uniquePoints = new LinkedHashSet<>();
        for (int i = 0; i < steps.size(); i++) {
            JSONObject step = steps.getJSONObject(i);
            if (step == null) {
                continue;
            }
            String path = step.getString("path");
            if (path == null || path.trim().isEmpty()) {
                continue;
            }
            String[] pathSegments = path.split(";");
            for (String segment : pathSegments) {
                if (segment == null || segment.trim().isEmpty()) {
                    continue;
                }
                uniquePoints.add(segment);
            }
        }

        for (String point : uniquePoints) {
            String[] coordinates = point.split(",");
            if (coordinates.length != 2) {
                continue;
            }
            try {
                points.add(MapPointVO.builder()
                        .latitude(Double.parseDouble(coordinates[1]))
                        .longitude(Double.parseDouble(coordinates[0]))
                        .build());
            } catch (NumberFormatException e) {
                log.warn("解析百度路线点失败: {}", point, e);
            }
        }
        return points;
    }
    /**
     * 格式化距离
     */
    private String formatDistance(Integer distanceMeters) {
        if (distanceMeters == null) {
            return "0m";
        }
        if (distanceMeters >= 1000) {
            return String.format("%.1fkm", distanceMeters / 1000.0D);
        }
        return distanceMeters + "m";
    }
    /**
     * 格式化时长
     */
    private String formatDuration(Integer durationSeconds) {
        if (durationSeconds == null) {
            return "0分钟";
        }
        if (durationSeconds >= 3600) {
            int hours = durationSeconds / 3600;
            int minutes = (durationSeconds % 3600) / 60;
            return minutes > 0 ? hours + "小时" + minutes + "分钟" : hours + "小时";
        }
        if (durationSeconds >= 60) {
            return (durationSeconds / 60) + "分钟";
        }
        return durationSeconds + "秒";
    }
    /**
     * 获取必填的AK
     */
    private String getRequiredAk() {
        String ak = baiduMapProperties.getAk();
        if (ak == null || ak.trim().isEmpty()) {
            throw new BaseException("百度地图AK未配置");
        }
        return ak.trim();
    }
   
    private List<MapPointVO> buildSinglePointList(Double latitude, Double longitude) {
        List<MapPointVO> points = new ArrayList<>();
        points.add(MapPointVO.builder().latitude(latitude).longitude(longitude).build());
        return points;
    }

    private List<MapPointVO> copyPoints(List<MapPointVO> source) {
        List<MapPointVO> copiedPoints = new ArrayList<>();
        for (MapPointVO point : source) {
            if (point == null) {
                continue;
            }
            copiedPoints.add(MapPointVO.builder()
                    .latitude(point.getLatitude())
                    .longitude(point.getLongitude())
                    .build());
        }
        return copiedPoints;
    }

    private String normalizeCoordType(String coordType) {
        if (coordType == null || coordType.trim().isEmpty()) {
            return "bd09";
        }
        String normalized = coordType.trim().toLowerCase();
        if ("bd09ll".equals(normalized)) {
            return "bd09";
        }
        return normalized;
    }

    private String resolveCoordTypeCode(String coordType) {
        if ("wgs84".equals(coordType)) {
            return "1";
        }
        if ("gcj02".equals(coordType)) {
            return "3";
        }
        if ("bd09".equals(coordType)) {
            return "5";
        }
        throw new BaseException("暂不支持的坐标类型: " + coordType);
    }
}

5,编写业务类 MapServiceImpl

复制代码
package com.smart.service.impl;

import com.smart.common.exception.BaseException;
import com.smart.common.properties.BaiduMapProperties;
import com.smart.common.utils.BaiduMapUtil;
import com.smart.mapper.ParkingLotMapper;
import com.smart.pojo.dto.ParkingLotQueryDTO;
import com.smart.pojo.vo.MapPlaceSearchVO;
import com.smart.pojo.vo.MapPointVO;
import com.smart.pojo.vo.MapRouteVO;
import com.smart.pojo.vo.ParkingLotVO;
import com.smart.service.MapService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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

@Service
public class MapServiceImpl implements MapService {

    private static final int DEFAULT_NEARBY_RADIUS_METERS = 100_000;

    @Autowired
    private ParkingLotMapper parkingLotMapper;

    @Autowired
    private BaiduMapUtil baiduMapUtil;

    @Autowired
    private BaiduMapProperties baiduMapProperties;

    @Override
    public List<MapPlaceSearchVO> searchPlaces(String keyword, String region, String coordType) {
        String normalizedKeyword = keyword == null ? null : keyword.trim();
        if (normalizedKeyword == null || normalizedKeyword.isEmpty()) {
            throw new BaseException("地点关键词不能为空");
        }
        String normalizedRegion = region == null || region.trim().isEmpty()
                ? baiduMapProperties.getDefaultRegion()
                : region.trim();
        List<MapPlaceSearchVO> places = baiduMapUtil.searchPlace(normalizedKeyword, normalizedRegion);
        String resultCoordType = normalizeCoordType(coordType);
        if ("bd09".equals(resultCoordType)) {
            return places;
        }
        for (MapPlaceSearchVO place : places) {
            if (place.getLatitude() == null || place.getLongitude() == null) {
                continue;
            }
            MapPointVO convertedPoint = baiduMapUtil.convertPoint(place.getLatitude(), place.getLongitude(), "bd09", resultCoordType);
            place.setLatitude(convertedPoint.getLatitude());
            place.setLongitude(convertedPoint.getLongitude());
        }
        return places;
    }

    @Override
    public List<ParkingLotVO> listNearbyParkingLots(Double latitude, Double longitude, Integer radius, String coordType) {
        if (latitude == null || longitude == null) {
            throw new BaseException("查询附近停车场时坐标不能为空");
        }
        String resultCoordType = normalizeCoordType(coordType);
        MapPointVO centerPoint = baiduMapUtil.convertPoint(latitude, longitude, resultCoordType, "bd09");
        List<ParkingLotVO> allParkingLots = loadPublishedParkingLots();
        int searchRadius = normalizeRadius(radius);

        List<ParkingLotVO> nearbyParkingLots = new ArrayList<>();
        for (ParkingLotVO parkingLot : allParkingLots) {
            if (parkingLot.getLatitude() == null || parkingLot.getLongitude() == null) {
                continue;
            }
            Double distanceKm = calculateDistance(centerPoint.getLatitude(), centerPoint.getLongitude(),
                    parkingLot.getLatitude().doubleValue(), parkingLot.getLongitude().doubleValue());
            if (distanceKm == null || distanceKm * 1000 > searchRadius) {
                continue;
            }
            if (!"bd09".equals(resultCoordType)) {
                MapPointVO convertedPoint = baiduMapUtil.convertPoint(parkingLot.getLatitude().doubleValue(),
                        parkingLot.getLongitude().doubleValue(), "bd09", resultCoordType);
                parkingLot.setLatitude(convertedPoint.getLatitude() == null ? null : java.math.BigDecimal.valueOf(convertedPoint.getLatitude()));
                parkingLot.setLongitude(convertedPoint.getLongitude() == null ? null : java.math.BigDecimal.valueOf(convertedPoint.getLongitude()));
            }
            parkingLot.setDistanceKm(distanceKm);
            parkingLot.setRecommended(0);
            nearbyParkingLots.add(parkingLot);
        }

        nearbyParkingLots.sort(Comparator
                .comparing((ParkingLotVO item) -> item.getDistanceKm() == null ? Double.MAX_VALUE : item.getDistanceKm())
                .thenComparing(item -> item.getFreeSpaceCount() == null ? 0 : -item.getFreeSpaceCount())
                .thenComparing(ParkingLotVO::getId));

        int limit = baiduMapProperties.getNearbyLimit() == null || baiduMapProperties.getNearbyLimit() <= 0
                ? nearbyParkingLots.size()
                : Math.min(nearbyParkingLots.size(), baiduMapProperties.getNearbyLimit());
        List<ParkingLotVO> result = new ArrayList<>(nearbyParkingLots.subList(0, limit));
        if (!result.isEmpty()) {
            result.get(0).setRecommended(1);
        }
        return result;
    }

    @Override
    public MapRouteVO planRoute(Double fromLatitude, Double fromLongitude, Double toLatitude, Double toLongitude,
                                String fromCoordType, String toCoordType) {
        if (fromLatitude == null || fromLongitude == null || toLatitude == null || toLongitude == null) {
            throw new BaseException("路线规划坐标不能为空");
        }
        String resultCoordType = normalizeCoordType(fromCoordType);
        MapPointVO originPoint = baiduMapUtil.convertPoint(fromLatitude, fromLongitude, resultCoordType, "bd09");
        MapPointVO destinationPoint = baiduMapUtil.convertPoint(toLatitude, toLongitude,
                normalizeCoordType(toCoordType), "bd09");
        MapRouteVO route = baiduMapUtil.planDrivingRoute(originPoint.getLatitude(), originPoint.getLongitude(),
                destinationPoint.getLatitude(), destinationPoint.getLongitude());
        if (!"bd09".equals(resultCoordType)) {
            route.setOrigin(baiduMapUtil.convertPoint(route.getOrigin().getLatitude(), route.getOrigin().getLongitude(), "bd09", resultCoordType));
            route.setDestination(baiduMapUtil.convertPoint(route.getDestination().getLatitude(), route.getDestination().getLongitude(), "bd09", resultCoordType));
            route.setPolylinePoints(baiduMapUtil.convertPoints(route.getPolylinePoints(), "bd09", resultCoordType));
        }
        return route;
    }

    private List<ParkingLotVO> loadPublishedParkingLots() {
        ParkingLotQueryDTO queryDTO = new ParkingLotQueryDTO();
        queryDTO.setPublishStatus(1);
        return parkingLotMapper.listForUser(queryDTO);
    }

    private int normalizeRadius(Integer radius) {
        if (radius == null || radius <= 0) {
            return baiduMapProperties.getNearbyRadius() == null ? DEFAULT_NEARBY_RADIUS_METERS : baiduMapProperties.getNearbyRadius();
        }
        return radius;
    }

    private String normalizeCoordType(String coordType) {
        if (coordType == null || coordType.trim().isEmpty()) {
            return "bd09";
        }
        String normalized = coordType.trim().toLowerCase();
        return "bd09ll".equals(normalized) ? "bd09" : normalized;
    }

    private Double calculateDistance(Double fromLatitude, Double fromLongitude, Double toLatitude, Double toLongitude) {
        if (fromLatitude == null || fromLongitude == null || toLatitude == null || toLongitude == null) {
            return null;
        }
        double earthRadiusKm = 6371.0D;
        double latitudeDiff = Math.toRadians(toLatitude - fromLatitude);
        double longitudeDiff = Math.toRadians(toLongitude - fromLongitude);
        double a = Math.sin(latitudeDiff / 2) * Math.sin(latitudeDiff / 2)
                + Math.cos(Math.toRadians(fromLatitude)) * Math.cos(Math.toRadians(toLatitude))
                * Math.sin(longitudeDiff / 2) * Math.sin(longitudeDiff / 2);
        double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
        return Math.round(earthRadiusKm * c * 100.0D) / 100.0D;
    }
}

6,暴露MapController 接口给前端

复制代码
package com.smart.controller.user;

import com.smart.common.result.Result;
import com.smart.pojo.vo.MapPlaceSearchVO;
import com.smart.pojo.vo.MapRouteVO;
import com.smart.pojo.vo.ParkingLotVO;
import com.smart.service.MapService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
@RequestMapping("/user/map")
@Api(tags = "用户端-地图相关接口")
public class MapController {

    @Autowired
    private MapService mapService;

    @GetMapping("/place-search")
    @ApiOperation("地点检索")
    public Result<List<MapPlaceSearchVO>> searchPlace(String keyword, String region, String coordType) {
        return Result.success(mapService.searchPlaces(keyword, region, coordType));
    }

    @GetMapping("/nearby")
    @ApiOperation("查询附近停车场")
    public Result<List<ParkingLotVO>> nearby(Double latitude, Double longitude, Integer radius, String coordType) {
        return Result.success(mapService.listNearbyParkingLots(latitude, longitude, radius, coordType));
    }

    @GetMapping("/route")
    @ApiOperation("路线规划")
    public Result<MapRouteVO> route(Double fromLatitude, Double fromLongitude, Double toLatitude, Double toLongitude,
                                    String fromCoordType, String toCoordType) {
        return Result.success(mapService.planRoute(fromLatitude, fromLongitude, toLatitude, toLongitude,
                fromCoordType, toCoordType));
    }
}
相关推荐
敲个大西瓜1 小时前
加密算法小解
java
小短腿的代码世界1 小时前
Qt对象树析构链与智能指针协同:零泄漏内存管理架构
开发语言·qt·架构
阿维的博客日记1 小时前
怎么样才算是用到了反射呢?有什么关键特征吗
java
zhaqonianzhu1 小时前
LOL切回桌面问题,采用监控抓出元凶方式
开发语言
Aurorar0rua1 小时前
CS50 x 2024 Notes Arrays - 04
c语言·开发语言·学习方法
wuminyu2 小时前
Java世界中StringTable源码剖析
java·linux·c语言·jvm·c++
一个做软件开发的牛马2 小时前
Spring Boot 自动配置原理揭秘:从 @SpringBootApplication 到手写自定义 Starter
java·后端
一起吃元宵2 小时前
百度网盘下载不限速的办法_百度网盘不限速
开发语言·百度网盘·下载不限速·不限速·百度网盘不限速
人道领域2 小时前
【LeetCode刷题日记】47.全排列Ⅱ
java·开发语言·算法·leetcode