开发者

springboot项目中整合高德地图的实践

目录
  • 一:高德开放平台的使用
  • 二:创建数据库(我是用的是mysql)
  • 三:Springboot所需的依赖(根据你的需求再去增加删除依赖)
  • 四:yml文件的配置
  • 五:所需要的类
    • 写一个简单的页面展示吧
  • 总结

    一:高德开放平台的使用

    高德开放平台 | 高德地图API

    注册高德地图账号

    springboot项目中整合高德地图的实践

    认证填写个人信息:

    认证方式选择“个人认证开发者”即可,然后完善信息

    springboot项目中整合高德地图的实践

    认证成功之后,再次进入控制台,创建关于地图的应用

    springboot项目中整合高德地图的实践

    创建Key(yml文件需要使用):

    springboot项目中整合高德地图的实践

    springboot项目中整合高德地图的实践

    以上步骤便可以完成高德地图的申请和key的创建。

    开始Springboot的创建(就不从0到一的创建了)

    二:创建数据库(我是用的是MySQL)

    建表语句:

    CREATE TABLE `location_record` (
      `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
      `ip` VARCHAR(50) DEFAULT NULL COMMENT '客户端IP地址',
      `longitude` DOUBLE(10,6) NOT NULL COMMENT '经度坐标,精确到小数点后6位',
      `latitude` DOUBLE(1编程客栈0,6) NOT NULL COMMENT '纬度坐标,精确到小数点后6位',
      `address` VARCHAR(255) DEFAULT NULL COMMENT '详细地址信息',
      `formatted_address` VARCHAR(255) DEFAULT NULL COMMENT '格式化后的完整地址',
      `city` VARCHAR(100) DEFAULT NULL COMMENT '所在城市名称',
      `province` VARCHAR(100) DEFAULT NULL COMMENT '所在省份名称',
      `district` VARCHAR(100) DEFAULT NULL COMMENT '新增:所在区县名称',
      `street` VARCHAR(100) DEFAULT NULL COMMENT '新增:街道信息',
      `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '记录创建时间',
      `update_time` DATETIME DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '记录更新时间',
      PRIMARY KEY (`id`),
      KEY `idx_location` (`longitude`,`latitude`),
      KEY `idx_create_time` (`create_time`)
    ) ENGINE=INNODB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='地理位置信息记录表';

    表中样式:

    springboot项目中整合高德地图的实践

    三:Springboot所需的依赖(根据你的需求再去增加删除依赖)

    dependencies>
        <!-- FastjsON -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.76</version>
        </dependency>
        
        <!-- OkHttp -->
        <dependency>
            <groupId>com.squareup.okhttp3</groupId>
            <artifactId>okhttp</artifactId>
            <version>4.12.0</version>
        </dependency>
    
    
        <dependency>
             <groupId>com.alibaba</groupId>
             <artifactId>druid-spring-boot-starter</artifactId>
             <version> 1.2.23</version>
        </dependency>
        <dependency>
              <groupId>mysql</groupId>
              <artifactId>mysql-connector-Java</artifactId>
              <version>8.0.33</version>
        </dependency>
         <dependency>
              <groupId>com.baomidou</groupId>
              <artifactId>myBATis-plus-boot-starter</artifactId>
               <version>3.5.6</version>
          </dependency>
    
        <!-- Spring Boot Starter Web -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.6.13</version>
        </dependency>
        
        <!-- Apache HttpClient -->
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.5.13</version>
        </dependency>
    
        <!-- Spring Boot Configuration Processor -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <version>2.6.13</version>
            <optional>true</optional>
        </dependency>
    
        <!-- Lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.26</version>
        </dependency>
    </dependencies>

    四:yml文件的配置

    server:
      port: 8096
    
    spring:
      amap:
        key: "你的高德地图key值"
        version: 2.0
        geocode-url: https://restapi.amap.com/v3/geocode/geo
        ip-url: https://restapi.amap.com/v3/ip
        regeo-url: https://restapi.amap.com/v3/geocode/regeo
    
      datasource: # 数据源配置
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://localhost:3306/你所建表对应的数据库?serverTimezone=Asia/Shanghai&useSSL=false
        username: root
        password: root
        type: com.alibaba.druid.pool.DruidDataSource
    
    # mybatis-plus配置,也可以不加,只是为了显示SQL,Springboot都自动配置好了
    mybatis-plus:
      configuration:
        log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

    五:所需要的类

    springboot项目中整合高德地图的实践

    • AmapConfig:
    package com.qfedu.config;
    
    
    import lombok.Data;
    import org.springframework.boot.context.properties.ConfigurationProperties;
    import org.springframework.context.annotation.Configuration;
    
    @Data
    @Configuration
    @ConfigurationProperties(prefix = "spring.amap")
    public class AmapConfig {
        private String key;                   // 对应配置中的 key
        private String securityJsCode;        // 对应 security-js-code
        private String version = "2.0";       // 默认版本号
        private String geocodeUrl;            // 对应 geocode.url
        private String ipUrl;                 // 对应 ip.url
        private String regeoUrl;              // 对应 regeo.url
    }
    • WebMvcConfig(因为我的项目中配置了拦截器,所以需要这样一个类)
    package com.qfedu.config;
    
    import com.qfedu.common.core.interceptor.LoginInterceptor;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
    
    @Configuration
    public class WebMvcConfig implements WebMvcConfigurer {
    
        @Bean
        public LoginInterceptor loginInterceptor() {
            return new LoginInterceptor();
        }
    
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            registry.addInterceptor(loginInterceptor())
                    .addPathPatterns("/**")
                    .excludePathPatterns(
                            "/api/amap/**",
                            "/api/location/**"  // 新增排除location相关路径
                    );
        }
    }
    • HttpUtils:
    package com.qfedu.utils;
    
    import com.sun.deploy.net.URLEncoder;
    import org.apache.http.HttpEntity;
    import org.apache.http.client.methods.CloseableHttpResponse;
    import org.apache.http.client.methods.HttpGet;
    import org.apache.http.impl.client.CloseableHttpClient;
    import org.apache.http.impl.client.HttpClients;
    import org.apache.http.util.EntityUtils;
    
    import java.io.IOException;
    import java.nio.charset.StandardCharsets;
    
    public class HttpUtil {
        public static String doGet(String url) throws IOException {
            if (url == null || url.trim().isEmpty()) {
                throw new IllegalArgumentException("URL不能为空");
            }
    
            CloseableHttpClient httpClient = HttpClients.createDefault();
            HttpGet httpGet = new HttpGet(url);
    
            // 设置请求头
            httpGet.setHeader("Accept", "application/json");
            httpGet.setHeader("Content-Type", "application/json");
    
            try (CloseableHttpResponse response = httpClient.execute(httpGet)) {
                int statusCode = response.getStatusLine().getStatusCode();
                if (statusCode != 200) {
                    throw new IOException("HTTP请求失败,状态码: " + statusCode + ", URL: " + url);
                }
    
                HttpEntity entity = response.getEntity();
                if (entity == null) {
                    throw new IOException("响应体为空");
                }
    
                return EntityUtils.toString(entity, StandardCharsets.UTF_8);
            } finally {
                httpClient.close();
            }
        }
    
        public static String encodeUrlParam(String param) {
            try {
                return URLEncoder.encode(param, StandardCharsets.UTF_8.name());
            } catch (Exception e) {
                return param;
            }
        }
    }
    • 返回值R类:(我的R类没有使用泛型)
    package com.qfedu.common.core.common;
    
    public class R {
        /**
         * code,指状态码,
         * 随意定,20000 是正确,40000 错误
         * 50000 请求超时
         * 60000 没有权限
         * msg,指信息描述
         * data,返回的数据
         */
        private int code;
        private String msg;
        private Object data;
    
    
        public static R ok() {
            R r = new R();
            r.setCode(200);
            r.setMsg(编程客栈"成功");
            return r;
        }
    
        public static R ok(Object data) {
            R r = new R();
            r.setCode(200);
            r.setMsg("成功");
            r.setData(data);
            return r;
        }
    
    
        public static R fail() {
            R r = new R();
            r.setCode(500);
            r.setMsg("失败");
            return r;
        }
    
        public static R fail(String msg) {
            R r = new R();
            r.setCode(500);
            r.setMsg(msg);
            return r;
        }
    
        public int getCode() {
            return code;
        }
    
        public void setCode(int code) {
            this.code = code;
        }
    
        public String getMsg() {
            return msg;
        }
    
        public void setMsg(String msg) {
            this.msg = msg;
        }
    
        public Object getData() {
            return data;
        }
    
        public void setData(Object data) {
            this.data = data;
        }
    
    
    }
    • 免登录自定义注解:
    package com.qfedu.common.core.annotation;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    /**
     * 以梦为马,以汗为泉,不忘初心,不负韶华
     *
     * @author ${上官箫宇}
     * @version 1.0
     * @data 2025/6/3 16:08
     */
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)//注解运行时生效
    public @interface NoLogin {
    }
    • 拦截器:
    package com.qfedu.common.core.interceptor;
    
    
    import com.qfedu.common.core.annotation.NoLogin;
    import com.qfedu.common.core.constants.CommonConstants;
    import com.qfedu.common.core.utils.JwtUtils;
    import com.qfedu.common.core.utils.UserUtils;
    import io.jsonwebtoken.Claims;
    import org.springframework.web.method.HandlerMethod;
    import org.springframework.web.servlet.HandlerInterceptor;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.lang.reflect.Method;
    
    /**
     * ---Do First---
     *
     * @author:wellseasun
     * @date:2025/5/22 下午 8:30
     * @desc:
     */
    public class LoginInterceptor implements HandlerInterceptor {
        // preHandle:执行时机:访问接口前
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
            // handler表示处理某个请求的处理器对象,
            // 如果是类级别的拦截器,则handler为类对象,如果是方法级别的拦截器,则handler为方法对象
    
            if (handler instanceof HandlerMethod) {
                HandlerMethod handlerMethod = (HandlerMethod) handler;
                Method method = handlerMethod.getMethod();
                boolean annotationPresent = method.isAnnotationPresent(NoLogin.class);
                if (annotationPresent) {
                    // 如果使用了注解,直接放行
                    return true;
                } else {
                    // 没有使用注解,需要从请求头中获取名为LOGIN_TOKEN的token
                    String token = request.getHeader(CommonConstants.LOGIN_TOKEN);
                    if (token == null || token.isEmpty()) {
                        throw new RuntimeException("请重新登录");
                    }
                    try {
                        JwtUtils jwtUtils = new JwtUtils();
                        Claims claims = jwtUtils.parseJWT(token);
                        UserUtils.setUid((Integer) claims.get("uid"));
                    } catch (Exception e) {
                        throw e;
                    }
                }
            }
            return true;
        }
    
    
    
    }

    没错,下面就是层级关系

    • mapper:
    package com.qfedu.mapper;
    
    
    import com.baomidou.mybatisplus.core.mapper.BaseMapper;
    import com.qfedu.common.core.entity.LocationRecord;
    
    public interface LocationRecordMapper extends BaseMapper<LocationRecord> {
    }
    • service:
    package com.qfedu.service;
    
    import com.alibaba.fastjson.JSONObject;
    import com.qfedu.common.core.entity.LocationRecord;
    
    
    public interface AmapService {
        /**
         * IP定位
         * @param ip IP地址
         * @return 定位结果
         */
        JSONObject ipLocation(String ip);
    
        /**
         * 逆地理编码
         * @param longitude 经度
         * @param latitude 纬度
         * @return 地址信息
         */
        JSONObject regeoLocation(Double longitude, Double latitude);
    
        /**
         * 地理编码
         * @param address 地址
         * @return 经纬度信息
         */
        JSONObject geoLocation(String address);
    
        /**
         * 保存定位记录
         * @param record 定位记录
         * @return 是否成功
         */
        boolean saveLocationRecord(LocationRecord record);
    }
    • service实现类:
    package com.qfedu.service.impl;
    
    import com.alibaba.fastjson.JSON;
    import com.alibaba.fastjson.JSONObject;
    import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
    import com.qfedu.common.core.entity.LocationRecord;
    import com.qfedu.config.AmapConfig;
    import com.qfedu.mapper.LocationRecordMapper;
    import com.qfedu.service.AmapService;
    import com.qfedu.utils.HttpUtil;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import org.springframework.util.StringUtils;
    
    import javax.annotation.PostConstruct;
    
    /**
     * 高德地图服务实现类
     * 提供IP定位、地理编码、逆地理编码等核心功能
     */
    @Service
    public class AmapServiceImpl extends ServiceImpl<LocationRecordMapper, LocationRecord>
            implements AmapService {
    
        private static final Logger logger = LoggerFactory.getLogger(AmapServiceImpl.class);
    
        @Autowired
        private AmapConfig amapConfig; // 高德配置参数(key/url等)
    
        /**
         * 初始化时打印配置信息(调试用)
         */
        @PostConstruct
        public void init() {
            logger.info("高德地图配置加载: key={}, ipUrl={}, geoUrl={}, regeoUrl={}",
                    amapConfig.getKey(),
                    amapConfig.getIpUrl(),
                    amapConfig.getGeocodeUrl(),
                    amapConfig.getRegeoUrl());
        }
    
        // ==================== 核心服务方法 ====================
    
        /**
         * IP定位服务
         * @param ip 需要查询的IP地址
       编程客栈  * @return 包含定位结果的JSON对象(status=1成功,0失败)
         */
        @Override
        public JSONObject ipLocation(String ip) {
            // 参数校验
            if (!StringUtils.hasText(ip)) {
                return createErrorResponse("IP地址不能为空");
            }
    
            try {
                // 配置校验
                validateConfig(amapConfig.getKey(), amapConfig.getIpUrl());
    
                // 构建请求URL(示例:https://restapi.amap.com/v3/ip?key=xxx&ip=8.8.8.8)
                String url = String.format("%s?key=%s&ip=%s",
                        amapConfig.getIpUrl().trim(),
                        amapConfig.getKey().trim(),
                        HttpUtil.encodeUrlParam(ip));
    
                validateUrl(url); // URL格式校验
                logger.info("请求高德IP定位API: {}", url);
    
                // 发送HTTP请求并解析响应
                String response = HttpUtil.doGet(url);
                logger.debug("高德IP定位API响应: {}", response);
    
                return parseResponse(response);
            } catch (Exception e) {
                logger.error("IP定位失败, IP: " + ip, e);
                return createErrorResponse("IP定位失败: " + e.getMessage());
            }
        }
    
        /**
         * 逆地理编码服务(坐标→地址)
         * @param longitude 经度
         * @param latitude 纬度
         * @return 包含地址信息的JSON响应
         */
        @Override
        public JSONObject regeoLocation(Double longitude, Double latitude) {
            if (longitude == null || latitude == null) {
                return createErrorResponse("经纬度不能为空");
            }
    
            try {
                validateConfig(amapConfig.getKey(), null); // 仅校验Key
    
                // 构建请求URL(示例:https://restapi.amap.com/v3/geocode/regeo?key=xxx&location=116.4,39.9)
                String location = longitude + "," + latitude;
                String url = String.format("%s?key=%s&location=%s",
                        amapConfig.getRegeoUrl(),
                        amapConfig.getKey(),
                        HttpUtil.encodeUrlParam(location));
    
                logger.debug("请求高德逆地理编码API: {}", url);
                String response = HttpUtil.doGet(url);
                logger.debug("高德逆地理编码API响应: {}", response);
    
                return parseResponse(response);
            } catch (Exception e) {
                logger.error("逆地理编码失败, 位置: " + longitude + "," + latitude, e);
                return createErrorResponse("逆地理编码失败: " + getErrorMessage(e));
            }
        }
    
        /**
         * 地理编码服务(地址→坐标)
         * @param address 结构化地址(如"北京市海淀区中关村大街1号")
         * @return 包含经纬度的JSON响应
         */
        @Override
        public JSONObject geoLocation(String pythonaddress) {
            if (!StringUtils.hasText(address)) {
                return createErrorResponse("地址不能为空");
            }
    
            try {
                validateConfig(amapConfig.getKey(), null); // 仅校验Key
    
                // 构建请求URL(示例:https://restapi.amap.com/v3/geocode/geo?key=xxx&address=北京)
                String url = String.format("%s?key=%s&address=%s",
                        amapConfig.getGeocodeUrl(),
                        amapConfig.getKey(),
                        HttpUtil.encodeUrlParam(address));
    
                logger.debug("请求高德地理编码API: {}", url);
                String response = HttpUtil.doGet(url);
                logger.debug("高德地理编码API响应: {}", response);
    
                return parseResponse(response);
            } catch (Exception e) {
                logger.error("地理编码失败, 地址: " + address, e);
                return createErrorResponse("地理编码失败: " + getErrorMessage(e));
            }
        }
    
        /**
         * 保存定位记录到数据库
         * @param record 定位记录实体
         * @return 是否保存成功
         */
        @Override
        public boolean saveLocationRecord(LocationRecord record) {
            try {
                return this.save(record); // 调用MyBatis-Plus的save方法
            } catch (Exception e) {
                logger.error("保存定位记录失败", e);
                return false;
            }
        }
    
        // ==================== 内部工具方法 ====================
    
        /**
         * 校验高德配置参数
         * @param key 高德API Key
         * @param url 需要校验的API地址(可选)
         * @throws IllegalStateException 当配置不合法时抛出
         */
        private void validateConfig(String key, String url) {
            if (amapConfig == null || !StringUtils.hasText(key)) {
                throw new IllegalStateException("高德地图配置未正确初始化");
            }
            if (url != null && !StringUtils.hasText(url)) {
                throw new IllegalStateException("高德API地址未配置");
            }
        }
    
        /**
         * 校验URL合法性
         * @param url 待校验的URL
         * @throws IllegalArgumentException 当URL非法时抛出
         */
        private void validateUrl(String url) {
            if (!url.startsWith("http")) {
                throw new IllegalArgumentException("无效的API URL: " + url);
            }
        }
    
        /**
         * 解析高德API响应
         * @param response 原始JSON字符串
         * @return 解析后的JSONObject
         */
        private JSONObject parseResponse(String response) {
            if (!StringUtils.hasText(response)) {
                return createErrorResponse("空响应");
            }
            try {
                JSONObject result = JSON.parseobject(response);
                return result != null ? result : createErrorResponse("响应解析失败");
            } catch (Exception e) {
                logger.error("解析高德API响应失败", e);
                return createErrorResponse("响应解析失败: " + e.getMessage());
            }
        }
    
        /**
         * 创建错误响应
         * @param message 错误信息
         * @return 标准化错误JSON(status=0)
         */
        private JSONObject createErrorResponse(String message) {
            JSONObject result = new JSONObject();
            result.put("status", "0"); // 高德标准错误码
            result.put("info", message);
            return result;
        }
    
        /**
         * 提取异常信息(避免null)
         */
        private String getErrorMessage(Exception e) {
            return e.getMessage() != null ? e.getMessage() : "未知错误";
        }
    }
    • controller:
    package com.qfedu.controller;
    
    import com.alibaba.fastjson.JSONObject;
    import com.qfedu.common.core.annotation.NoLogin;
    import com.qfedu.common.core.common.R;
    import com.qfedu.common.core.entity.LocationRecord;
    import com.qfedu.service.AmapService;
    import org.springframework.beans.factory.annotation.Autowired;
    imVhoZxNmCdnport org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.bind.annotation.RestController;
    
    import java.util.Date;
    
    /**
     * 高德地图定位服务控制器
     * 提供IP定位、逆地理编码、地理编码三大核心功能
     */
    @RestController
    @RequestMapping("/api/location")
    public class LocationController {
    
        @Autowired
        private AmapService amapService; // 高德地图服务接口
    
        /**
         * IP定位接口
         * @param ip 需要定位的IP地址(如8.8.8.8)
         * @return 标准化响应R<JSONObject>,包含定位结果或错误信息
         */
        @GetMapping("/ip")
        @NoLogin
        public R locateByIp(@RequestParam String ip) {
            // 调用高德IP定位服务
            JSONObject result = amapService.ipLocation(ip);
    
            // 校验高德API返回状态码(1=成功)
            if (result != null && "1".equals(result.getString("status"))) {
                saveLocationRecord(ip, result); // 持久化定位记录
                return R.ok(result); // 返回成功响应
            }
            // 失败时返回错误信息(优先使用高德返回的info字段)
            return R.fail(result != null ? result.getString("info") : "IP定位服务不可用");
        }
    
        /**
         * 逆地理编码接口(坐标→地址)
         * @param longitude 经度(如116.404)
         * @param latitude 纬度(如39.915)
         * @return 包含地址信息的标准化响应
         */
        @GetMapping("/regeo")
        @NoLogin
        public R regeo(
                @RequestParam Double longitude,
                @RequestParam Double latitude) {
            JSONObject result = amapService.regeoLocation(longitude, latitude);
            if (result != null && "1".equals(result.getString("status"))) {
                saveLocationRecord(null, longitude, latitude, result); // IP传null
                return R.ok(result);
            }
            return R.fail(result != null ? result.getString("info") : "逆地理编码服务不可用");
        }
    
        /**
         * 地理编码接口(地址→坐标)
         * @param address 结构化地址(如"北京市海淀区中关村大街1号")
         * @return 包含经纬度的标准化响应
         */
        @GetMapping("/geo")
        @NoLogin
        public R geo(@RequestParam String address) {
            JSONObject result = amapService.geoLocation(address);
            if (result != null && "1".equals(result.getString("status"))) {
                return R.ok(result); // 地理编码不保存记录
            }
            return R.fail(result != null ? result.getString("info") : "地理编码服务不可用");
        }
    
        // 内部工具方法
    
        /**
         * 从IP定位结果提取经纬度并保存记录
         * @param ip IP地址
         * @param result 高德API返回的完整结果
         */
        private void saveLocationRecord(String ip, JSONObject result) {
            JSONObject locationObj = result.getJSONObject("location");
            if (locationObj != null) {
                saveLocationRecord(
                        ip,
                        locationObj.getDouble("lng"), // 经度字段
                        locationObj.getDouble("lat"), // 纬度字段
                        result
                );
            }
        }
    
        /**
         * 保存定位记录到数据库(核心方法)
         * @param ip 可能为null(当来源是逆地理编码时)
         * @param longitude 经度(必填)
         * @param latitude 纬度(必填)
         * @param result 高德API原始结果(用于提取地址信息)
         */
        private void saveLocationRecord(
                String ip,
                Double longitude,
                Double latitude,
                JSONObject result) {
            if (result == null) return;
    
            // 1. 构建定位记录实体
            LocationRecord record = new LocationRecord();
            record.setIp(ip); // IP可能为null
            record.setLongitude(longitude);
            record.setLatitude(latitude);
    
            // 2. 提取格式化地址(如"北京市海淀区中关村大街1号")
            String formattedAddress = result.getString("formatted_address");
            record.setAddress(formattedAddress);
            record.setFormattedAddress(formattedAddress);
    
            // 3. 提取结构化地址组件(省、市、区等)
            JSONObject addressComponent = result.getJSONObject("addressComponent");
            if (addressComponent != null) {
                record.setProvince(addressComponent.getString("province"));
                record.setCity(addressComponent.getString("city"));
                // 可扩展:district(区)、street(街道)等字段
            }
    
            // 4. 设置时间戳并保存
            record.setCreateTime(new Date());
            amapService.saveLocationRecord(record); // 调用MyBatis-Plus持久化
        }
    }

    下面就是启动类:(首先不要忘记启动类的扫描注解,还有就是本次用到的注解

    @EnableConfigurationProperties({AmapConfig.class})// 启用AmapConfig配置类)
    package com.qfedu;
    
    import com.qfedu.config.AmapConfig;
    import org.mybatis.spring.annotation.MapperScan;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.boot.context.properties.EnableConfigurationProperties;
    
    @SpringBootApplication
    @MapperScan("com.qfedu.mapper")
    @EnableConfigurationProperties({AmapConfig.class})// 启用AmapConfig配置类
    
    public class MicroServeAmapApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(MicroServeAmapApplication.class, args);
        }
    
    }

    写一个简单的页面展示吧

    位置你们知道吧,我就不说详细了

    展示台湾省地图吧(中国一点都不能少)

    springboot项目中整合高德地图的实践

    springboot项目中整合高德地图的实践

    下面就是展示的代码,我只不过吧经纬度写成死值了,

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <title>高德地图展示测试:台湾省台北市地图 - 台北101</title>
        <!-- 引入高德地图JS API -->
        <script src="https://webapi.amap.com/maps?v=2.0&key=你的高德地图key"></script>
        <style>
            #container {
                width: 100%;
                height: 600px;
            }
        </style>
    </head>
    <body>
    <!-- 地图容器 -->
    <div id="container"></div>
    
    <script>
        // 初始化地图,中心点设为台北市
        var map = new AMap.Map('container', {
            zoom: 14,          // 缩放级别
            center: [121.5654, 25.0330], // 台北市坐标
            viewMode: '2D'     // 2D地图
        });
    
        // 添加标记点(台北101大楼)
        var marker = new AMap.Marker({
            position: [121.5654, 25.0330], // 台北101坐标
            map: map
        });
    
        // 信息窗口内容
        var infoWindow = new AMap.InfoWindow({
            content: '<div>台北101大楼</div>',
            offset: new AMap.Pixel(0, -30)
        });
        infoWindow.open(map, marker.getPosition());
    </script>
    </body>
    </html>

    总结

    以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程客栈(www.devze.com)。

    0

    上一篇:

    下一篇:

    精彩评论

    暂无评论...
    验证码 换一张
    取 消

    最新开发

    开发排行榜