一、数据来源:高德开发API(后端调用接口实现数据落库)

行政区域查询-API文档-开发指南-Web服务 API | 高德地图API

二、需要用到的依赖(只附上主要依赖)

      其他依赖:MybatisPlus、SpringBoot、Mysql、Lombok等(你不会没有吧)

<!--请求工具依赖-->
<dependency>
            <groupId>com.github.kevinsawicki</groupId>
            <artifactId>http-request</artifactId>
            <version>5.6</version>
</dependency>

<!--JSON转换依赖-->
<dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.78</version>
</dependency>

三、类封装

第一个,请求结果工具类(方便数据转换):

package icu.liuwisdom.request.util;

import com.alibaba.fastjson.JSON;
import com.github.kevinsawicki.http.HttpRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.Map;

/**
 * Http请求工具
 *
 * @author LDB
 * @version 1.0
 * @date 2022-07-25 15:10
 */
@Slf4j
@Component
public class HttpRequestUtil {

    /**
     * 获取最后请求到的数据
     *
     * @param request 请求后的结果
     * @param c       指定类类型
     * @return T
     * @author LDB
     * @date 2022-07-25
     **/
    public static <T> T getRequestResult(HttpRequest request, Class<T> c) {
        log.info(request.url().toString());
        if (!request.ok()) {
            log.error(request.message());
        }
        return JSON.parseObject(request.body(), c);
    }

}

第二个(因为我们需要用到一些不变的数据,请求key记得替换成自己的):

package icu.liuwisdom.request.gaode.common;

import java.util.Arrays;
import java.util.List;

/**
 * 高德API
 *
 * @author LDB
 * @version 1.0
 * @date 2022-07-25 15:52
 */

public interface GaoDeApi {
    /**
     * 接口地址前缀
     *
     * @author LDB
     * @date 2022-07-25 15:53
     * @version 1.0
     */
    String URL = "https://restapi.amap.com/v3/config/district?key=" + GaoDeApi.KEY + "&subdistrict=3&extensions=base&";

    /**
     * 请求key
     *
     * @author LDB
     * @date 2022-07-25 15:55
     * @version 1.0
     */

    String KEY = "your self key!";

    /**
     * 省份关键字列表
     *
     * @author LDB
     * @date 2022-07-25 22:20
     * @version 1.0
     */
    List<String> keywords = Arrays.asList(new String[]{"河北省", "山西省", "辽宁省", "吉林省", "黑龙江省", "江苏省", "浙江省", "安徽省", "福建省", "江西省", "山东省", "河南省", "湖北省", "湖南省", "广东省", "海南省", "四川省", "贵州省", "云南省", "陕西省", "甘肃省", "青海省", "台湾省", "内蒙古自治区", "广西壮族自治区", "西藏自治区", "宁夏回族自治区", "新疆维吾尔自治区", "北京市", "天津市", "上海市", "重庆市", "香港特别行政区", "澳门特别行政区"});
}

第三个,实体类(po、vo,需要对照高德API给的数据来)

package icu.liuwisdom.request.gaode;

import lombok.Data;

/**
 * 高德数据结果
 *
 * @author LDB
 * @version 1.0
 * @date 2022-07-25 15:56
 */
@Data
public class GaoResult {
    /**
     * 返回结果状态值
     *
     * @author LDB
     * @date 2022-07-25 22:12
     * @version 1.0
     */

    private String status;
    /**
     * 返回状态说明
     *
     * @author LDB
     * @date 2022-07-25 22:12
     * @version 1.0
     */

    private String info;
    /**
     * 状态码
     *
     * @author LDB
     * @date 2022-07-25 22:12
     * @version 1.0
     */
    private String infocode;
    /**
     * 查询个数
     *
     * @author LDB
     * @date 2022-07-25 22:29
     * @version 1.0
     */
    private String count;

}
package icu.liuwisdom.request.gaode.vo;

import icu.liuwisdom.request.gaode.GaoResult;
import icu.liuwisdom.request.gaode.po.District;
import icu.liuwisdom.request.gaode.po.Districts;
import icu.liuwisdom.request.gaode.po.Suggestion;
import lombok.Data;

import java.util.ArrayList;
import java.util.List;

/**
 * 区域Vo
 *
 * @author LDB
 * @version 1.0
 * @date 2022-07-25 22:28
 */
@Data
public class DistrictsVo extends GaoResult {
    /**
     * 建议结果
     *
     * @author LDB
     * @date 2022-07-25 22:30
     * @version 1.0
     */
    private Suggestion suggestion;

    /**
     * 行政区列表
     *
     * @author LDB
     * @date 2022-07-25 22:32
     * @version 1.0
     */
    private List<Districts> districts = new ArrayList<>();
}
package icu.liuwisdom.request.gaode.po;

import lombok.Data;

import java.util.ArrayList;
import java.util.List;

/**
 * 建议结果列表
 *
 * @author LDB
 * @version 1.0
 * @date 2022-07-25 22:22
 */
@Data
public class Suggestion {
    /**
     * 建议关键字列表
     *
     * @author LDB
     * @date 2022-07-25 22:23
     * @version 1.0
     */

    List<String> keywords = new ArrayList<>();

    /**
     * 建议城市列表
     *
     * @author LDB
     * @date 2022-07-25 22:23
     * @version 1.0
     */

    List<String> cites = new ArrayList<>();
}
package icu.liuwisdom.request.gaode.po;

import icu.liuwisdom.core.modal.BaseModel;
import lombok.Data;

/**
 * 行政区信息
 *
 * @author LDB
 * @version 1.0
 * @date 2022-07-25 22:25
 */
@Data
public class District extends BaseModel {
    /**
     * 主键id
     *
     * @author LDB
     * @date 2022-07-25 22:46
     * @version 1.0
     */

    private String id;
    /**
     * 上级id
     *
     * @author LDB
     * @date 2022-07-25 22:46
     * @version 1.0
     */

    private String parentId;
    /**
     * 城市编码
     *
     * @author LDB
     * @date 2022-07-25 22:25
     * @version 1.0
     */
    private String cityCode;
    /**
     * 区域编码
     *
     * @author LDB
     * @date 2022-07-25 22:25
     * @version 1.0
     */

    private String adcode;
    /**
     * 行政区名称
     *
     * @author LDB
     * @date 2022-07-25 22:26
     * @version 1.0
     */

    private String name;
    /**
     * 行政区边界坐标点
     *
     * @author LDB
     * @date 2022-07-25 22:26
     * @version 1.0
     */

    private String polyline;
    /**
     * 区域中心点
     *
     * @author LDB
     * @date 2022-07-25 22:26
     * @version 1.0
     */

    private String center;

    /**
     * 行政区划级别
     * <p>
     * <p>
     * country:国家  province:省份(直辖市会在province和city显示) city:市(直辖市会在province和city显示) district:区县 street:街道
     * <p>
     *
     * <p>
     *
     * <p>
     *
     * <p>
     *
     * @author LDB
     * @date 2022-07-25 22:27
     * @version 1.0
     */

    private String level;


    public Districts toVo() {
        Districts vo = new Districts();
        vo.setId(this.id);
        vo.setParentId(this.parentId);
        vo.setCityCode(this.cityCode);
        vo.setAdcode(this.adcode);
        vo.setName(this.name);
        vo.setPolyline(this.polyline);
        vo.setCenter(this.center);
        vo.setLevel(this.level);
        return vo;
    }
}
package icu.liuwisdom.request.gaode.po;

import icu.liuwisdom.core.modal.BaseModel;
import lombok.Data;

import java.util.ArrayList;
import java.util.List;

/**
 * 行政区信息
 *
 * @author LDB
 * @version 1.0
 * @date 2022-07-25 22:25
 */
@Data
public class Districts extends BaseModel {
    /**
     * 主键id
     *
     * @author LDB
     * @date 2022-07-25 22:46
     * @version 1.0
     */

    private String id;
    /**
     * 上级id
     *
     * @author LDB
     * @date 2022-07-25 22:46
     * @version 1.0
     */

    private String parentId;
    /**
     * 城市编码
     *
     * @author LDB
     * @date 2022-07-25 22:25
     * @version 1.0
     */
    private String cityCode;
    /**
     * 区域编码
     *
     * @author LDB
     * @date 2022-07-25 22:25
     * @version 1.0
     */

    private String adcode;
    /**
     * 行政区名称
     *
     * @author LDB
     * @date 2022-07-25 22:26
     * @version 1.0
     */

    private String name;
    /**
     * 行政区边界坐标点
     *
     * @author LDB
     * @date 2022-07-25 22:26
     * @version 1.0
     */

    private String polyline;
    /**
     * 区域中心点
     *
     * @author LDB
     * @date 2022-07-25 22:26
     * @version 1.0
     */

    private String center;

    /**
     * 行政区划级别
     * <p>
     * <p>
     * country:国家  province:省份(直辖市会在province和city显示) city:市(直辖市会在province和city显示) district:区县 street:街道
     * <p>
     *
     * <p>
     *
     * <p>
     *
     * <p>
     *
     * @author LDB
     * @date 2022-07-25 22:27
     * @version 1.0
     */

    private String level;

    /**
     * 下级行政区列表,包含district元素
     *
     * @author LDB
     * @date 2022-07-25 22:28
     * @version 1.0
     */

    private List<Districts> districts = new ArrayList<>();


    public District toPo() {
        District po = new District();
        po.setId(this.id);
        po.setParentId(this.parentId);
        po.setAdcode(this.adcode);
        po.setCityCode(this.cityCode);
        po.setLevel(this.level);
        po.setPolyline(this.polyline);
        po.setCenter(this.center);
        po.setName(this.name);
        return po;
    }
}

差点忘了,还有一个uuid类

package icu.liuwisdom.utils;

import java.util.UUID;

/**
 * UUID工具类
 * */
public class IdUtils {

    public static String getUUID() {
        String id = UUID.randomUUID().toString();
        String[] split = id.split("-");
        String res = new String();
        for (String s : split) {
            res += s;
        }
        return res;
    }
}

四、数据库设计

CREATE TABLE `district` (
  `id` varchar(32) DEFAULT NULL COMMENT '编号',
  `parent_id` varchar(32) DEFAULT NULL COMMENT '上级行政区id',
  `city_code` varchar(500) DEFAULT NULL COMMENT '城市编码',
  `adcode` varchar(500) DEFAULT NULL COMMENT '区域编码',
  `name` varchar(500) DEFAULT NULL COMMENT '行政区名称',
  `polyline` varchar(5000) DEFAULT NULL COMMENT '行政区边界坐标点',
  `center` varchar(500) DEFAULT NULL COMMENT '区域中心点',
  `level` varchar(100) DEFAULT NULL COMMENT '行政区划级别 country:国家  province:省份(直辖市会在province和city显示) city:市(直辖市会在province和city显示) district:区县 street:街道',
  `create_by` varchar(50) DEFAULT NULL COMMENT '创建人',
  `create_time` datetime DEFAULT NULL COMMENT '创建时间',
  `last_update_by` varchar(50) DEFAULT NULL COMMENT '更新人',
  `last_update_time` datetime DEFAULT NULL COMMENT '更新时间',
  `remarks` varchar(255) DEFAULT NULL COMMENT '备注信息',
  `del_flag` tinyint(4) DEFAULT '0' COMMENT '是否删除  -1:已删除  0:正常',
  KEY `index_1` (`id`),
  KEY `index_2` (`parent_id`),
  KEY `index_3` (`parent_id`),
  KEY `index_4` (`level`),
  KEY `index_5` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='省份区域信息表';

四、核心代码

好啦,准备工作已经做完了,核心思路就是:按照省份关键字来循环调用接口,将获取到的数据新增到自己的数据库中,因为需要区分上下级关系,所以id由咱自己定!

package icu.liuwisdom.request.gaode.controller;


import com.github.kevinsawicki.http.HttpRequest;
import icu.liuwisdom.core.http.HttpResult;
import icu.liuwisdom.request.gaode.common.GaoDeApi;
import icu.liuwisdom.request.gaode.query.DistrictQuery;
import icu.liuwisdom.request.gaode.service.DistrictService;
import icu.liuwisdom.request.gaode.vo.DistrictsVo;
import icu.liuwisdom.request.util.HttpRequestUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.val;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;

/**
 * <p>
 * 省份区域信息表 前端控制器
 * </p>
 *
 * @author ldb
 * @since 2022-07-25
 */
@RestController
@Api(tags = "省份区域信息")
@RequestMapping("request/district")
public class DistrictController {
    @Resource
    DistrictService districtService;

    @ApiOperation("请求省市区数据")
    @GetMapping("/")
    public HttpResult get() {
        val city = GaoDeApi.keywords;
        for (String c : city) {
            DistrictsVo vo = HttpRequestUtil.getRequestResult(HttpRequest.get(GaoDeApi.URL + "keywords=" + c), DistrictsVo.class);
            districtService.insert(vo);
        }
        return HttpResult.ok("获取省市区数据成功");
    }

    @ApiOperation("获取省市区")
    @PostMapping("/tree")
    public HttpResult post(@RequestBody DistrictQuery query) {
        return HttpResult.ok("获取省市区成功", districtService.tree(query));
    }
}
package icu.liuwisdom.request.gaode.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import icu.liuwisdom.request.gaode.mapper.DistrictMapper;
import icu.liuwisdom.request.gaode.po.District;
import icu.liuwisdom.request.gaode.po.Districts;
import icu.liuwisdom.request.gaode.query.DistrictQuery;
import icu.liuwisdom.request.gaode.service.DistrictService;
import icu.liuwisdom.request.gaode.vo.DistrictsVo;
import icu.liuwisdom.utils.IdUtils;
import lombok.val;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * <p>
 * 省份区域信息表 服务实现类
 * </p>
 *
 * @author ldb
 * @since 2022-07-25
 */
@Service
public class DistrictServiceImpl extends ServiceImpl<DistrictMapper, District> implements DistrictService {
    @Resource
    DistrictMapper mapper;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void insert(DistrictsVo vo) {
        // 请求到的数据为空
        if (Objects.isNull(vo)) {
            return;
        }
        // 获取区域信息
        List<Districts> districts = vo.getDistricts();
        List<Districts> districtList = new ArrayList<>();
        // 递归传入父id(所有id都交由用户自行定义)
        // 先设置所有一级的区域id
        for (Districts district : districts) {
            val parentId = IdUtils.getUUID();
            district.setId(parentId);
            // 如果有子区域,则递归设置
            if (!district.getDistricts().isEmpty()) {
                injectId(district.getDistricts(), parentId, districtList);
            }
            districtList.add(district);
        }
        if (!districtList.isEmpty()) {
            List<District> list = districtList.stream().map(val -> val.toPo()).collect(Collectors.toList());
            this.saveBatch(list);
        }
    }

    @Override
    public List<District> tree(DistrictQuery query) {
        PageHelper.startPage(query.getPageNum(), query.getPageSize());
        val wrapper = new LambdaQueryWrapper<District>()
                .eq(StringUtils.isNotEmpty(query.getId()), District::getId, query.getId())
                .eq(StringUtils.isNotEmpty(query.getParentId()), District::getParentId, query.getParentId())
                .eq(StringUtils.isNotEmpty(query.getCityCode()), District::getCityCode, query.getCityCode())
                .eq(StringUtils.isNotEmpty(query.getAdcode()), District::getAdcode, query.getAdcode())
                .like(StringUtils.isNotEmpty(query.getName()), District::getName, query.getName())
                .like(StringUtils.isNotEmpty(query.getPolyline()), District::getPolyline, query.getPolyline())
                .like(StringUtils.isNotEmpty(query.getCenter()), District::getCenter, query.getCenter())
                .eq(StringUtils.isNotEmpty(query.getLevel()), District::getLevel, query.getLevel());
        return mapper.selectList(wrapper);
    }


    /**
     * 生成子区域id数据
     *
     * @param districts    子区域列表
     * @param parentId     父id
     * @param districtList 要新增的区域数据列表
     * @author LDB
     * @date 2022-07-25
     **/
    private void injectId(List<Districts> districts, String parentId, List<Districts> districtList) {
        for (Districts district : districts) {
            String currentId = IdUtils.getUUID();
            district.setId(currentId);
            district.setParentId(parentId);
            districtList.add(district);
            if (!district.getDistricts().isEmpty()) {
                injectId(district.getDistricts(), currentId, districtList);
            }
        }
    }
}

五、大功告成⛏

java获取高德地图省份信息 高德获取省市区_spring

附录-补充信息

package icu.liuwisdom.core.page;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import java.io.Serializable;
import java.util.List;

/**
 * 分页请求对象
 *
 * @author ldb
 * @ClassName PageRequest.java
 * @Data 2022-02-19 15:10
 */
@Data
@ApiModel("分页请求对象")
public class PageRequest implements Serializable {

    @ApiModelProperty("页码")
    private int pageNum = 1;

    @ApiModelProperty("页数")
    private int pageSize = 10;

    @ApiModelProperty("关键字")
    private String keyword;

    @ApiModelProperty("多个状态值,根据多个条件查询时用到 比如:1,2,3")
    private String dataStates;

    @ApiModelProperty(value = "主表id,一对多分页使用", hidden = true)
    private List<String> ids;
}
package icu.liuwisdom.core.http;

import icu.liuwisdom.constant.ErrorCode;
import icu.liuwisdom.constant.SystemConstant;
import icu.liuwisdom.utils.DateUtils;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.format.annotation.DateTimeFormat;

import java.time.LocalDateTime;

/**
 * 请求结果封装类
 *
 * @author ldb
 * @ClassName HttpResult.java
 * @Data 2022-02-19 15:48
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
@ApiModel("请求结果封装类")
public class HttpResult<T> {
    @ApiModelProperty("响应码")
    private int code;

    @ApiModelProperty("响应消息")
    private String msg;

    @ApiModelProperty("响应数据")
    private T data;

    @ApiModelProperty("响应时间")
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime time;

    public static HttpResult<Boolean> error() {
        return error(666, "请求失败");
    }

    public static HttpResult<Boolean> error(String msg) {
        return error(666, msg);
    }

    public static HttpResult<Boolean> error(int code, String msg) {
        return new HttpResult(code, msg, false, LocalDateTime.now());
    }

    public static HttpResult<Boolean> ok(String msg) {
        return new HttpResult(200, msg, true, LocalDateTime.now());
    }

    public static <D> HttpResult<D> ok(String msg, D data) {
        return new HttpResult<D>(200, msg, data, LocalDateTime.now());
    }

    public static <D> HttpResult<D> ok(D data) {
        return new HttpResult<D>(200, "请求成功", data, LocalDateTime.now());
    }

    public static HttpResult<Boolean> ok() {
        return ok("请求成功");
    }
}