java调用百度地图api获取所有省市区街道信息-即拿即用

本文主要实现了获取省市区以及省市区信息落库。避免重复代码(主要代码在下文),文章末尾有使用场景说明。

一、百度地图api文档

行政区域api文档链接

响应示例

在使用百度API获取省市区内容时,我们需要注意以下几点。首先,确保您的API密钥安全,不要将其泄露给未经授权的人员。其次,遵守百度API的使用规则,不要进行恶意请求或滥用API资源。最后,对于获取到的省市区数据,我们需要注意数据的准确性和完整性,以确保我们的应用程序能够正确地处理和使用这些数据。

二、获取省市区工具类

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.util.UriUtils;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.security.NoSuchAlgorithmException;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@Slf4j
public class BaiduMapUtil {// 用户服务访问密钥
    public static String AK = "******";
	// 用于生成请求url
    public static String SK = "*******";
	
    public static String URL = "https://api.map.baidu.com/api_region_search/v1/?";
    public static void main(String[] args) throws Exception { BaiduMapUtil snCal = new BaiduMapUtil();
        Map paramsMap = new LinkedHashMap();
//        paramsMap.put("keyword", "石家庄市");
        paramsMap.put("keyword", "中国");
        paramsMap.put("sub_admin", "4");
        paramsMap.put("extensions_code", "1");
        System.out.println(JSONUtil.toJsonStr(snCal.requestGetSN(paramsMap)));
    }
    public static List requestGetSN(Map param) throws Exception { param.put("ak", AK);
        param.put("sn", caculateSn(param));
        return requestGetSN(URL, param);
    }
    /**
     * 选择了ak,使用SN校验:
     * 根据您选择的AK已为您生成调用代码
     * 检测您当前的AK设置了sn检验,本示例中已为您生成sn计算代码
     * @param strUrl
     * @param param
     * @throws Exception
     */
    public static List requestGetSN(String strUrl, Map param) throws Exception { if (strUrl == null || strUrl.length() <= 0 || param == null || param.size() <= 0) { return null;
        }
        StringBuffer queryString = new StringBuffer();
        queryString.append(strUrl);
        for (Map.Entry pair : param.entrySet()) { queryString.append(pair.getKey() + "=");
            //    第一种方式使用的 jdk 自带的转码方式  第二种方式使用的 spring 的转码方法 两种均可
            //    queryString.append(URLEncoder.encode((String) pair.getValue(), "UTF-8").replace("+", "%20") + "&");
            queryString.append(UriUtils.encode((String) pair.getValue(), "UTF-8") + "&");
        }
        if (queryString.length() > 0) { queryString.deleteCharAt(queryString.length() - 1);
        }
        URL url = new URL(queryString.toString());
        log.info("请求百度地区url:{}",queryString);
        URLConnection httpConnection = url.openConnection();
        httpConnection.connect();
        InputStreamReader isr = new InputStreamReader(httpConnection.getInputStream());
        BufferedReader reader = new BufferedReader(isr);
        StringBuffer buffer = new StringBuffer();
        String line;
        while ((line = reader.readLine()) != null) { buffer.append(line);
        }
        reader.close();
        isr.close();
        JSONObject jsonObject = JSONUtil.parseObj(buffer.toString());
        Object status = jsonObject.get("status");
        if (status == null || Convert.toInt(status)!=0) { log.info("获取百度地区失败:{}",buffer);
            return null;
        }
        JSONArray districts = jsonObject.getJSONArray("districts");
        return BeanUtil.copyToList(districts, BaiduMapVO.class);
    }
    public static String caculateSn(Map paramsMap) throws UnsupportedEncodingException,
            NoSuchAlgorithmException { BaiduMapUtil snCal = new BaiduMapUtil();
        // 计算sn跟参数对出现顺序有关,get请求请使用LinkedHashMap保存,该方法根据key的插入顺序排序;post请使用TreeMap保存,该方法会自动将key按照字母a-z顺序排序。
        // 所以get请求可自定义参数顺序(sn参数必须在最后)发送请求,但是post请求必须按照字母a-z顺序填充body(sn参数必须在最后)。
        // 以get请求为例:http://api.map.baidu.com/geocoder/v2/?address=百度大厦&output=json&ak=yourak,paramsMap中先放入address,再放output,然后放ak,放入顺序必须跟get请求中对应参数的出现顺序保持一致。
        //paramsMap
        // 调用下面的toQueryString方法,对LinkedHashMap内所有value作utf8编码,拼接返回结果address=%E7%99%BE%E5%BA%A6%E5%A4%A7%E5%8E%A6&output=json&ak=yourak
        String paramsStr = snCal.toQueryString(paramsMap);
        // 对paramsStr前面拼接上/geocoder/v2/?,后面直接拼接yoursk得到/geocoder/v2/?address=%E7%99%BE%E5%BA%A6%E5%A4%A7%E5%8E%A6&output=json&ak=yourakyoursk
        String wholeStr = new String("/api_region_search/v1/?" + paramsStr + SK);
        System.out.println(wholeStr);
        // 对上面wholeStr再作utf8编码
        String tempStr = URLEncoder.encode(wholeStr, "UTF-8");
        // 调用下面的MD5方法得到最后的sn签名
        String sn = snCal.MD5(tempStr);
        System.out.println(sn);
        return sn;
    }
    // 对Map内所有value作utf8编码,拼接返回结果
    public String toQueryString(Map data)
            throws UnsupportedEncodingException { StringBuffer queryString = new StringBuffer();
        for (Map.Entry pair : data.entrySet()) { queryString.append(pair.getKey() + "=");
            //    第一种方式使用的 jdk 自带的转码方式  第二种方式使用的 spring 的转码方法 两种均可
            //    queryString.append(URLEncoder.encode((String) pair.getValue(), "UTF-8").replace("+", "%20") + "&");
            queryString.append(UriUtils.encode((String) pair.getValue(), "UTF-8") + "&");
        }
        if (queryString.length() > 0) { queryString.deleteCharAt(queryString.length() - 1);
        }
        return queryString.toString();
    }
    // 来自stackoverflow的MD5计算方法,调用了MessageDigest库函数,并把byte数组结果转换成16进制
    public String MD5(String md5) { try { java.security.MessageDigest md = java.security.MessageDigest
                    .getInstance("MD5");
            byte[] array = md.digest(md5.getBytes());
            StringBuffer sb = new StringBuffer();
            for (int i = 0; i < array.length; ++i) { sb.append(Integer.toHexString((array[i] & 0xFF) | 0x100)
                        .substring(1, 3));
            }
            return sb.toString();
        } catch (NoSuchAlgorithmException e) { }
        return null;
    }
}

三、pojo对象

@Data
public class BaiduMapVO { private String code;
    private String name;
    private String level;
    private List districts;
}
@Data
@TableName("area")
public class area implements Serializable {private static final long serialVersionUID = 1L;
	/**
	 * 区域id
	 */
	private String areaId;
	/**
	 * 区域名称
	 */
	private String areaName;
	
	/**
	 * 层级(0国,1 省,2 市,3 区,4 街道)
	 */
	private Integer level;
	/**
	 * 上级区域Id
	 */
	private String parentId;
}

四、落库逻辑

@Slf4j
public class AreaService  { public static void main(String[] args) { syncArea();
    }
    public static Boolean syncArea() { Map params = new LinkedHashMap();
        params.put("keyword", "中国");
        params.put("sub_admin", "4");
        params.put("extensions_code", "1");
        try { List baiduMapVOList = BaiduMapUtil.requestGetSN(params);
            fillArea(baiduMapVOList);
        } catch (Exception e) { e.printStackTrace();
            log.info("同步异常:{}",e.getMessage());
            return Boolean.FALSE;
        }
        return Boolean.TRUE;
    }
    private static void fillArea(List baiduMapVOList) { for (BaiduMapVO baiduMapVO : baiduMapVOList) { saveArea(null,baiduMapVO);
        }
    }
	
	// 递归写入/输出
    private static void saveArea(String parentId, BaiduMapVO baiduMapVO) { SysArea area = new SysArea();
        String areaId = baiduMapVO.getCode();
        area.setAreaId(areaId);
        area.setAreaName(baiduMapVO.getName());
        area.setLevel(Convert.toInt(baiduMapVO.getLevel()));
        area.setParentId(parentId);
        //todo 落库逻辑
//        saveOrUpdate(area);
//        log.info("area:{}",area);
        List districts = baiduMapVO.getDistricts();
        if (CollUtil.isNotEmpty(districts)){ for (BaiduMapVO mapVO : districts) { saveArea(areaId,mapVO);
            }
        }
    }
}

五、应用场景

①物流配送:在物流领域,省市区信息是实现精确配送的基础。通过输入收货地址的省市区信息,物流公司可以准确地计算出配送路线,提高配送效率,减少错误和延误。

②电商平台:电商平台在用户注册或购买商品时,通常需要用户输入收货地址的省市区信息。通过获取这些信息,电商平台可以为用户提供更加精准的商品推荐和物流服务,提高用户满意度。

③人口普查和统计:政府机构或企事业单位在进行人口普查、统计或调查时,需要获取详细的行政区划信息。通过省市区查询API接口,可以快速、准确地获取这些信息,提高工作效率和数据准确性。

④地理信息系统:在地理信息系统中,省市区信息是构建地理数据库的基础。通过获取这些信息,可以实现地图绘制、位置查询、路径规划等功能,为各种应用提供地理数据支持。

⑤房地产平台:房地产平台通常需要展示房产的地理位置和周边环境。通过获取省市区信息,可以为用户提供更加详细的房产信息和位置展示,帮助用户更好地了解房产情况。

六、结尾

将这些省市区信息进行落库后,可以定时进行一个同步更新,当然这类地区内容基本上短时间是不会有太大的变动的。

非常感谢您花时间阅读本文,希望我的内容对您有所帮助。如果您觉得本文对您有帮助,用您发财的小手点赞和收藏以下吧,您的支持就是作者最大的动力。