SpringBoot拉取高德行政区域数据
一、账号申请
1.整体流程
行政区域文档:https://lbs.amap.com/api/webservice/guide/api/district
整体流程可参考:https://lbs.amap.com/api/webservice/guide/create-project/get-key
2.注册账号
注册地址:https://console.amap.com/dev/id/phone
3.创建应用
地址:https://console.amap.com/dev/key/app
4.申请key
请勾选web服务
二、核心代码
核心代码如下
- 目前使用spring定时任务去拉取数据
- 五级行政区域:国家、省、市、区、街道
- 包括上下级关系、行政区划代码、经纬度信息
java
package com.qiangesoft.district.gaode;
import com.qiangesoft.district.entity.SysArea;
import com.qiangesoft.district.gaode.constant.RegionLevelEnum;
import com.qiangesoft.district.gaode.model.District;
import com.qiangesoft.district.gaode.model.DistrictConstant;
import com.qiangesoft.district.gaode.model.GaoDeDistrictResult;
import com.qiangesoft.district.service.ISysAreaService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.web.client.RestTemplate;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
/**
* 区域数据
*
* @author qiangesoft
* @date 2023-07-18
*/
@Slf4j
@Component
public class AreaTask {
@Autowired
private RestTemplate restTemplate;
@Autowired
private ISysAreaService sysAreaService;
/**
* 每天10点执行一次
*/
@Scheduled(cron = "0 0 10 * * ?")
public void pullArea() {
log.info("Update area data begin==================>");
long startTime = System.currentTimeMillis();
StringBuilder sendUrl = new StringBuilder(DistrictConstant.DISTRICT_URL)
.append("?key=").append(GaoDeApi.KEY_VALUE)
.append("&keywords=").append(DistrictConstant.ZQ_KEYWORD_VALUE)
.append("&subdistrict=4&extensions=base");
ResponseEntity<GaoDeDistrictResult> responseEntity = restTemplate.getForEntity(sendUrl.toString(), GaoDeDistrictResult.class);
// 请求异常,可能由于网络等原因
HttpStatus statusCode = responseEntity.getStatusCode();
if (!HttpStatus.OK.equals(statusCode)) {
log.info("Request for Gaode interface error");
return;
}
// 请求失败
GaoDeDistrictResult gaoDeDistrictResult = responseEntity.getBody();
String status = gaoDeDistrictResult.getStatus();
if (!status.equals(GaoDeApi.SUCCESS)) {
log.info("Request for Gaode interface failed");
return;
}
// 请求无数据
List<District> districts = gaoDeDistrictResult.getDistricts();
if (CollectionUtils.isEmpty(districts)) {
log.info("Request for Gaode interface no data");
return;
}
// 保存数据
this.saveData(districts, null);
long endTime = System.currentTimeMillis();
log.info("spend time:" + (endTime - startTime));
log.info("Update area data end<==================");
}
/**
* 保存数据
*
* @param districts
* @param parentId
*/
private void saveData(List<District> districts, Long parentId) {
if (CollectionUtils.isEmpty(districts)) {
return;
}
// 排序
districts.sort(Comparator.comparing(District::getAdcode));
// 国家一级特殊处理
if (parentId == null) {
districts = districts.stream().filter(e -> RegionLevelEnum.COUNTRY.getCode().equals(e.getLevel())).collect(Collectors.toList());
}
// 执行保存
List<SysArea> areaList = new ArrayList<>();
for (District district : districts) {
SysArea sysArea = new SysArea();
sysArea.setCode(district.getAdcode());
sysArea.setAreaCode(district.getCitycode().toString());
sysArea.setName(district.getName());
sysArea.setFullName(district.getName());
sysArea.setSortValue(1);
String center2 = district.getCenter();
if (StringUtils.isNotBlank(center2)) {
String[] split = center2.split(",");
sysArea.setLongitude(split[0]);
sysArea.setLatitude(split[1]);
}
String level = RegionLevelEnum.getCodeByDes(district.getLevel());
sysArea.setLevel(level);
sysArea.setDelFlag(false);
sysArea.setParentId(parentId);
areaList.add(sysArea);
}
sysAreaService.saveBatch(areaList);
// 下级
for (int i = 0; i < districts.size(); i++) {
District district = districts.get(i);
List<District> children = district.getDistricts();
if (!CollectionUtils.isEmpty(children)) {
this.saveData(children, areaList.get(i).getId());
}
}
}
}
java
package com.qiangesoft.district.gaode.model;
import java.util.Arrays;
import java.util.List;
/**
* 行政区划常量
*
* @author qiangesoft
* @date 2023-08-10
*/
public class DistrictConstant {
/**
* 行政区划接口地址
*/
public static final String DISTRICT_URL = "https://restapi.amap.com/v3/config/district";
/**
* key
*/
public static final String KEY = "key";
/**
* 搜索关键词支持:行政区名称、citycode、adcode
*/
public static final String KEYWORDS = "keywords";
/**
* 子级行政区
* 可选值:0、1、2、3等数字,并以此类推
* 0:不返回下级行政区;
* 1:返回下一级行政区;
* 2:返回下两级行政区;
* 3:返回下三级行政区;
*/
public static final String SUBDISTRICT = "subdistrict";
/**
* 需要第几页数据
*/
public static final String PAGE = "page";
/**
* 最外层返回数据个数
*/
public static final String OFFSET = "offset";
/**
* 此项控制行政区信息中返回行政区边界坐标点; 可选值:base、all;
* base:不返回行政区边界坐标点;
* all:只返回当前查询district的边界值,不返回子节点的边界值;
*/
public static final String EXTENSIONS = "extensions";
/**
* 按照指定行政区划进行过滤,填入后则只返回该省/直辖市信息
* 填入adcode,为了保证数据的正确,强烈建议填入此参数
*/
public static final String FILTER = "filter";
/**
* callback值是用户定义的函数名称,此参数只在output=JSON时有效
*/
public static final String CALLBACK = "callback";
/**
* 可选值:JSON,XML
*/
public static final String OUTPUT = "output";
/**
* 省份关键字列表
*/
public static final List<String> ZQ_KEYWORD_VALUE = Arrays.asList("中华人民共和国");
public static final List<String> KEYWORDS_VALUE = Arrays.asList("河北省", "山西省", "辽宁省", "吉林省", "黑龙江省", "江苏省", "浙江省", "安徽省", "福建省",
"江西省", "山东省", "河南省", "湖北省", "湖南省", "广东省", "海南省", "四川省", "贵州省", "云南省", "陕西省", "甘肃省", "青海省", "台湾省",
"内蒙古自治区", "广西壮族自治区", "西藏自治区", "宁夏回族自治区", "新疆维吾尔自治区", "北京市", "天津市", "上海市", "重庆市", "香港特别行政区", "澳门特别行政区");
/**
* 香港澳门台湾特殊处理
*/
public static final List<String> TSKEYWORDS_VALUE = Arrays.asList("台湾省", "香港特别行政区", "澳门特别行政区");
}
java
package com.qiangesoft.district.gaode;
/**
* 高德API
*
* @author qiangesoft
* @date 2023-07-18
*/
public class GaoDeApi {
/**
* 成功标志
*/
public static final String SUCCESS = "1";
/**
* 请求key
*/
public static final String KEY_VALUE = "eea81fd695ceeda7bdab6d3e98ecc2ed";
}
java
package com.qiangesoft.district.gaode.model;
import lombok.Data;
import java.util.List;
/**
* 高德数据结果
*
* @author qiangesoft
* @date 2023-07-18
*/
@Data
public class GaoDeDistrictResult {
/**
* 返回结果状态值
*/
private String status;
/**
* 返回状态说明
*/
private String info;
/**
* 状态码
*/
private String infocode;
/**
* 查询个数
*/
private String count;
/**
* 建议结果列表
*/
private Suggestion suggestion;
/**
* 区域信息
*/
private List<District> districts;
}
java
package com.qiangesoft.district.gaode.model;
import lombok.Data;
import java.util.List;
/**
* 行政区信息
*
* @author qiangesoft
* @date 2023-07-18
*/
@Data
public class District {
/**
* 城市编码
*/
private Object citycode;
/**
* 区域编码
*/
private String adcode;
/**
* 行政区名称
*/
private String name;
/**
* 行政区边界坐标点
*/
private String polyline;
/**
* 区域中心点
*/
private String center;
/**
* 行政区划级别
* country:国家
* province:省份(直辖市会在province和city显示)
* city:市(直辖市会在province和city显示)
* district:区县
* street:街道
*/
private String level;
/**
* 下级区域
*/
private List<District> districts;
}
java
package com.qiangesoft.district.entity;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
import java.util.Date;
/**
* 地区对象 sys_area
*
* @author qiangesoft
* @date 2023-04-25
*/
@Data
@EqualsAndHashCode(callSuper = false)
public class SysArea implements Serializable {
private static final long serialVersionUID = 1L;
/**
* id
*/
private Long id;
/**
* 行政级别
*/
@TableField(value = "level_")
private String level;
/**
* 父ID
*/
private Long parentId;
/**
* 行政区划代码
*/
private String code;
/**
* 区号
*/
private String areaCode;
/**
* 名称
*/
private String name;
/**
* 全名
*/
private String fullName;
/**
* 排序
*/
private Integer sortValue;
/**
* 经度
*/
private String longitude;
/**
* 维度
*/
private String latitude;
/**
* 删除标志
*/
private Boolean delFlag;
/**
* 创建时间
*/
@TableField(fill = FieldFill.INSERT)
private Date createTime;
/**
* 创建人
*/
@TableField(fill = FieldFill.INSERT)
private Long createBy;
/**
* 更新时间
*/
@TableField(fill = FieldFill.UPDATE)
private Date updateTime;
/**
* 更新人
*/
@TableField(fill = FieldFill.UPDATE)
private Long updateBy;
}
三、源码仓库
源码地址:https://gitee.com/qiangesoft/boot-business/tree/master/boot-business-district