一、数据来源:高德开发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 {@ResourceDistrictService 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 {@ResourceDistrictMapper 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都交由用户自行定义)// 先设置所有一级的区域idfor (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);}}@Overridepublic 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);}}}
}

五、大功告成⛏

获取中国省、市、区数据(调用高德API)-编程知识网

附录-补充信息

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("请求成功");}
}