马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
团体流程图
获取当前登任命户所在都会,是一个非经常见的需求,在许多业务场景中用到。
好比:导航的定位功能默认选择的都会,大概一些防盗体系中辨认用户两次登录的都会不一样的会有报警提示。
下载geoip2数据库
geoip2是国外的一个免费的IP库,只要注册账号就能下载IP数据库了。
官网地点:https://www.maxmind.com/。
其他下载:https://kohler.o.com/i3Fkb36wobuh
将IP库生存到电脑的某个目次下
之后利用绝对路径
引入干系依靠
引入geoip干系的依靠包:- <dependency>
- <groupId>com.maxmind.geoip2</groupId>
- <artifactId>geoip2</artifactId>
- <version>2.16.1</version>
- </dependency>
复制代码 增长获取都会接口
增长一个根据ip获取所在都会的接口。
创建一个GeoIpController类:- @Tag( name= "geoip操作", description = "geoip操作")
- @RestController
- @RequestMapping("/v1/web/geoip")
- @Validated
- public class GeoIpController {
- @Autowired
- private GeoIpHelper geoIpHelper;
- /**
- * 根据ip获取所在城市
- *
- * @param ip ip地址
- * @return 城市
- */
- @NoLogin
- @Operation(summary = "根据ip获取所在城市", description = "根据ip获取所在城市")
- @GetMapping("/getCity")
- public CityDTO getCity(@RequestParam(value = "ip") String ip) {
- return geoIpHelper.getCity(ip);
- }
- }
复制代码 这个类中只包罗了getCity这一个接口,该接口就是通过ip获取所在国家、省份和都会。
创建GeoIpHelper类:- @Slf4j
- @Component
- public class GeoIpHelper {
- private static final String GEO_IP_FILE_NAME = "GeoLite2-City.mmdb";
- @Value("${shop.mgt.geoIpFilePath:}")
- private String geoIpFilePath;
- @Value("${shop.mgt.taobaoIpUrl:}")
- private String taobaoIpUrl;
- @Value("${shop.mgt.taobaoIpRequestOff:false}")
- private Boolean taobaoIpRequestOff;
- @Autowired
- private HttpHelper httpHelper;
- /**
- * 根据ip获取所在城市
- *
- * @param ip ip地址
- * @return 城市
- */
- public CityDTO getCity(String ip) {
- CityDTO cityFromGeoIp = getCityFromGeoIp(ip);
- if (Objects.nonNull(cityFromGeoIp) && Objects.nonNull(cityFromGeoIp.getCity())) {
- return cityFromGeoIp;
- }
- if (taobaoIpRequestOff) {
- return null;
- }
- return getCityFromApi(ip);
- }
- private CityDTO getCityFromGeoIp(String ip) {
- String fileUrl = getFileUrl();
- File file = new File(fileUrl);
- if (!file.exists()) {
- log.warn(String.format("%s文件不存在", fileUrl));
- return null;
- }
- try {
- DatabaseReader reader = new DatabaseReader.Builder(file).build();
- //解析IP地址
- InetAddress ipAddress = InetAddress.getByName(ip);
- // 获取查询结果
- CityResponse response = reader.city(ipAddress);
- if (response == null) {
- return null;
- }
- // 国家
- String country = response.getCountry().getNames().get("zh-CN");
- // 省份
- String province = response.getMostSpecificSubdivision().getNames().get("zh-CN");
- //城市
- String city = response.getCity().getNames().get("zh-CN");
- return new CityDTO(ip, country, province, city);
- } catch (Exception e) {
- log.error("从GeoIp库中获取城市失败,原因:", e);
- }
- return null;
- }
- private CityDTO getCityFromApi(String ip) {
- String url = String.format(taobaoIpUrl, ip);
- TaoboCityEntity taoboCityEntity = httpHelper.doGet(url, TaoboCityEntity.class);
- if (Objects.nonNull(taoboCityEntity)) {
- TaoboCityEntity.TaoboAreaEntity data = taoboCityEntity.getData();
- if (Objects.nonNull(data)) {
- return new CityDTO(ip, data.getCountry(), data.getRegion(), data.getCity());
- }
- }
- return null;
- }
- private String getFileUrl() {
- return geoIpFilePath + "/" + GEO_IP_FILE_NAME;
- }
- }
复制代码 这个类重要是来用读取IP库的数据,通过ip查询国家、省份和都会。
由于ip库有大概不全,大概不是最新的数据。大概会导致根据ip获取不到我们想要的数据的环境。
因此必要做兼容处理惩罚,如果从ip库查询不到数据,则再调用一下长途接口获取数据。
调用淘宝接口
创建HttpHelper类:- @Slf4j
- @Component
- public class HttpHelper {
- @Autowired
- private RestTemplate restTemplate;
- /**
- * 发送get请求
- *
- * @param url url地址
- * @param tClass 返回值实体
- * @param <T> 泛型
- * @return 返回值实体
- */
- public <T> T doGet(String url, Class<T> tClass) {
- return restTemplate.getForObject(url, tClass);
- }
- }
复制代码 界说了doGet方法获取用户哀求。
创建了RestTemplateConfig类:- @Configuration
- public class RestTemplateConfig {
- @Value("${shop.mgt.rest.template.connectTimeout:3000}")
- private int connectTimeout;
- @Value("${shop.mgt.rest.template.readTimeout:50000}")
- private int readTimeout;
- @Bean
- public RestTemplate restTemplate(ClientHttpRequestFactory factory) {
- return new RestTemplate(factory);
- }
- @Bean
- public ClientHttpRequestFactory simpleClientHttpRequestFactory() {
- HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
- factory.setConnectTimeout(connectTimeout);
- factory.setReadTimeout(readTimeout);
- return factory;
- }
- /**
- * 忽略证书配置
- */
- public static HttpComponentsClientHttpRequestFactory generateHttpRequestFactory()
- throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException {
- TrustStrategy acceptingTrustStrategy = (x509Certificates, authType) -> true;
- SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(null, acceptingTrustStrategy).build();
- SSLConnectionSocketFactory connectionSocketFactory = new SSLConnectionSocketFactory(sslContext,
- new NoopHostnameVerifier());
- HttpClientBuilder httpClientBuilder = HttpClients.custom();
- httpClientBuilder.setSSLSocketFactory(connectionSocketFactory);
- CloseableHttpClient httpClient = httpClientBuilder.build();
- HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
- factory.setHttpClient(httpClient);
- return factory;
- }
- }
复制代码 这个类是一个设置类,重要设置了RestTemplate的一些参数,以及https哀求忽略证书的环境。
如果不忽略证书,有些环境下,好比:调用测试环境的哀求,利用的不是有效的证书,会哀求失败。
application.yml文件中增长设置:- shop:
- mgt:
- geoIpFilePath: D:\workplace\SpringBoot\kailong_shop\shop_business\src\main\resources\files\geoip2
- taobaoIpUrl: https://ip.taobao.com/outGetIpInfo?ip=%s&accessKey=alibaba-inc
复制代码 此中accessKey利用的淘宝的测试key。
测试
代码开发好之后,接下来举行测试。
在欣赏器上访问:http://localhost:8011/v1/web/geoip/getCity?ip=123.245.11.177(我的测试路径)
返回了精确的都会
分析根据ip获取所在都会的功能OK了。
必要特殊留意的是如今调用淘宝的测试接口,天天有数目限定,到达肯定测试就会返回失败。
也可以换成其他平台的接口,大概申请一个付费的accessKey。
|