当前位置: 代码网 > it编程>编程语言>Java > SpringBoot集成高德地图SDK的详细步骤

SpringBoot集成高德地图SDK的详细步骤

2026年01月26日 Java 我要评论
一、高德地图简介1.1 高德地图概述高德地图是中国领先的数字地图内容、导航和位置服务解决方案提供商,由阿里巴巴集团控股。它提供了全面的地图服务,包括:基础地图服务:街道、建筑物、地形等地图数据定位服务

一、高德地图简介

1.1 高德地图概述

高德地图是中国领先的数字地图内容、导航和位置服务解决方案提供商,由阿里巴巴集团控股。它提供了全面的地图服务,包括:

  • 基础地图服务:街道、建筑物、地形等地图数据
  • 定位服务:gps、基站、wi-fi多重定位
  • 地理编码:地址与坐标之间的相互转换
  • 路径规划:驾车、步行、骑行、公交路线规划
  • 地图展示:2d/3d地图展示、自定义地图样式
  • 地点搜索:poi(兴趣点)搜索、周边搜索
  • 轨迹服务:车辆轨迹管理和分析

1.2 高德地图服务优势

  • 高精度定位:米级到厘米级精确定位
  • 丰富api:提供web端、android、ios、服务端全方位sdk
  • 实时路况:覆盖全国主要城市的实时交通信息
  • 数据更新快:地图数据每周更新

1.3 高德地图应用场景

  • 位置服务(lbs)应用
  • 物流配送和路径优化
  • 出行服务和导航应用
  • 地理信息系统(gis)
  • 商业分析和选址决策

二、springboot集成高德地图sdk详细步骤

2.1 环境准备

2.1.1 注册高德开发者账号

  1. 访问高德开放平台
  2. 注册账号并完成实名认证
  3. 创建应用,获取api key

2.1.2 创建springboot项目

# 使用spring initializr创建项目
mvn archetype:generate -dgroupid=com.example -dartifactid=amap-demo -darchetypeartifactid=maven-archetype-quickstart -dinteractivemode=false

# 或使用spring boot cli
spring init --dependencies=web,configuration-processor amap-demo

2.2 项目依赖配置

pom.xml配置

<?xml version="1.0" encoding="utf-8"?>
<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 
         http://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.0</version>
        <relativepath/>
    </parent>

    <groupid>com.example</groupid>
    <artifactid>amap-demo</artifactid>
    <version>1.0.0</version>

    <properties>
        <java.version>11</java.version>
    </properties>

    <dependencies>
        <!-- spring boot web -->
        <dependency>
            <groupid>org.springframework.boot</groupid>
            <artifactid>spring-boot-starter-web</artifactid>
        </dependency>
        
        <!-- spring boot configuration processor -->
        <dependency>
            <groupid>org.springframework.boot</groupid>
            <artifactid>spring-boot-configuration-processor</artifactid>
            <optional>true</optional>
        </dependency>
        
        <!-- lombok -->
        <dependency>
            <groupid>org.projectlombok</groupid>
            <artifactid>lombok</artifactid>
            <optional>true</optional>
        </dependency>
        
        <!-- http client -->
        <dependency>
            <groupid>org.apache.httpcomponents</groupid>
            <artifactid>httpclient</artifactid>
            <version>4.5.13</version>
        </dependency>
        
        <!-- json processing -->
        <dependency>
            <groupid>com.fasterxml.jackson.core</groupid>
            <artifactid>jackson-databind</artifactid>
        </dependency>
        
        <!-- test dependencies -->
        <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>

2.3 配置文件

application.yml

server:
  port: 8080
  servlet:
    context-path: /api

spring:
  application:
    name: amap-service

# 高德地图配置
amap:
  # 在高德开放平台申请的key
  api-key: your-amap-api-key-here
  # api基础url
  base-url: https://restapi.amap.com/v3
  # 地理编码服务路径
  geocode-path: /geocode/geo
  # 逆地理编码服务路径
  regeocode-path: /geocode/regeo
  # 路径规划服务路径
  direction-path: /direction/driving
  # ip定位服务路径
  ip-locate-path: /ip
  # 天气查询服务路径
  weather-path: /weather/weatherinfo
  # 签名密钥(可选)
  sig-key: 
  # 返回数据格式
  output: json

2.4 核心代码实现

2.4.1 配置类

package com.example.amap.config;

import lombok.data;
import org.springframework.boot.context.properties.configurationproperties;
import org.springframework.context.annotation.configuration;

@data
@configuration
@configurationproperties(prefix = "amap")
public class amapproperties {
    private string apikey;
    private string baseurl;
    private string geocodepath;
    private string regeocodepath;
    private string directionpath;
    private string iplocatepath;
    private string weatherpath;
    private string sigkey;
    private string output = "json";
    
    public string getgeocodeurl() {
        return baseurl + geocodepath;
    }
    
    public string getregeocodeurl() {
        return baseurl + regeocodepath;
    }
    
    public string getdirectionurl() {
        return baseurl + directionpath;
    }
    
    public string getiplocateurl() {
        return baseurl + iplocatepath;
    }
    
    public string getweatherurl() {
        return baseurl + weatherpath;
    }
}

2.4.2 http客户端配置

package com.example.amap.config;

import org.apache.http.client.config.requestconfig;
import org.apache.http.impl.client.closeablehttpclient;
import org.apache.http.impl.client.httpclientbuilder;
import org.apache.http.impl.conn.poolinghttpclientconnectionmanager;
import org.springframework.context.annotation.bean;
import org.springframework.context.annotation.configuration;
import org.springframework.http.client.clienthttprequestfactory;
import org.springframework.http.client.httpcomponentsclienthttprequestfactory;
import org.springframework.web.client.resttemplate;

@configuration
public class httpclientconfig {
    
    @bean
    public resttemplate resttemplate() {
        return new resttemplate(httprequestfactory());
    }
    
    @bean
    public clienthttprequestfactory httprequestfactory() {
        return new httpcomponentsclienthttprequestfactory(httpclient());
    }
    
    @bean
    public closeablehttpclient httpclient() {
        poolinghttpclientconnectionmanager connectionmanager = 
            new poolinghttpclientconnectionmanager();
        connectionmanager.setmaxtotal(200);
        connectionmanager.setdefaultmaxperroute(50);
        
        requestconfig requestconfig = requestconfig.custom()
            .setsockettimeout(10000)
            .setconnecttimeout(5000)
            .setconnectionrequesttimeout(5000)
            .build();
        
        return httpclientbuilder.create()
            .setconnectionmanager(connectionmanager)
            .setdefaultrequestconfig(requestconfig)
            .build();
    }
}

2.4.3 服务层实现

package com.example.amap.service;

import com.example.amap.config.amapproperties;
import com.example.amap.model.*;
import com.fasterxml.jackson.databind.jsonnode;
import com.fasterxml.jackson.databind.objectmapper;
import lombok.requiredargsconstructor;
import lombok.extern.slf4j.slf4j;
import org.springframework.http.responseentity;
import org.springframework.stereotype.service;
import org.springframework.web.client.resttemplate;
import org.springframework.web.util.uricomponentsbuilder;

import java.net.uri;
import java.util.hashmap;
import java.util.map;

@slf4j
@service
@requiredargsconstructor
public class amapservice {
    
    private final resttemplate resttemplate;
    private final amapproperties amapproperties;
    private final objectmapper objectmapper;
    
    /**
     * 地理编码:地址转坐标
     */
    public georesult geocode(string address, string city) {
        map<string, string> params = new hashmap<>();
        params.put("key", amapproperties.getapikey());
        params.put("address", address);
        if (city != null && !city.isempty()) {
            params.put("city", city);
        }
        
        string url = buildurl(amapproperties.getgeocodeurl(), params);
        log.info("请求地理编码api: {}", url);
        
        responseentity<string> response = resttemplate.getforentity(url, string.class);
        return parsegeoresult(response.getbody());
    }
    
    /**
     * 逆地理编码:坐标转地址
     */
    public regeoresult regeocode(string location) {
        map<string, string> params = new hashmap<>();
        params.put("key", amapproperties.getapikey());
        params.put("location", location);
        params.put("extensions", "all"); // 返回详细信息
        
        string url = buildurl(amapproperties.getregeocodeurl(), params);
        log.info("请求逆地理编码api: {}", url);
        
        responseentity<string> response = resttemplate.getforentity(url, string.class);
        return parseregeoresult(response.getbody());
    }
    
    /**
     * 路径规划
     */
    public directionresult direction(string origin, string destination, string strategy) {
        map<string, string> params = new hashmap<>();
        params.put("key", amapproperties.getapikey());
        params.put("origin", origin);
        params.put("destination", destination);
        params.put("strategy", strategy != null ? strategy : "0"); // 0:速度优先
        
        string url = buildurl(amapproperties.getdirectionurl(), params);
        log.info("请求路径规划api: {}", url);
        
        responseentity<string> response = resttemplate.getforentity(url, string.class);
        return parsedirectionresult(response.getbody());
    }
    
    /**
     * ip定位
     */
    public iplocateresult iplocate(string ip) {
        map<string, string> params = new hashmap<>();
        params.put("key", amapproperties.getapikey());
        params.put("ip", ip != null ? ip : "");
        
        string url = buildurl(amapproperties.getiplocateurl(), params);
        log.info("请求ip定位api: {}", url);
        
        responseentity<string> response = resttemplate.getforentity(url, string.class);
        return parseiplocateresult(response.getbody());
    }
    
    /**
     * 天气查询
     */
    public weatherresult weather(string city, string extensions) {
        map<string, string> params = new hashmap<>();
        params.put("key", amapproperties.getapikey());
        params.put("city", city);
        params.put("extensions", extensions != null ? extensions : "base"); // base:实时天气
        
        string url = buildurl(amapproperties.getweatherurl(), params);
        log.info("请求天气查询api: {}", url);
        
        responseentity<string> response = resttemplate.getforentity(url, string.class);
        return parseweatherresult(response.getbody());
    }
    
    /**
     * 构建请求url
     */
    private string buildurl(string baseurl, map<string, string> params) {
        uricomponentsbuilder builder = uricomponentsbuilder.fromhttpurl(baseurl);
        params.foreach(builder::queryparam);
        return builder.build().touristring();
    }
    
    /**
     * 解析地理编码结果
     */
    private georesult parsegeoresult(string json) {
        try {
            jsonnode root = objectmapper.readtree(json);
            georesult result = new georesult();
            result.setstatus(root.get("status").astext());
            result.setinfo(root.get("info").astext());
            
            if ("1".equals(result.getstatus())) {
                jsonnode geocodes = root.get("geocodes");
                if (geocodes != null && geocodes.isarray() && geocodes.size() > 0) {
                    jsonnode first = geocodes.get(0);
                    geocode geocode = new geocode();
                    geocode.setformattedaddress(first.get("formatted_address").astext());
                    geocode.setcountry(first.get("country").astext());
                    geocode.setprovince(first.get("province").astext());
                    geocode.setcity(first.get("city").astext());
                    geocode.setdistrict(first.get("district").astext());
                    string location = first.get("location").astext();
                    if (location.contains(",")) {
                        string[] coords = location.split(",");
                        geocode.setlongitude(double.parsedouble(coords[0]));
                        geocode.setlatitude(double.parsedouble(coords[1]));
                    }
                    result.setgeocode(geocode);
                }
            }
            return result;
        } catch (exception e) {
            log.error("解析地理编码结果失败", e);
            return null;
        }
    }
    
    /**
     * 解析逆地理编码结果
     */
    private regeoresult parseregeoresult(string json) {
        try {
            jsonnode root = objectmapper.readtree(json);
            regeoresult result = new regeoresult();
            result.setstatus(root.get("status").astext());
            result.setinfo(root.get("info").astext());
            
            if ("1".equals(result.getstatus())) {
                jsonnode regeocode = root.get("regeocode");
                if (regeocode != null) {
                    regeocode regeocode = new regeocode();
                    regeocode.setformattedaddress(regeocode.get("formatted_address").astext());
                    result.setregeocode(regeocode);
                }
            }
            return result;
        } catch (exception e) {
            log.error("解析逆地理编码结果失败", e);
            return null;
        }
    }
    
    // 其他解析方法类似,限于篇幅省略...
}

2.4.4 数据模型

package com.example.amap.model;

import lombok.data;
import java.util.list;

@data
public class georesult {
    private string status;
    private string info;
    private geocode geocode;
}

@data
class geocode {
    private string formattedaddress;
    private string country;
    private string province;
    private string city;
    private string district;
    private double longitude;
    private double latitude;
}

@data
public class regeoresult {
    private string status;
    private string info;
    private regeocode regeocode;
}

@data
class regeocode {
    private string formattedaddress;
    private addresscomponent addresscomponent;
}

@data
class addresscomponent {
    private string province;
    private string city;
    private string district;
    private string township;
}

@data
public class directionresult {
    private string status;
    private string info;
    private route route;
}

@data
class route {
    private list<path> paths;
}

@data
class path {
    private double distance;
    private double duration;
    private string strategy;
    private string tolls;
    private string restriction;
    private string trafficlights;
}

@data
public class iplocateresult {
    private string status;
    private string info;
    private string province;
    private string city;
    private string adcode;
    private string rectangle;
}

@data
public class weatherresult {
    private string status;
    private string info;
    private string count;
    private list<liveweather> lives;
    private list<forecastweather> forecasts;
}

@data
class liveweather {
    private string province;
    private string city;
    private string adcode;
    private string weather;
    private string temperature;
    private string winddirection;
    private string windpower;
    private string humidity;
    private string reporttime;
}

@data
class forecastweather {
    private string city;
    private string adcode;
    private string province;
    private string reporttime;
    private list<cast> casts;
}

@data
class cast {
    private string date;
    private string week;
    private string dayweather;
    private string nightweather;
    private string daytemp;
    private string nighttemp;
    private string daywind;
    private string nightwind;
    private string daypower;
    private string nightpower;
}

2.4.5 控制器层

package com.example.amap.controller;

import com.example.amap.model.*;
import com.example.amap.service.amapservice;
import lombok.requiredargsconstructor;
import org.springframework.web.bind.annotation.*;

@restcontroller
@requestmapping("/amap")
@requiredargsconstructor
public class amapcontroller {
    
    private final amapservice amapservice;
    
    /**
     * 地址转坐标
     */
    @getmapping("/geocode")
    public apiresponse<georesult> geocode(
            @requestparam string address,
            @requestparam(required = false) string city) {
        georesult result = amapservice.geocode(address, city);
        return apiresponse.success(result);
    }
    
    /**
     * 坐标转地址
     */
    @getmapping("/regeocode")
    public apiresponse<regeoresult> regeocode(@requestparam string location) {
        regeoresult result = amapservice.regeocode(location);
        return apiresponse.success(result);
    }
    
    /**
     * 路径规划
     */
    @getmapping("/direction")
    public apiresponse<directionresult> direction(
            @requestparam string origin,
            @requestparam string destination,
            @requestparam(required = false) string strategy) {
        directionresult result = amapservice.direction(origin, destination, strategy);
        return apiresponse.success(result);
    }
    
    /**
     * ip定位
     */
    @getmapping("/ip-locate")
    public apiresponse<iplocateresult> iplocate(@requestparam(required = false) string ip) {
        iplocateresult result = amapservice.iplocate(ip);
        return apiresponse.success(result);
    }
    
    /**
     * 天气查询
     */
    @getmapping("/weather")
    public apiresponse<weatherresult> weather(
            @requestparam string city,
            @requestparam(required = false) string extensions) {
        weatherresult result = amapservice.weather(city, extensions);
        return apiresponse.success(result);
    }
}

/**
 * 统一api响应格式
 */
@data
class apiresponse<t> {
    private int code;
    private string message;
    private t data;
    private long timestamp;
    
    public static <t> apiresponse<t> success(t data) {
        apiresponse<t> response = new apiresponse<>();
        response.setcode(200);
        response.setmessage("success");
        response.setdata(data);
        response.settimestamp(system.currenttimemillis());
        return response;
    }
    
    public static <t> apiresponse<t> error(int code, string message) {
        apiresponse<t> response = new apiresponse<>();
        response.setcode(code);
        response.setmessage(message);
        response.settimestamp(system.currenttimemillis());
        return response;
    }
}

2.4.6 全局异常处理

package com.example.amap.exception;

import com.example.amap.controller.apiresponse;
import lombok.extern.slf4j.slf4j;
import org.springframework.web.bind.annotation.exceptionhandler;
import org.springframework.web.bind.annotation.restcontrolleradvice;

@slf4j
@restcontrolleradvice
public class globalexceptionhandler {
    
    @exceptionhandler(exception.class)
    public apiresponse<object> handleexception(exception e) {
        log.error("系统异常", e);
        return apiresponse.error(500, e.getmessage());
    }
    
    @exceptionhandler(amapexception.class)
    public apiresponse<object> handleamapexception(amapexception e) {
        log.error("高德地图服务异常", e);
        return apiresponse.error(e.getcode(), e.getmessage());
    }
}

class amapexception extends runtimeexception {
    private int code;
    
    public amapexception(int code, string message) {
        super(message);
        this.code = code;
    }
    
    public int getcode() {
        return code;
    }
}

2.4.7 启动类

package com.example.amap;

import org.springframework.boot.springapplication;
import org.springframework.boot.autoconfigure.springbootapplication;
import org.springframework.boot.context.properties.enableconfigurationproperties;

@springbootapplication
@enableconfigurationproperties
public class amapapplication {
    public static void main(string[] args) {
        springapplication.run(amapapplication.class, args);
    }
}

2.5 测试示例

package com.example.amap.test;

import com.example.amap.amapapplication;
import com.example.amap.service.amapservice;
import lombok.extern.slf4j.slf4j;
import org.junit.jupiter.api.test;
import org.springframework.beans.factory.annotation.autowired;
import org.springframework.boot.test.context.springboottest;

@slf4j
@springboottest(classes = amapapplication.class)
public class amapservicetest {
    
    @autowired
    private amapservice amapservice;
    
    @test
    void testgeocode() {
        var result = amapservice.geocode("北京市朝阳区阜通东大街6号", "北京");
        log.info("地理编码结果: {}", result);
    }
    
    @test
    void testregeocode() {
        var result = amapservice.regeocode("116.481488,39.990464");
        log.info("逆地理编码结果: {}", result);
    }
    
    @test
    void testdirection() {
        var result = amapservice.direction("116.481488,39.990464", "116.434307,39.90909", "0");
        log.info("路径规划结果: {}", result);
    }
}

三、详细总结

3.1 集成要点总结

技术架构优势

  1. 微服务友好:通过resttemplate封装,易于集成到微服务架构
  2. 配置灵活:使用spring boot配置属性,支持多环境配置
  3. 性能优化:http连接池配置,提高并发性能
  4. 异常处理:统一的异常处理机制,提高系统稳定性
  5. 日志完善:完整的日志记录,便于问题排查

安全性考虑

  1. api key保护:配置文件中存储,避免硬编码
  2. 请求签名:支持sig参数,提高接口安全性
  3. 输入验证:对用户输入进行校验,防止非法参数
  4. 限流机制:可结合redis实现api调用限流

3.2 最佳实践建议

性能优化

// 1. 使用缓存减少重复请求
@cacheable(value = "geocodecache", key = "#address + '-' + #city")
public georesult geocode(string address, string city) {
    // 实现逻辑
}

// 2. 异步调用提高响应速度
@async
public completablefuture<georesult> geocodeasync(string address, string city) {
    return completablefuture.completedfuture(geocode(address, city));
}

// 3. 批量处理接口
public list<georesult> batchgeocode(list<addressrequest> requests) {
    return requests.stream()
        .map(req -> geocode(req.getaddress(), req.getcity()))
        .collect(collectors.tolist());
}

监控与告警

// 添加监控指标
@component
public class amapmetrics {
    
    private final meterregistry meterregistry;
    private final counter successcounter;
    private final counter failurecounter;
    private final timer apitimer;
    
    public amapmetrics(meterregistry meterregistry) {
        this.meterregistry = meterregistry;
        this.successcounter = counter.builder("amap.api.calls")
            .tag("status", "success")
            .register(meterregistry);
        this.failurecounter = counter.builder("amap.api.calls")
            .tag("status", "failure")
            .register(meterregistry);
        this.apitimer = timer.builder("amap.api.duration")
            .register(meterregistry);
    }
    
    public void recordsuccess(long duration) {
        successcounter.increment();
        apitimer.record(duration, timeunit.milliseconds);
    }
}

3.3 扩展功能

  1. 地理围栏服务:实现电子围栏监控
  2. 轨迹分析:车辆轨迹管理和分析
  3. 热力图生成:基于位置数据的可视化
  4. 地址标准化:地址数据清洗和标准化
  5. 智能推荐:基于位置的商家推荐

3.4 注意事项

  1. api调用限制:注意高德地图api的调用频率限制
  2. 错误码处理:完整处理高德地图返回的错误码
  3. 服务降级:在api服务不可用时实现降级策略
  4. 数据一致性:考虑数据更新和缓存的同步问题
  5. 合规性:确保应用符合国家的地理信息安全规定

3.5 部署

  1. 多环境配置:开发、测试、生产环境使用不同的api key
  2. 密钥轮换:定期更新api key,提高安全性
  3. 监控告警:设置api调用异常告警
  4. 文档完善:编写详细的api使用文档
  5. 压力测试:上线前进行充分的压力测试

通过以上完整的集成方案,springboot应用可以高效、稳定地集成高德地图sdk,为业务提供丰富的位置服务功能。

以上就是springboot集成高德地图sdk的详细步骤的详细内容,更多关于springboot集成高德地图sdk的资料请关注代码网其它相关文章!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com