概述
本文将探讨如何使用MaxMind GeoIP2 Java API和免费的GeoLite2数据库从IP地址获取地理位置数据。我们将通过一个简单的Spring MVC Web演示应用来展示这个过程。
1. 开始
首先,您需要从MaxMind下载GeoIP2 API和GeoLite2数据库。
1.1. Maven依赖
要在Maven项目中包含MaxMind GeoIP2 API,只需在pom.xml
文件中添加以下内容:
<dependency>
<groupId>com.maxmind.geoip2</groupId>
<artifactId>geoip2</artifactId>
<version>2.8.0</version>
</dependency>
要获取API的最新版本,请访问Maven中央仓库。
1.2. 下载数据库
接下来,您需要下载GeoLite2数据库。本教程中,我们将使用GeoLite2 City数据库的二进制gzip版本。
解压压缩包后,您将得到一个名为GeoLite2-City.mmdb
的文件。这是一个包含IP地址到位置映射的MaxMind专有二进制格式数据库。
2. 使用GeoIP2 Java API
现在,让我们使用GeoIP2 Java API从数据库中检索给定IP地址的位置信息。首先,我们创建一个DatabaseReader
来查询数据库:
File database = new File(dbLocation);
DatabaseReader dbReader = new DatabaseReader.Builder(database).build();
然后,使用city()
方法获取IP地址的城市数据:
CityResponse response = dbReader.city(ipAddress);
CityResponse
对象除了城市名称之外,还包含其他一些信息。以下是一个示例JUnit测试,展示了如何打开数据库、获取IP地址的城市信息,并从CityResponse
中提取这些信息:
@Test
public void givenIP_whenFetchingCity_thenReturnsCityData()
throws IOException, GeoIp2Exception {
String ip = "your-ip-address";
String dbLocation = "your-path-to-mmdb";
File database = new File(dbLocation);
DatabaseReader dbReader = new DatabaseReader.Builder(database)
.build();
InetAddress ipAddress = InetAddress.getByName(ip);
CityResponse response = dbReader.city(ipAddress);
String countryName = response.getCountry().getName();
String cityName = response.getCity().getName();
String postal = response.getPostal().getCode();
String state = response.getLeastSpecificSubdivision().getName();
}
3. 在Web应用中使用GeoIP
接下来,我们来看一个示例Web应用,它从用户的公共IP地址获取地理位置数据并在地图上显示。
我们将从一个基本的Spring MVC应用开始。然后,我们编写一个Controller
,接受POST请求中的IP地址,并返回一个包含从GeoIP2 API推断出的城市、纬度和经度的JSON响应。
最后,我们将编写一些HTML和JavaScript代码,用于加载用户公共IP地址到表单中,通过Ajax POST请求发送到我们的Controller
,并在Google Maps上显示结果。
3.1. 响应实体类
首先,定义一个类来存储地理位置响应:
public class GeoIP {
private String ipAddress;
private String city;
private String latitude;
private String longitude;
// constructors, getters and setters...
}
3.2. 服务类
现在,编写一个服务类,使用GeoIP2 Java API和GeoLite2数据库获取地理位置数据:
public class RawDBDemoGeoIPLocationService {
private DatabaseReader dbReader;
public RawDBDemoGeoIPLocationService() throws IOException {
File database = new File("your-mmdb-location");
dbReader = new DatabaseReader.Builder(database).build();
}
public GeoIP getLocation(String ip)
throws IOException, GeoIp2Exception {
InetAddress ipAddress = InetAddress.getByName(ip);
CityResponse response = dbReader.city(ipAddress);
String cityName = response.getCity().getName();
String latitude =
response.getLocation().getLatitude().toString();
String longitude =
response.getLocation().getLongitude().toString();
return new GeoIP(ip, cityName, latitude, longitude);
}
}
3.3. Spring Controller
以下是Spring MVC的Controller
,它将发送名为"ipAddress"的请求参数到我们的服务类以获取地理位置响应数据:
@RestController
public class GeoIPTestController {
private RawDBDemoGeoIPLocationService locationService;
public GeoIPTestController() throws IOException {
locationService = new RawDBDemoGeoIPLocationService();
}
@PostMapping("/GeoIPTest")
public GeoIP getLocation(
@RequestParam(value="ipAddress", required=true) String ipAddress
) throws Exception {
GeoIPLocationService<String, GeoIP> locationService
= new RawDBDemoGeoIPLocationService();
return locationService.getLocation(ipAddress);
}
}
3.4. HTML表单
现在添加前端代码来调用我们的Spring Controller
,首先是一个包含IP地址的HTML表单:
<body>
<form id="ipForm" action="GeoIPTest" method="POST">
<input type="text" name = "ipAddress" id = "ip"/>
<input type="submit" name="submit" value="submit" />
</form>
...
</body>
3.5. 在客户端加载公共IP地址
接下来,使用jQuery和ipify.org JavaScript API预先填充"ipAddress"文本字段:
<script src
="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js">
</script>
<script type="text/javascript">
$(document).ready (function () {
$.get( "https://api.ipify.org?format=json",
function( data ) {
$("#ip").val(data.ip) ;
});
...
</script>
3.6. 提交Ajax POST请求
当表单提交时,我们将通过Ajax POST请求向Spring Controller
发送数据:
$( "#ipForm" ).submit(function( event ) {
event.preventDefault();
$.ajax({
url: "GeoIPTest",
type: "POST",
contentType:
"application/x-www-form-urlencoded; charset=UTF-8",
data: $.param( {ipAddress : $("#ip").val()} ),
complete: function(data) {},
success: function(data) {
$("#status").html(JSON.stringify(data));
if (data.ipAddress !=null) {
showLocationOnMap(data);
}
},
error: function(err) {
$("#status").html("Error:"+JSON.stringify(data));
},
});
});
3.7. 示例JSON响应
从Spring Controller
返回的JSON响应格式如下:
{
"ipAddress":"your-ip-address",
"city":"your-city",
"latitude":"your-latitude",
"longitude":"your-longitude"
}
3.8. 在Google Maps上显示位置
要在HTML中显示Google Maps,您需要在代码中包含Google Maps API:
<script src="https://maps.googleapis.com/maps/api/js?key=YOUR-API-KEY"
async defer></script>
您可以通过Google开发者控制台获取Google Maps API密钥。
还需要定义一个HTML <div>
标签来包含地图图像:
<div id="map" style="height: 500px; width:100%; position:absolute"></div>
您可以使用以下JavaScript函数在Google Maps上显示坐标:
function showLocationOnMap (location) {
var map;
map = new google.maps.Map(document.getElementById('map'), {
center: {
lat: Number(location.latitude),
lng: Number(location.longitude)},
zoom: 15
});
var marker = new google.maps.Marker({
position: {
lat: Number(location.latitude),
lng: Number(location.longitude)},
map: map,
title:
"Public IP:"+location.ipAddress
+" @ "+location.city
});
}
启动Web应用后,打开地图页面的URL:
http://localhost:8080/spring-mvc-xml/GeoIpTest.jsp
您将看到连接的公共IP地址被加载到文本框中:
请注意,GeoIP2和ipify都支持IPv4和IPv6地址。
当您提交表单时,您将看到包含与您的公共IP地址对应的城市、纬度和经度的JSON响应文本,下面是一张指向您位置的Google地图:
4. 结论
在这篇教程中,我们回顾了如何使用MaxMind GeoIP2 Java API和免费的GeoLite2 City数据库进行JUnit测试。
然后,我们构建了一个Spring MVC Controller
和服务,从IP地址获取地理位置(城市、纬度和经度)数据。
最后,我们构建了一个HTML/JavaScript前端,展示如何使用这个功能在Google Maps上显示用户的位置。
此产品包括由MaxMind创建的GeoLite2数据,可以从http://www.maxmind.com获取。
本教程的代码可以在GitHub网站上找到。