java 百度地图API、高德地图API 经纬度 正逆向 地址转换

   在实际业务开发中,可能需要使用到 打卡,签到等功能,则 就需要调用第三方地图API。
   
   百度WebAPI地址:http://lbsyun.baidu.com/index.php?title=webapi/guide/webservice-geocoding-abroad
   
   高德WebAPI地址:https://lbs.amap.com/api/webservice/guide/api/georegeo
   
   代码说明:
         默认使用的时百度API,可以通过修改参数的方式他调整。代码中使用到的经纬度均为百度API对应的经纬度,
         如果切换为高德API,在代码中有将 百度 经纬度转成为 高德 经纬度,特此说明。

配置文件XXX.yml

map:
  # 根据经纬度转换地址的百度API的url
  getAddressByLngAndLat: https://api.map.baidu.com/geocoder/v2/?location=
  # 根据实际地址转换经纬度的百度APIURL
  getLngAndLatByAddress: https://api.map.baidu.com/geocoder/v2/?address=
  # 根据实际地址转换经纬度的高德API 使用的 KEY
  KEY_1: XXXXXXXXXXX
  # 高德地图API
  GdMapUrl: https://restapi.amap.com/v3/geocode/  
  # 高德地图API 使用的key
  KEY_2 : XXXXXXXXXXX
  # 调整使用的地图API 开关 false->使用百度   true->使用高德
  useGd : true
#网络代理信息
http:
  proxy:
    enable: true
    host: 0.0.0.0
    port: 8080

工具类:
方法简单说明:

getGeocoderLatitude(String) :返回输入地址的经纬度坐标 key lng(经度),lat(纬度)
getAdd(String log, String lat) :根据经纬度信息 获取实际的地理位置
GetDistance(double lat1, double lng1, double lat2, double lng2):计算两个经纬度之间的距离 计算结果单位:米

工具类代码:


	
	
/**
 * 打卡、签到 用到的 XY坐标和地理位置之前的转换、两组经纬度之间计算距离
 */
@Configuration
public class MapUtil {
	private static final Logger logger = LoggerFactory.getLogger(MapUtil.class);
	/**
	 * 百度API 根据实际地址转换经纬度的API 使用的 KEY
	 */
	public static String KEY_1;

	private static double EARTH_RADIUS = 6371.393;
	/**
	 * 百度API 根据经纬度转换地址的API的url
	 */
	private static String getAddressByLngAndLat;
	
	/**
	 * 百度API 根据实际地址转换经纬度的API的URL
	 */
	private static String getLngAndLatByAddress;
	
	/**
	 * 高德API 使用 的 地图 PAI地址
	 */
	private static String gdMapUrl;
	/**
	 * 高德API 使用 的 key
	 */
	private static String KEY_2;
	/**
	 * 调整使用的地图API 开关 false->使用百度   true->使用高德
	 */
	private static Boolean useGd;
	
	
	private static boolean proxyEnable = false;

	private static String proxyhost;

	private static int proxyPort = 80;
	
	private static double rad(double d) {
		return d * Math.PI / 180.0;
	}
	
	public static String getKEY_1() {
		return KEY_1;
	}
	@Value("${map.KEY_1}")
	public  void setKEY_1(String kEY_1) {
		MapUtil.KEY_1 = kEY_1;
	}

	public static String getGetAddressByLngAndLat() {
		return getAddressByLngAndLat;
	}
	@Value("${map.getAddressByLngAndLat}")
	public  void setGetAddressByLngAndLat(String getAddressByLngAndLat) {
		MapUtil.getAddressByLngAndLat = getAddressByLngAndLat;
	}

	public static String getGetLngAndLatByAddress() {
		return getLngAndLatByAddress;
	}

	@Value("${map.getLngAndLatByAddress}")
	public  void setGetLngAndLatByAddress(String getLngAndLatByAddress) {
		MapUtil.getLngAndLatByAddress = getLngAndLatByAddress;
	}

	public static boolean isProxyEnable() {
		return proxyEnable;
	}
	@Value(value = "${http.proxy.enable:false}")
	public  void setProxyEnable(boolean proxyEnable) {
		MapUtil.proxyEnable = proxyEnable;
	}

	public static String getProxyhost() {
		return proxyhost;
	}
	@Value(value = "${http.proxy.host}")
	public  void setProxyhost(String proxyhost) {
		MapUtil.proxyhost = proxyhost;
	}

	public static int getProxyPort() {
		return proxyPort;
	}
	@Value(value = "${http.proxy.port:80}")
	public  void setProxyPort(int proxyPort) {
		MapUtil.proxyPort = proxyPort;
	}
	
	public static String getGdMapUrl() {
		return gdMapUrl;
	}
	@Value("${map.GdMapUrl}")
	public void setGdMapUrl(String gdMapUrl) {
		MapUtil.gdMapUrl = gdMapUrl;
	}

	public static String getKEY_2() {
		return KEY_2;
	}
	@Value("${map.KEY_2}")
	public void setKEY_2(String kEY_2) {
		KEY_2 = kEY_2;
	}

	public static Boolean getUseGd() {
		return useGd;
	}
	@Value("${map.useGd}")
	public  void setUseGd(Boolean useGd) {
		MapUtil.useGd = useGd;
	}

	/**
	 * 返回输入地址的经纬度坐标 key lng(经度),lat(纬度)
	 */
	public static Map<String, String> getGeocoderLatitude(String address) {
		logger.info("\n【返回输入地址的经纬度坐标】getGeocoderLatitude----->入参,address=" + address);
		BufferedReader in = null;
		try {
			// 将地址转换成utf-8的16进制
			address = URLEncoder.encode(address, "UTF-8");
			String getGeocoderLatitudeUrl = getGeocoderLatitudeMapUrl(address);
			URL tirc = new URL(getGeocoderLatitudeUrl);
			java.net.HttpURLConnection conn = (java.net.HttpURLConnection) openConnection(tirc);
			in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
			String res;
			StringBuilder sb = new StringBuilder("");
			while ((res = in.readLine()) != null) {
				sb.append(res.trim());
			}
			String str = sb.toString();
			return dealReturnJson(str);
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
		} finally {
			try {
				in.close();
			} catch (IOException e) {
				logger.error(e.getMessage(), e);
			}
		}
		return null;
	}
	
	/**
	 * 根据配置的开关 获取地图 根据地址计算经纬度的API 对应的 url
	 * @return
	 */
	public static String getGeocoderLatitudeMapUrl(String address) {
		if(useGd) {//使用高德地图API 
			return gdMapUrl + "geo?address=" + address + "&output=json&key="+KEY_2+"";
		}else {//默认使用百度API
			return getLngAndLatByAddress + address + "&output=json&ak=" + KEY_1+"&s=1";
		}
	}
	/**
	 * 解析 逆向请求 返回地址信息
	 * @param str
	 * @return
	 */
	public static Map<String, String> dealReturnJson(String str){
		logger.info("\n【返回输入地址的经纬度坐标】getGeocoderLatitude----->str="+str);
		JSONObject jsonObject = JSON.parseObject(str);
		Map<String, String> map = null;
		String status = jsonObject.getString("status");
		if(useGd) {//使用高德
			logger.info("use 高德API------");
			if("1".equals(status)){// 1 表示查询成功
				logger.info("\n【返回输入地址的经纬度坐标】getGeocoderLatitude----->实际的物理地址转经纬度转换成功,status="+status);
				JSONArray arr = JSON.parseArray(jsonObject.getString("geocodes"));
				JSONObject obj = JSON.parseObject(arr.getString(0));
				String location = obj.getString("location");
				map = new HashMap<String, String>();
				map.put("lng", location.split(",")[0]);
				map.put("lat", location.split(",")[1]);
				return map;
			}else if(!"1".equals(status)){
				logger.info("\n【返回输入地址的经纬度坐标】getGeocoderLatitude----->实际的物理地址转经纬度转换,失败 status="+status);
				return null;
			}
		}else {//默认使用百度
			logger.info("use 百度API------");
			if("0".equals(status)){// 0 表示查询成功
				logger.info("\n【返回输入地址的经纬度坐标】getGeocoderLatitude----->实际的物理地址转经纬度转换成功,status="+status);
				JSONObject result_obj = JSON.parseObject(jsonObject.getString("result"));
				String confidence = result_obj.getString("confidence");
				String location_obj = result_obj.getString("location");
				JSONObject location_ = JSON.parseObject(location_obj.toString());
				map = new HashMap<String, String>();
				map.put("lng", location_.getString("lng"));
				map.put("lat", location_.getString("lat"));
				map.put("confidence", confidence);
				return map;
			}else if(!"0".equals(status)){
				logger.info("\n【返回输入地址的经纬度坐标】getGeocoderLatitude----->实际的物理地址转经纬度转换,失败 status="+status);
				return null;
			}
		}
		
		return null;
	}

	/**
	 * 计算两个经纬度之间的距离 计算结果单位:米
	 * 
	 * @param lat1
	 *            纬度1
	 * @param lng1
	 *            经度1
	 * @param lat2
	 *            纬度2
	 * @param lng2
	 *            经度2
	 * @return
	 */
	public static double GetDistance(double lat1, double lng1, double lat2, double lng2) {
		
		if(useGd) { //使用高德地图API
			double[] arr1 = LngLonUtil.bd09_To_Gcj02(lat1, lng1);
			double[] arr2 = LngLonUtil.bd09_To_Gcj02(lat2, lng2);
			lat1 = arr1[0];
			lng1 = arr1[1];
			lat2 = arr2[0];
			lng2 = arr2[1];
		} else { //默认使用百度API
			
		}
		double radLat1 = rad(lat1);
		double radLat2 = rad(lat2);
		double a = radLat1 - radLat2;
		double b = rad(lng1) - rad(lng2);
		double s = 2 * Math.asin(Math.sqrt(
				Math.pow(Math.sin(a / 2), 2) + Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2)));
		s = s * EARTH_RADIUS;
		s = Math.round(s * 1000);
		return s;
	}

	/**
	 * 根据经纬度信息 获取实际的地理位置
	 * 
	 * @param log
	 *            经度
	 * @param lat
	 *            纬度
	 * @return
	 */
	public static String getAdd(String log, String lat) {
		logger.info("\n【根据经纬度信息获取实际的地理位置】getAdd----->入参,log={},lat={}", log, lat);
		String urlString = getAddUrl(log, lat);
		String res = "";
		try {
			URL url = new URL(urlString);
			logger.info("\n【根据经纬度信息获取实际的地理位置】getAdd----->调用获取位置的百度API地址,urlString={},经纬度:log={},lat={}",
					urlString, log, lat);
			java.net.HttpURLConnection conn = (java.net.HttpURLConnection) openConnection(url);
			conn.setDoOutput(true);
			conn.setRequestMethod("GET");
			java.io.BufferedReader in = new java.io.BufferedReader(
					new java.io.InputStreamReader(conn.getInputStream(), "UTF-8"));
			String line;
			while ((line = in.readLine()) != null) {
				res += line + "\n";
			}
			in.close();
		} catch (Exception e) {
			logger.error("\n【根据经纬度信息获取实际的地理位置】getAdd----->异常信息:" + e.getMessage(), e);
		}
		return dealReturnAddJson(res);
	}
	/**
	 * 获取经纬度转地点的url
	 * @param log
	 * @param lat
	 * @return
	 */
	public static String getAddUrl(String log, String lat) {
		if(useGd) {//使用高德地图API
			double[] arr1 = LngLonUtil.bd09_To_Gcj02(Double.parseDouble(lat), Double.parseDouble(log));
			return gdMapUrl + "regeo?output=json&location="+ arr1[1] +"," + arr1[0] + "&key="+ KEY_2 +"&radius=1000&extensions=base";
		} else { //默认使用百度API
			return getAddressByLngAndLat+lat+","+log+"&output=json&pois=0&ak="+KEY_1+"&s=1";
		}
	}
	/**
	 * 解析 根据经纬度换算的 地址信息
	 * @param res
	 * @return
	 */
	public static String dealReturnAddJson(String res) {
		if(useGd) {//使用高德地图API
			if(res!=null && !"".equals(res)){
				JSONObject jsonObject = JSON.parseObject(res);
				String status = jsonObject.getString("status");
				if("1".equals(status)){
					JSONObject jsonObject_ = JSON.parseObject(jsonObject.getString("regeocode"));
					String formatted_address = jsonObject_.getString("formatted_address");
					return formatted_address;
				}else {
					logger.info("\n【根据经纬度信息获取实际的地理位置】getAdd----->根据经纬度转换实际的物理地址失败,status="+status);
					return "";
				}
			}else{
				return "";
			}
		} else { //默认使用百度API
			if(res!=null && !"".equals(res)){
				logger.info("\n【根据经纬度信息获取实际的地理位置】getAdd----->调用百度API返回的json,getAdd--->res="+res);
				JSONObject jsonObject = JSON.parseObject(res);
				String status = jsonObject.getString("status");
				logger.info("\n【根据经纬度信息获取实际的地理位置】getAdd----->调用百度API是否成功(0表示成功),status="+status);
				if("0".equals(status)){
					logger.info("\n【根据经纬度信息获取实际的地理位置】getAdd----->根据经纬度转换实际的物理地址成功,status="+status);
					logger.info("\n【根据经纬度信息获取实际的地理位置】getAdd----->result="+JSON.parseObject(jsonObject.getString("result")));
					String formatted_address = "";
					JSONObject jsonObject_ = JSON.parseObject(jsonObject.getString("result"));
					formatted_address = jsonObject_.getString("formatted_address");
					if(jsonObject_.containsKey("poiRegions")) {
						JSONArray poiRegions = (JSONArray) jsonObject_.get("poiRegions");
						if(poiRegions.size()>0) {
							JSONObject jobj = (JSONObject) poiRegions.get(0);
							if(jobj.containsKey("name")) {
								String name = (String) jobj.get("name");
								formatted_address +=" "+name;
							}
						}else {
							formatted_address+=" "+jsonObject_.get("sematic_description");
						}
					}
					return formatted_address;
					
				}else if(!"0".equals(status)){
					logger.info("\n【根据经纬度信息获取实际的地理位置】getAdd----->根据经纬度转换实际的物理地址失败,status="+status);
					return "";
				}
				return "";
			}else{
				return "";
			}
		}
	}
	
	private static URLConnection openConnection(URL url) throws IOException {
		if (proxyEnable) {
			logger.info("\n【请求目标URL】openConnection----->启用代理:proxyEnable={},proxyhost={},proxyPort={}", proxyEnable, proxyhost, proxyPort);
			Proxy proxy = new Proxy(Proxy.Type.DIRECT.HTTP, new InetSocketAddress(proxyhost, proxyPort));
			return url.openConnection(proxy);
		} else {
			logger.info("\n【请求目标URL】openConnection----->没有启用代理");
			return url.openConnection();
		}

	}

}

百度经纬度 和 高德经纬度 相互转换代码:

/** 
     * 百度 == 》 高德
     * @param lat 
     * @param lon 
     */  
    public static double[] bd09_To_Gcj02(double lat, double lon) {  
        double x = lon - 0.0065, y = lat - 0.006;  
        double z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * x_pi);  
        double theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * x_pi);  
        double tempLon = z * Math.cos(theta);  
        double tempLat = z * Math.sin(theta);  
        double[] gps = {retain6(tempLat),retain6(tempLon)};  
        return gps;  
    }  
        /** 
     * 高德 == 》 百度
     * @param lat 
     * @param lon 
     */  
    public static double[] gcj02_To_Bd09(double lat, double lon) {  
        double x = lon, y = lat;  
        double z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * x_pi);  
        double theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * x_pi);  
        double tempLon = z * Math.cos(theta) + 0.0065;  
        double tempLat = z * Math.sin(theta) + 0.006;  
        double[] gps = {tempLat,tempLon};  
        return gps;  
    }

献丑了……

你可能感兴趣的:(#,java,java)