SpringBoot拉取高德行政区域数据

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

相关推荐
悟空码字5 小时前
Spring Boot 整合 MongoDB 最佳实践:CRUD、分页、事务、索引全覆盖
java·spring boot·后端
皮皮林5512 天前
拒绝写重复代码,试试这套开源的 SpringBoot 组件,效率翻倍~
java·spring boot
用户908324602734 天前
Spring AI 1.1.2 + Neo4j:用知识图谱增强 RAG 检索(上篇:图谱构建)
java·spring boot
用户8307196840825 天前
Spring Boot 集成 RabbitMQ :8 个最佳实践,杜绝消息丢失与队列阻塞
spring boot·后端·rabbitmq
Java水解5 天前
Spring Boot 视图层与模板引擎
spring boot·后端
Java水解5 天前
一文搞懂 Spring Boot 默认数据库连接池 HikariCP
spring boot·后端
洋洋技术笔记5 天前
Spring Boot Web MVC配置详解
spring boot·后端
初次攀爬者6 天前
Kafka 基础介绍
spring boot·kafka·消息队列
用户8307196840826 天前
spring ai alibaba + nacos +mcp 实现mcp服务负载均衡调用实战
spring boot·spring·mcp
Java水解6 天前
SpringBoot3全栈开发实战:从入门到精通的完整指南
spring boot·后端