Springboot利于第三方服务进行ip定位获取省份城市
作者:化尘成影
在web应用的开发中,我们或许会想知道我们的用户请求的来源分布情况。本文基于springboot框架,调用百度地图、高德地图的开放平台api,在线对对请求来源的ip进行定位、解析,获取目标ip所对应的省份、城市、经纬度等信息,方便开发者将相关数据记录在操作日志中。
一. 共用部分
统一响应类
/** * @author 摆渡人 * @description 统一响应类 * @date 2023/7/13 23:26 */ @Data @Builder public class IpAnalyzeResponse { /** * 状态码 */ private String status; /** * 是否成功 */ private Boolean successFlag; /** * 失败原因 */ private String msg; /** * 省份名称 */ private String province; /** * 城市名称 */ private String city; /** * 经度 */ private Double x; /** * 维度 */ private Double y; }
定义接口
实现该接口,并在配置类中注入接口的实现类,即可拓展ip定位的更多实现方式
/** * @author 摆渡人 * @description ip定位接口 * @date 2023/7/13 23:25 */ public interface IPlatFormIpAnalyzeService { /** * ip定位解析 * @param ip * @return */ IpAnalyzeResponse ipAnalyze(String ip); }
http请求工具类(用于发送http请求)
源码来自SmartAdmin
/** * [ HttpUtils ] * * @author yandanyang * @version 1.0 * @company 1024lab.net * @copyright (c) 2019 1024lab.netInc. All rights reserved. * @date * @since JDK1.8 */ public class SmartHttpUtil { public static String sendGet(String url, Map<String, String> params, Map<String, String> header) throws Exception { HttpGet httpGet = null; String body = ""; try { CloseableHttpClient httpClient = HttpClients.createDefault(); List<String> mapList = new ArrayList<>(); if (params != null) { for (Entry<String, String> entry : params.entrySet()) { mapList.add(entry.getKey() + "=" + entry.getValue()); } } if (CollectionUtils.isNotEmpty(mapList)) { url = url + "?"; String paramsStr = StringUtils.join(mapList, "&"); url = url + paramsStr; } httpGet = new HttpGet(url); httpGet.setHeader("Content-type", "application/json; charset=utf-8"); httpGet.setHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)"); if (header != null) { for (Entry<String, String> entry : header.entrySet()) { httpGet.setHeader(entry.getKey(), entry.getValue()); } } HttpResponse response = httpClient.execute(httpGet); int statusCode = response.getStatusLine().getStatusCode(); if (statusCode != HttpStatus.SC_OK) { throw new RuntimeException("请求失败"); } else { body = EntityUtils.toString(response.getEntity(), "UTF-8"); } } catch (Exception e) { throw e; } finally { if (httpGet != null) { httpGet.releaseConnection(); } } return body; } public static String sendPostJson(String url, String json, Map<String, String> header) throws Exception { HttpPost httpPost = null; String body = ""; try { CloseableHttpClient httpClient = HttpClients.createDefault(); httpPost = new HttpPost(url); httpPost.setHeader("Content-type", "application/json; charset=utf-8"); httpPost.setHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)"); if (header != null) { for (Entry<String, String> entry : header.entrySet()) { httpPost.setHeader(entry.getKey(), entry.getValue()); } } StringEntity entity = new StringEntity(json, Charset.forName("UTF-8")); entity.setContentEncoding("UTF-8"); entity.setContentType("application/json"); httpPost.setEntity(entity); HttpResponse response = httpClient.execute(httpPost); int statusCode = response.getStatusLine().getStatusCode(); if (statusCode != HttpStatus.SC_OK) { throw new RuntimeException("请求失败"); } else { body = EntityUtils.toString(response.getEntity(), "UTF-8"); } } catch (Exception e) { throw e; } finally { if (httpPost != null) { httpPost.releaseConnection(); } } return body; } public static String sendPostForm(String url, Map<String, String> params, Map<String, String> header) throws Exception { HttpPost httpPost = null; String body = ""; try { CloseableHttpClient httpClient = HttpClients.createDefault(); httpPost = new HttpPost(url); httpPost.setHeader("Content-type", "application/x-www-form-urlencoded"); httpPost.setHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)"); if (header != null) { for (Entry<String, String> entry : header.entrySet()) { httpPost.setHeader(entry.getKey(), entry.getValue()); } } List<NameValuePair> nvps = new ArrayList<>(); if (params != null) { for (Entry<String, String> entry : params.entrySet()) { nvps.add(new BasicNameValuePair(entry.getKey(), entry.getValue())); } } //设置参数到请求对象中 httpPost.setEntity(new UrlEncodedFormEntity(nvps, "UTF-8")); HttpResponse response = httpClient.execute(httpPost); int statusCode = response.getStatusLine().getStatusCode(); if (statusCode != HttpStatus.SC_OK) { throw new RuntimeException("请求失败"); } else { body = EntityUtils.toString(response.getEntity(), "UTF-8"); } } catch (Exception e) { throw e; } finally { if (httpPost != null) { httpPost.releaseConnection(); } } return body; } }
二.百度地图开放平台实现
1. 使用准备
阅读文档普通IP定位 | 百度地图API SDK (baidu.com),成为开发者,获取服务密钥(AK)
2. 封装实体类
/** * @author 摆渡人 * @description 地址解析的结果 * @date 2023/7/10 20:29 */ @Data public class IpAnalyzeBaiduResponse implements Serializable { /** * 返回状态码 */ private Integer status; /** * 错误信息 */ private String message; /** * 地址 */ private String address; /** * 详细内容 */ private IpAnalyzeContent content; }
/** * @author 摆渡人 * @description 详细内容 * @date 2023/7/10 20:42 */ @Data public class IpAnalyzeContent implements Serializable { /** * 简要地址 */ private String address; /** * 详细地址信息 */ @JsonProperty("address_detail") private IpAnalyzeAddressDetail addressDetail; /** * 百度经纬度坐标值 */ @JsonProperty("point") private IpAnalyzePoint point; }
/** * @author 摆渡人 * @description 详细地址信息 * @date 2023/7/10 20:41 */ @Data public class IpAnalyzeAddressDetail implements Serializable { /** * 城市 */ private String city; /** * 百度城市代码 */ @JsonProperty("city_code") private Integer cityCode; /** * 区县 */ private String district; /** * 省份 */ private String province; /** * 街道 */ private String street; /** * 门地址 */ @JsonProperty("street_number") private String streetNumber; }
/** * @author 摆渡人 * @description 百度经纬度坐标值 * @date 2023/7/10 20:43 */ @Data public class IpAnalyzePoint implements Serializable { private String x; private String y; }
3.实现接口IPlatFormIpAnalyzeService
/** * @author 摆渡人 * @description 百度地图开发平台实现类 * @date 2023/7/10 20:27 */ @Slf4j public class PlatformBaiduService implements IPlatFormIpAnalyzeService { /** * 响应成功状态码 */ private final Integer OK_CODE = 0; @Value("${platform.conf.baidu.ak}") public String ak; @Override public IpAnalyzeResponse ipAnalyze(String ip) { String URL = "http://api.map.baidu.com/location/ip"; Map<String,String> params = new HashMap<>(); params.put("ip", ip); params.put("ak", ak); params.put("coor", "bd09ll"); try { String json = SmartHttpUtil.sendGet(URL, params, null); IpAnalyzeBaiduResponse response = JSONUtil.toBean(json, IpAnalyzeBaiduResponse.class); if(OK_CODE.equals(response.getStatus())) { return IpAnalyzeResponse.builder() .status(response.getStatus() + "") .successFlag(true) .msg(response.getMessage()) .province(response.getContent().getAddressDetail().getProvince()) .city(response.getContent().getAddressDetail().getCity()) .x(Double.parseDouble(response.getContent().getPoint().getX())) .y(Double.parseDouble(response.getContent().getPoint().getY())) .build(); } return IpAnalyzeResponse.builder() .status(response.getStatus() + "") .successFlag(false) .msg(response.getMessage()) .build(); } catch (Exception e) { return IpAnalyzeResponse.builder() .status("500") .successFlag(false) .msg(e.getMessage()) .build(); } } }
三.高德地图开放平台实现
1. 使用准备
根据文档获取Key-创建工程-开发指南-Web服务 API|高德地图API (amap.com)指引获取key
2. 封装实体类
/** * @author 摆渡人 * @description 高德地图ip定位响应类 * @date 2023/7/14 0:00 */ @Data public class IpAnalyzeGaodeResponse { /** * 返回结果状态值,值为0或1,0表示失败;1表示成功 */ private String status; /** * 返回状态说明,status为0时,info返回错误原因,否则返回“OK */ private String info; /** * 返回状态说明,10000代表正确,详情参阅info状态表 */ private String infocode; /** * 若为直辖市则显示直辖市名称; * * 如果在局域网 IP网段内,则返回“局域网”; * * 非法IP以及国外IP则返回空 */ private String province; /** * 若为直辖市则显示直辖市名称; * * 如果为局域网网段内IP或者非法IP或国外IP,则返回空 */ private String city; /** * 城市的adcode编码 */ private String adcode; /** * 所在城市矩形区域范围,所在城市范围的左下右上对标对,如:116.0119343,39.66127144;116.7829835,40.2164962 */ private String rectangle; }
3.实现接口IPlatFormIpAnalyzeService
/** * @author 摆渡人 * @description 高德地图开放平台ip定位实现类 * @date 2023/7/13 23:56 */ @Slf4j public class PlatformGaodeService implements IPlatFormIpAnalyzeService { /** * 响应成功状态码 */ private final String OK_CODE = "1"; @Value("${platform.conf.gaode.key}") private String key; @Override public IpAnalyzeResponse ipAnalyze(String ip) { String URL = "https://restapi.amap.com/v3/ip"; Map<String,String> params = new HashMap<>(); params.put("key",key); params.put("ip",ip); try { String json = SmartHttpUtil.sendGet(URL, params, null); IpAnalyzeGaodeResponse response = JSONUtil.toBean(json, IpAnalyzeGaodeResponse.class); if(OK_CODE.equals(response.getStatus())) { IpAnalyzeResponse ipAnalyzeResponse = IpAnalyzeResponse.builder() .status(response.getInfocode()) .successFlag(true) .msg(response.getInfo()) .province(response.getProvince()) .city(response.getCity()) .build(); // 对rectangle进行解析 String rectangle = response.getRectangle(); String[] split = rectangle.split(";|,"); if(split.length == 1) { ipAnalyzeResponse.setSuccessFlag(false); ipAnalyzeResponse.setStatus("0"); ipAnalyzeResponse.setMsg("ip[" + ip + "]非法"); return ipAnalyzeResponse; } ipAnalyzeResponse.setX((Double.parseDouble(split[0]) + Double.parseDouble(split[2])) / 2.0); ipAnalyzeResponse.setY((Double.parseDouble(split[1]) + Double.parseDouble(split[3])) / 2.0); return ipAnalyzeResponse; } return IpAnalyzeResponse.builder() .status(response.getInfocode()) .successFlag(false) .msg(response.getInfo()) .build(); } catch (Exception e) { e.printStackTrace(); return IpAnalyzeResponse.builder() .status(“500”) .successFlag(false) .msg(e.getMessage()) .build(); } } }
四. 使用
1.配置参数
# 第三方开放平台的服务 platform: # 目前支持百度[baidu] 高德[gaode] mode: # 您选择的服务 # 相关配置 conf: # 百度 baidu: ak: # 您的百度地图开放平台服务密钥(AK) # 高德 gaode: key: # 您的高德地图开放平台key
2.配置类
根据配置参数中platform.mode
的值选择接口IPlatFormIpAnalyzeService
的一个服务类注入Spring容器中去
/** * @author 摆渡人 * @description 接口实现类配置 * @date 2023/7/14 0:16 */ @Configuration public class PlatFormConfig { @Bean @ConditionalOnProperty(prefix = "platform",name = "mode",havingValue = "baidu") public IPlatFormIpAnalyzeService initBaiduIpAnalyzeService() { return new PlatformBaiduService(); } @Bean @ConditionalOnProperty(prefix = "platform",name = "mode",havingValue = "gaode") public IPlatFormIpAnalyzeService initGaodeIpAnalyzeService() { return new PlatformGaodeService(); } }
3.单元测试
/** * @author 摆渡人 * @description * @date 2023/7/14 0:23 */ @Slf4j @ExtendWith(SpringExtension.class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) public class PlatformTest { @Autowired private IPlatFormIpAnalyzeService platFormIpAnalyzeService; @Test public void testIpAnalyzeService() { log.info("解析结果:{}",platFormIpAnalyzeService.ipAnalyze(null)); log.info("解析结果:{}",platFormIpAnalyzeService.ipAnalyze("")); log.info("解析结果:{}",platFormIpAnalyzeService.ipAnalyze("127.0.0.1")); log.info("解析结果:{}",platFormIpAnalyzeService.ipAnalyze("114.247.50.2")); log.info("解析结果:{}",platFormIpAnalyzeService.ipAnalyze("219.137.148.0")); log.info("解析结果:{}",platFormIpAnalyzeService.ipAnalyze("114.80.166.240")); } }
运行结果如下:
platform.mode=gaode
[2023-07-22 22:42:40,426][INFO ][main] 解析结果:IpAnalyzeResponse(status=0, successFlag=false, msg=ip[null]非法, province=[], city=[], x=null, y=null) (PlatformTest.java:26)
[2023-07-22 22:42:40,662][INFO ][main] 解析结果:IpAnalyzeResponse(status=0, successFlag=false, msg=ip[]非法, province=[], city=[], x=null, y=null) (PlatformTest.java:27)
[2023-07-22 22:42:40,898][INFO ][main] 解析结果:IpAnalyzeResponse(status=0, successFlag=false, msg=ip[127.0.0.1]非法, province=[], city=[], x=null, y=null) (PlatformTest.java:28)
[2023-07-22 22:42:41,132][INFO ][main] 解析结果:IpAnalyzeResponse(status=10000, successFlag=true, msg=OK, province=北京市, city=北京市, x=116.3974589, y=39.93888382) (PlatformTest.java:29)
[2023-07-22 22:42:41,365][INFO ][main] 解析结果:IpAnalyzeResponse(status=10000, successFlag=true, msg=OK, province=广东省, city=广州市, x=113.3893937, y=23.15653812) (PlatformTest.java:30)
[2023-07-22 22:42:41,600][INFO ][main] 解析结果:IpAnalyzeResponse(status=10000, successFlag=true, msg=OK, province=上海市, city=上海市, x=121.4767528, y=31.224348955) (PlatformTest.java:31)
platform.mode=baidu
[2023-07-22 22:40:48,774][INFO ][main] 解析结果:IpAnalyzeResponse(status=2, successFlag=false, msg=Request Parameter Error:ip illegal, province=null, city=null, x=null, y=null) (PlatformTest.java:26)
[2023-07-22 22:40:48,825][INFO ][main] 解析结果:IpAnalyzeResponse(status=0, successFlag=true, msg=null, province=广东省, city=广州市, x=113.27143134, y=23.13533631) (PlatformTest.java:27)
[2023-07-22 22:40:48,862][INFO ][main] 解析结果:IpAnalyzeResponse(status=1, successFlag=false, msg=Internal Service Error:ip[127.0.0.1] loc failed, province=null, city=null, x=null, y=null) (PlatformTest.java:28)
[2023-07-22 22:40:48,899][INFO ][main] 解析结果:IpAnalyzeResponse(status=0, successFlag=true, msg=null, province=北京市, city=北京市, x=116.4133837, y=39.91092455) (PlatformTest.java:29)
[2023-07-22 22:40:48,949][INFO ][main] 解析结果:IpAnalyzeResponse(status=0, successFlag=true, msg=null, province=广东省, city=广州市, x=113.27143134, y=23.13533631) (PlatformTest.java:30)
[2023-07-22 22:40:48,988][INFO ][main] 解析结果:IpAnalyzeResponse(status=0, successFlag=true, msg=null, province=上海市, city=上海市, x=121.48789949, y=31.24916171) (PlatformTest.java:31)
到此这篇关于Springboot利于第三方服务进行ip定位获取省份城市的文章就介绍到这了,更多相关Springboot ip定位获取省份城市内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!