springboot項(xiàng)目中整合高德地圖的實(shí)踐
一:高德開放平臺(tái)的使用
注冊高德地圖賬號(hào)
認(rèn)證填寫個(gè)人信息:
認(rèn)證方式選擇“個(gè)人認(rèn)證開發(fā)者”即可,然后完善信息
認(rèn)證成功之后,再次進(jìn)入控制臺(tái),創(chuàng)建關(guān)于地圖的應(yīng)用
創(chuàng)建Key(yml文件需要使用):
以上步驟便可以完成高德地圖的申請和key的創(chuàng)建。
開始Springboot的創(chuàng)建(就不從0到一的創(chuàng)建了)
二:創(chuàng)建數(shù)據(jù)庫(我是用的是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 '經(jīng)度坐標(biāo),精確到小數(shù)點(diǎn)后6位', `latitude` DOUBLE(10,6) NOT NULL COMMENT '緯度坐標(biāo),精確到小數(shù)點(diǎn)后6位', `address` VARCHAR(255) DEFAULT NULL COMMENT '詳細(xì)地址信息', `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 '新增:所在區(qū)縣名稱', `street` VARCHAR(100) DEFAULT NULL COMMENT '新增:街道信息', `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '記錄創(chuàng)建時(shí)間', `update_time` DATETIME DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '記錄更新時(shí)間', 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所需的依賴(根據(jù)你的需求再去增加刪除依賴)
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: # 數(shù)據(jù)源配置 driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/你所建表對應(yīng)的數(shù)據(jù)庫?serverTimezone=Asia/Shanghai&useSSL=false username: root password: root type: com.alibaba.druid.pool.DruidDataSource # mybatis-plus配置,也可以不加,只是為了顯示SQL,Springboot都自動(dòng)配置好了 mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
五:所需要的類
- 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; // 對應(yīng)配置中的 key private String securityJsCode; // 對應(yīng) security-js-code private String version = "2.0"; // 默認(rèn)版本號(hào) private String geocodeUrl; // 對應(yīng) geocode.url private String ipUrl; // 對應(yīng) ip.url private String regeoUrl; // 對應(yīng) regeo.url }
- WebMvcConfig(因?yàn)槲业捻?xiàng)目中配置了攔截器,所以需要這樣一個(gè)類)
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相關(guān)路徑 ); } }
- 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); // 設(shè)置請求頭 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請求失敗,狀態(tài)碼: " + statusCode + ", URL: " + url); } HttpEntity entity = response.getEntity(); if (entity == null) { throw new IOException("響應(yīng)體為空"); } 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,指狀態(tài)碼, * 隨意定,20000 是正確,40000 錯(cuò)誤 * 50000 請求超時(shí) * 60000 沒有權(quán)限 * msg,指信息描述 * data,返回的數(shù)據(jù) */ 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; /** * 以夢為馬,以汗為泉,不忘初心,不負(fù)韶華 * * @author ${上官簫宇} * @version 1.0 * @data 2025/6/3 16:08 */ @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME)//注解運(yùn)行時(shí)生效 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:執(zhí)行時(shí)機(jī):訪問接口前 @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { // handler表示處理某個(gè)請求的處理器對象, // 如果是類級(jí)別的攔截器,則handler為類對象,如果是方法級(jí)別的攔截器,則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; } }
沒錯(cuò),下面就是層級(jí)關(guān)系
- 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 定位結(jié)果 */ JSONObject ipLocation(String ip); /** * 逆地理編碼 * @param longitude 經(jīng)度 * @param latitude 緯度 * @return 地址信息 */ JSONObject regeoLocation(Double longitude, Double latitude); /** * 地理編碼 * @param address 地址 * @return 經(jīng)緯度信息 */ JSONObject geoLocation(String address); /** * 保存定位記錄 * @param record 定位記錄 * @return 是否成功 */ boolean saveLocationRecord(LocationRecord record); }
- service實(shí)現(xiàn)類:
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; /** * 高德地圖服務(wù)實(shí)現(xiàn)類 * 提供IP定位、地理編碼、逆地理編碼等核心功能 */ @Service public class AmapServiceImpl extends ServiceImpl<LocationRecordMapper, LocationRecord> implements AmapService { private static final Logger logger = LoggerFactory.getLogger(AmapServiceImpl.class); @Autowired private AmapConfig amapConfig; // 高德配置參數(shù)(key/url等) /** * 初始化時(shí)打印配置信息(調(diào)試用) */ @PostConstruct public void init() { logger.info("高德地圖配置加載: key={}, ipUrl={}, geoUrl={}, regeoUrl={}", amapConfig.getKey(), amapConfig.getIpUrl(), amapConfig.getGeocodeUrl(), amapConfig.getRegeoUrl()); } // ==================== 核心服務(wù)方法 ==================== /** * IP定位服務(wù) * @param ip 需要查詢的IP地址 * @return 包含定位結(jié)果的JSON對象(status=1成功,0失?。? */ @Override public JSONObject ipLocation(String ip) { // 參數(shù)校驗(yàn) if (!StringUtils.hasText(ip)) { return createErrorResponse("IP地址不能為空"); } try { // 配置校驗(yàn) validateConfig(amapConfig.getKey(), amapConfig.getIpUrl()); // 構(gòu)建請求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格式校驗(yàn) logger.info("請求高德IP定位API: {}", url); // 發(fā)送HTTP請求并解析響應(yīng) String response = HttpUtil.doGet(url); logger.debug("高德IP定位API響應(yīng): {}", response); return parseResponse(response); } catch (Exception e) { logger.error("IP定位失敗, IP: " + ip, e); return createErrorResponse("IP定位失敗: " + e.getMessage()); } } /** * 逆地理編碼服務(wù)(坐標(biāo)→地址) * @param longitude 經(jīng)度 * @param latitude 緯度 * @return 包含地址信息的JSON響應(yīng) */ @Override public JSONObject regeoLocation(Double longitude, Double latitude) { if (longitude == null || latitude == null) { return createErrorResponse("經(jīng)緯度不能為空"); } try { validateConfig(amapConfig.getKey(), null); // 僅校驗(yàn)Key // 構(gòu)建請求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響應(yīng): {}", response); return parseResponse(response); } catch (Exception e) { logger.error("逆地理編碼失敗, 位置: " + longitude + "," + latitude, e); return createErrorResponse("逆地理編碼失敗: " + getErrorMessage(e)); } } /** * 地理編碼服務(wù)(地址→坐標(biāo)) * @param address 結(jié)構(gòu)化地址(如"北京市海淀區(qū)中關(guān)村大街1號(hào)") * @return 包含經(jīng)緯度的JSON響應(yīng) */ @Override public JSONObject geoLocation(String address) { if (!StringUtils.hasText(address)) { return createErrorResponse("地址不能為空"); } try { validateConfig(amapConfig.getKey(), null); // 僅校驗(yàn)Key // 構(gòu)建請求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響應(yīng): {}", response); return parseResponse(response); } catch (Exception e) { logger.error("地理編碼失敗, 地址: " + address, e); return createErrorResponse("地理編碼失敗: " + getErrorMessage(e)); } } /** * 保存定位記錄到數(shù)據(jù)庫 * @param record 定位記錄實(shí)體 * @return 是否保存成功 */ @Override public boolean saveLocationRecord(LocationRecord record) { try { return this.save(record); // 調(diào)用MyBatis-Plus的save方法 } catch (Exception e) { logger.error("保存定位記錄失敗", e); return false; } } // ==================== 內(nèi)部工具方法 ==================== /** * 校驗(yàn)高德配置參數(shù) * @param key 高德API Key * @param url 需要校驗(yàn)的API地址(可選) * @throws IllegalStateException 當(dāng)配置不合法時(shí)拋出 */ 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地址未配置"); } } /** * 校驗(yàn)URL合法性 * @param url 待校驗(yàn)的URL * @throws IllegalArgumentException 當(dāng)URL非法時(shí)拋出 */ private void validateUrl(String url) { if (!url.startsWith("http")) { throw new IllegalArgumentException("無效的API URL: " + url); } } /** * 解析高德API響應(yīng) * @param response 原始JSON字符串 * @return 解析后的JSONObject */ private JSONObject parseResponse(String response) { if (!StringUtils.hasText(response)) { return createErrorResponse("空響應(yīng)"); } try { JSONObject result = JSON.parseObject(response); return result != null ? result : createErrorResponse("響應(yīng)解析失敗"); } catch (Exception e) { logger.error("解析高德API響應(yīng)失敗", e); return createErrorResponse("響應(yīng)解析失敗: " + e.getMessage()); } } /** * 創(chuàng)建錯(cuò)誤響應(yīng) * @param message 錯(cuò)誤信息 * @return 標(biāo)準(zhǔn)化錯(cuò)誤JSON(status=0) */ private JSONObject createErrorResponse(String message) { JSONObject result = new JSONObject(); result.put("status", "0"); // 高德標(biāo)準(zhǔn)錯(cuò)誤碼 result.put("info", message); return result; } /** * 提取異常信息(避免null) */ private String getErrorMessage(Exception e) { return e.getMessage() != null ? e.getMessage() : "未知錯(cuò)誤"; } }
- 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; import 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; /** * 高德地圖定位服務(wù)控制器 * 提供IP定位、逆地理編碼、地理編碼三大核心功能 */ @RestController @RequestMapping("/api/location") public class LocationController { @Autowired private AmapService amapService; // 高德地圖服務(wù)接口 /** * IP定位接口 * @param ip 需要定位的IP地址(如8.8.8.8) * @return 標(biāo)準(zhǔn)化響應(yīng)R<JSONObject>,包含定位結(jié)果或錯(cuò)誤信息 */ @GetMapping("/ip") @NoLogin public R locateByIp(@RequestParam String ip) { // 調(diào)用高德IP定位服務(wù) JSONObject result = amapService.ipLocation(ip); // 校驗(yàn)高德API返回狀態(tài)碼(1=成功) if (result != null && "1".equals(result.getString("status"))) { saveLocationRecord(ip, result); // 持久化定位記錄 return R.ok(result); // 返回成功響應(yīng) } // 失敗時(shí)返回錯(cuò)誤信息(優(yōu)先使用高德返回的info字段) return R.fail(result != null ? result.getString("info") : "IP定位服務(wù)不可用"); } /** * 逆地理編碼接口(坐標(biāo)→地址) * @param longitude 經(jīng)度(如116.404) * @param latitude 緯度(如39.915) * @return 包含地址信息的標(biāo)準(zhǔn)化響應(yīng) */ @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") : "逆地理編碼服務(wù)不可用"); } /** * 地理編碼接口(地址→坐標(biāo)) * @param address 結(jié)構(gòu)化地址(如"北京市海淀區(qū)中關(guān)村大街1號(hào)") * @return 包含經(jīng)緯度的標(biāo)準(zhǔn)化響應(yīng) */ @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") : "地理編碼服務(wù)不可用"); } // 內(nèi)部工具方法 /** * 從IP定位結(jié)果提取經(jīng)緯度并保存記錄 * @param ip IP地址 * @param result 高德API返回的完整結(jié)果 */ private void saveLocationRecord(String ip, JSONObject result) { JSONObject locationObj = result.getJSONObject("location"); if (locationObj != null) { saveLocationRecord( ip, locationObj.getDouble("lng"), // 經(jīng)度字段 locationObj.getDouble("lat"), // 緯度字段 result ); } } /** * 保存定位記錄到數(shù)據(jù)庫(核心方法) * @param ip 可能為null(當(dāng)來源是逆地理編碼時(shí)) * @param longitude 經(jīng)度(必填) * @param latitude 緯度(必填) * @param result 高德API原始結(jié)果(用于提取地址信息) */ private void saveLocationRecord( String ip, Double longitude, Double latitude, JSONObject result) { if (result == null) return; // 1. 構(gòu)建定位記錄實(shí)體 LocationRecord record = new LocationRecord(); record.setIp(ip); // IP可能為null record.setLongitude(longitude); record.setLatitude(latitude); // 2. 提取格式化地址(如"北京市海淀區(qū)中關(guān)村大街1號(hào)") String formattedAddress = result.getString("formatted_address"); record.setAddress(formattedAddress); record.setFormattedAddress(formattedAddress); // 3. 提取結(jié)構(gòu)化地址組件(省、市、區(qū)等) JSONObject addressComponent = result.getJSONObject("addressComponent"); if (addressComponent != null) { record.setProvince(addressComponent.getString("province")); record.setCity(addressComponent.getString("city")); // 可擴(kuò)展:district(區(qū))、street(街道)等字段 } // 4. 設(shè)置時(shí)間戳并保存 record.setCreateTime(new Date()); amapService.saveLocationRecord(record); // 調(diào)用MyBatis-Plus持久化 } }
下面就是啟動(dòng)類:(首先不要忘記啟動(dòng)類的掃描注解,還有就是本次用到的注解
@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); } }
寫一個(gè)簡單的頁面展示吧
位置你們知道吧,我就不說詳細(xì)了
展示臺(tái)灣省地圖吧(中國一點(diǎn)都不能少)
下面就是展示的代碼,我只不過吧經(jīng)緯度寫成死值了,
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>高德地圖展示測試:臺(tái)灣省臺(tái)北市地圖 - 臺(tái)北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> // 初始化地圖,中心點(diǎn)設(shè)為臺(tái)北市 var map = new AMap.Map('container', { zoom: 14, // 縮放級(jí)別 center: [121.5654, 25.0330], // 臺(tái)北市坐標(biāo) viewMode: '2D' // 2D地圖 }); // 添加標(biāo)記點(diǎn)(臺(tái)北101大樓) var marker = new AMap.Marker({ position: [121.5654, 25.0330], // 臺(tái)北101坐標(biāo) map: map }); // 信息窗口內(nèi)容 var infoWindow = new AMap.InfoWindow({ content: '<div style="padding:5px;">臺(tái)北101大樓</div>', offset: new AMap.Pixel(0, -30) }); infoWindow.open(map, marker.getPosition()); </script> </body> </html>
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
面向?qū)ο蠛兔嫦蜻^程的區(qū)別(動(dòng)力節(jié)點(diǎn)java學(xué)院整理)
很多朋友不清楚面向?qū)ο蠛兔嫦蜻^程有什么區(qū)別,接下來小編給大家整理了關(guān)于面向?qū)ο蠛兔嫦蜻^程的區(qū)別講解,感興趣的朋友可以參考下2017-04-04SpringBoot+Redis+Lua分布式限流的實(shí)現(xiàn)
本文主要介紹了SpringBoot+Redis+Lua分布式限流的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-08-08Springboot項(xiàng)目啟動(dòng)成功后可通過五種方式繼續(xù)執(zhí)行
本文主要介紹了Springboot項(xiàng)目啟動(dòng)成功后可通過五種方式繼續(xù)執(zhí)行,主要包括CommandLineRunner接口,ApplicationRunner接口,ApplicationListener接口,@PostConstruct注解,InitalizingBean接口,感興趣的可以了解一下2023-12-12SpringBoot項(xiàng)目啟動(dòng)數(shù)據(jù)加載內(nèi)存的三種方法
一般來說,SpringBoot工程環(huán)境配置放在properties文件中,啟動(dòng)的時(shí)候?qū)⒐こ讨械膒roperties/yaml文件的配置項(xiàng)加載到內(nèi)存中,本文給大家介紹了SpringBoot項(xiàng)目啟動(dòng)數(shù)據(jù)加載內(nèi)存中的三種方法,需要的朋友可以參考下2024-04-04java中JsonObject與JsonArray轉(zhuǎn)換方法實(shí)例
在項(xiàng)目日常開發(fā)中常常會(huì)遇到JSONArray和JSONObject的轉(zhuǎn)換,很多公司剛?cè)肼毜男∶刃聲?huì)卡在這里,下面這篇文章主要給大家介紹了關(guān)于java中JsonObject與JsonArray轉(zhuǎn)換方法的相關(guān)資料,需要的朋友可以參考下2023-04-04Spring AOP里的靜態(tài)代理和動(dòng)態(tài)代理用法詳解
這篇文章主要介紹了 Spring AOP里的靜態(tài)代理和動(dòng)態(tài)代理用法詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-07-07